canic_core/dto/
auth.rs

1//! Delegated signing DTOs.
2//!
3//! These types define the **data model and trust boundaries** for delegated
4//! authorization using **IC canister signatures only**.
5//!
6//! High-level design:
7//! - A single root authority canister is the trust anchor.
8//! - The root delegates signing authority to signer canisters via certificates.
9//! - Signer canisters issue authorization tokens.
10//! - Tokens are verified **locally** with no directory, registry, or topology calls.
11//!
12//! This model enables:
13//! - Offline / deterministic verification
14//! - No runtime dependency on external canisters
15//! - Clear, auditable trust chains
16//!
17//! Any change to these structures is **security-sensitive** and must be
18//! evaluated against the trust model below.
19
20use crate::dto::prelude::*;
21
22/// ---------------------------------------------------------------------------
23/// Trust model summary
24/// ---------------------------------------------------------------------------
25///
26/// - The **root authority canister** is the only long-term trust anchor.
27/// - The root signs `DelegationCert` objects using IC canister signatures.
28/// - A `DelegationCert` grants limited signing authority to a signer canister.
29/// - Signer canisters sign `DelegatedToken` objects.
30/// - Verifiers trust a token **only if**:
31///     - The delegation certificate is root-signed
32///     - The token signature matches the delegated signer
33///     - All temporal, scope, and audience constraints hold
34///
35/// No canister calls occur during verification.
36/// All trust is established cryptographically.
37///
38/// ---------------------------------------------------------------------------
39
40///
41/// DelegationCert
42///
43/// A root-signed certificate that delegates token-signing authority
44/// to a signer canister.
45///
46/// WHY THIS EXISTS
47/// ----------------
48/// This is the *only* object signed by the root authority canister.
49/// It is the **trust anchor** for all delegated tokens.
50///
51/// If this object is valid and trusted:
52/// - The signer canister is authorized to issue tokens
53/// - But *only* within the audiences, scopes, and lifetime specified here
54///
55/// Anything not explicitly allowed here is forbidden.
56///
57#[derive(CandidType, Clone, Debug, Deserialize, Serialize)]
58pub struct DelegationCert {
59    /// Version of the delegation certificate format.
60    ///
61    /// WHY:
62    /// - Allows forward-compatible evolution of fields and semantics
63    /// - Prevents silent misinterpretation during upgrades
64    pub v: u16,
65
66    /// Principal of the delegated signer canister.
67    ///
68    /// Tokens must be signed by this canister.
69    /// No other signer is valid under this certificate.
70    pub signer_pid: Principal,
71
72    /// Audiences the delegated signer is allowed to issue tokens for.
73    ///
74    /// Token `claims.aud` MUST be a member of this set.
75    /// This prevents a signer from issuing tokens for unrelated services.
76    pub audiences: Vec<String>,
77
78    /// Scopes the delegated signer is allowed to assert.
79    ///
80    /// Token `claims.scopes` MUST be a subset of this set.
81    /// This ensures least-privilege delegation.
82    pub scopes: Vec<String>,
83
84    /// Time (seconds since epoch) when this delegation was issued.
85    ///
86    /// Used for auditing and temporal validation.
87    pub issued_at: u64,
88
89    /// Absolute expiration time of this delegation.
90    ///
91    /// Tokens MUST NOT outlive this value, regardless of token TTL.
92    /// Rotation invalidates all tokens bound to an expired certificate.
93    pub expires_at: u64,
94}
95
96///
97/// DelegationProof
98///
99/// Cryptographic proof that a `DelegationCert` was authorized by the root.
100///
101/// WHY THIS EXISTS
102/// ----------------
103/// The `DelegationCert` alone is just data.
104/// This struct binds it to a **root canister signature**, establishing
105/// a verifiable trust chain:
106///
107/// root authority -> signer canister
108///
109/// Verifiers validate `cert_sig` using:
110/// - the root authority’s public key
111/// - a fixed domain separator
112///
113#[derive(CandidType, Clone, Debug, Deserialize, Serialize)]
114pub struct DelegationProof {
115    /// The delegated certificate describing signer authority.
116    pub cert: DelegationCert,
117
118    /// Root authority signature over the DelegationCert hash.
119    ///
120    /// This signature:
121    /// - Authenticates the certificate
122    /// - Prevents forgery or tampering
123    /// - Anchors the delegation chain
124    pub cert_sig: Vec<u8>,
125}
126
127///
128/// DelegatedTokenClaims
129///
130/// Claims asserted by a delegated signer.
131///
132/// IMPORTANT:
133/// -----------
134/// All fields in this struct are **untrusted input** until:
135/// - the delegation proof is verified
136/// - the token signature is verified
137///
138/// Authorization derives from *both* the claims AND the delegation.
139/// Claims alone are never sufficient.
140///
141#[derive(CandidType, Clone, Debug, Deserialize, Serialize)]
142pub struct DelegatedTokenClaims {
143    /// Subject of the token (e.g. user principal).
144    pub sub: Principal,
145
146    /// Intended audience of the token.
147    ///
148    /// MUST match one of `DelegationCert.audiences`.
149    /// This prevents cross-service token reuse.
150    pub aud: String,
151
152    /// Scopes asserted by this token.
153    ///
154    /// MUST be a subset of `DelegationCert.scopes`.
155    /// The signer cannot exceed delegated authority.
156    pub scopes: Vec<String>,
157
158    /// Issued-at timestamp.
159    ///
160    /// Used to enforce token freshness and TTL constraints.
161    pub iat: u64,
162
163    /// Expiration timestamp.
164    ///
165    /// MUST be:
166    /// - >= iat
167    /// - <= DelegationCert.expires_at
168    pub exp: u64,
169
170    /// Optional nonce for replay protection or correlation.
171    ///
172    /// Semantics are intentionally undefined at this layer.
173    /// Consumers may use it for replay detection or tracing.
174    pub nonce: Option<Vec<u8>>,
175}
176
177///
178/// DelegatedToken
179///
180/// A signed authorization token issued by a delegated signer.
181///
182/// Verification steps (normative):
183/// 1. Validate token version.
184/// 2. Verify the root signature on the delegation certificate.
185/// 3. Validate time bounds and scope/audience constraints.
186/// 4. Verify the token signature using the signer canister.
187///
188/// Design constraints:
189/// - No directory or registry lookup is required.
190/// - No topology or environment inspection is required.
191/// - All verification is local and deterministic.
192///
193#[derive(CandidType, Clone, Debug, Deserialize, Serialize)]
194pub struct DelegatedToken {
195    /// Version of the delegated token format.
196    ///
197    /// Allows format evolution without ambiguity.
198    pub v: u16,
199
200    /// Claims asserted by the signer.
201    pub claims: DelegatedTokenClaims,
202
203    /// Delegation proof binding signer authority to root trust.
204    pub proof: DelegationProof,
205
206    /// Signature over canonicalized claims and delegation hash.
207    ///
208    /// Produced by the delegated signer canister.
209    pub token_sig: Vec<u8>,
210}
211
212///
213/// DelegationAdminCommand
214///
215/// Administrative commands for managing delegation rotation.
216///
217/// These commands are expected to be root-authorized and are
218/// intentionally narrow in scope.
219///
220#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
221pub enum DelegationAdminCommand {
222    /// Start periodic delegation rotation.
223    ///
224    /// `interval_secs` defines how frequently new certificates are issued.
225    StartRotation { interval_secs: u64 },
226
227    /// Stop delegation rotation.
228    StopRotation,
229}
230
231///
232/// DelegationAdminResponse
233///
234/// Result of executing a delegation admin command.
235///
236#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
237pub enum DelegationAdminResponse {
238    RotationStarted,
239    RotationAlreadyRunning,
240    RotationStopped,
241    RotationNotRunning,
242}