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 application-defined extension payload.
171    ///
172    /// SECURITY:
173    /// ---------
174    /// - This field is covered by the token signature.
175    /// - Canic does NOT interpret this field.
176    /// - Semantics are defined entirely by the application.
177    ///
178    /// INTENDED USE:
179    /// -------------
180    /// - Application identity (e.g. user_id)
181    /// - Role snapshots
182    /// - Authorization context
183    ///
184    /// This enables stateless application authentication across
185    /// arbitrary canisters without database lookups.
186    #[serde(default)]
187    pub ext: Option<Vec<u8>>,
188
189    /// Optional nonce for replay protection or correlation.
190    ///
191    /// Semantics are intentionally undefined at this layer.
192    /// Consumers may use it for replay detection or tracing.
193    pub nonce: Option<Vec<u8>>,
194}
195
196///
197/// DelegatedToken
198///
199/// A signed authorization token issued by a delegated signer.
200///
201/// Verification steps (normative):
202/// 1. Validate token version.
203/// 2. Verify the root signature on the delegation certificate.
204/// 3. Validate time bounds and scope/audience constraints.
205/// 4. Verify the token signature using the signer canister.
206///
207/// Design constraints:
208/// - No directory or registry lookup is required.
209/// - No topology or environment inspection is required.
210/// - All verification is local and deterministic.
211///
212#[derive(CandidType, Clone, Debug, Deserialize, Serialize)]
213pub struct DelegatedToken {
214    /// Version of the delegated token format.
215    ///
216    /// Allows format evolution without ambiguity.
217    pub v: u16,
218
219    /// Claims asserted by the signer.
220    pub claims: DelegatedTokenClaims,
221
222    /// Delegation proof binding signer authority to root trust.
223    pub proof: DelegationProof,
224
225    /// Signature over canonicalized claims and delegation hash.
226    ///
227    /// Produced by the delegated signer canister.
228    pub token_sig: Vec<u8>,
229}
230
231///
232/// DelegationAdminCommand
233///
234/// Administrative commands for managing delegation rotation.
235///
236/// These commands are expected to be root-authorized and are
237/// intentionally narrow in scope.
238///
239#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
240pub enum DelegationAdminCommand {
241    /// Start periodic delegation rotation.
242    ///
243    /// `interval_secs` defines how frequently new certificates are issued.
244    StartRotation { interval_secs: u64 },
245
246    /// Stop delegation rotation.
247    StopRotation,
248}
249
250///
251/// DelegationAdminResponse
252///
253/// Result of executing a delegation admin command.
254///
255#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
256pub enum DelegationAdminResponse {
257    RotationStarted,
258    RotationAlreadyRunning,
259    RotationStopped,
260    RotationNotRunning,
261}