1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum DelegationAudience {
9 Canister(Principal),
10 CanicSubnet(Principal),
11 Project(String),
12}
13
14#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct DelegatedRoleGrant {
20 pub target: CanisterRole,
21 pub scopes: Vec<String>,
22}
23
24#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
29pub enum RootProof {
30 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
31}
32
33#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub enum IssuerProof {
39 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
40}
41
42#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
47pub struct IcCanisterSignatureProofV1 {
48 pub signature_cbor: Vec<u8>,
49 pub public_key_der: Vec<u8>,
50}
51
52#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub enum IssuerProofAlgorithm {
58 IcCanisterSignatureV1,
59}
60
61#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
66pub enum IssuerProofBinding {
67 IcCanisterSignatureV1 { seed_hash: [u8; 32] },
68}
69
70#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
75pub struct DelegationCert {
76 pub root_pid: Principal,
77 pub issuer_pid: Principal,
78 pub issuer_proof_alg: IssuerProofAlgorithm,
79 pub issuer_proof_binding_hash: [u8; 32],
80 pub issuer_proof_binding: IssuerProofBinding,
81 pub issuer_signer_generation: Option<u64>,
82 pub issued_at_ns: u64,
83 pub not_before_ns: u64,
84 pub expires_at_ns: u64,
85 pub max_token_ttl_ns: u64,
86 pub aud: DelegationAudience,
87 pub grants: Vec<DelegatedRoleGrant>,
88}
89
90#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
95pub struct DelegationProof {
96 pub cert: DelegationCert,
97 pub root_proof: RootProof,
98}
99
100#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
105pub struct ActiveDelegationProof {
106 pub proof: DelegationProof,
107 pub cert_hash: [u8; 32],
108 pub not_before_ns: u64,
109 pub expires_at_ns: u64,
110 pub refresh_after_ns: u64,
111 pub installed_at_ns: u64,
112 pub installed_by: Principal,
113}
114
115#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
120pub struct InstallActiveDelegationProofRequest {
121 pub proof: DelegationProof,
122}
123
124#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
129pub struct InstallActiveDelegationProofResponse {
130 pub active_proof: ActiveDelegationProof,
131}
132
133#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
138pub struct DelegatedTokenClaims {
139 pub subject: Principal,
140 pub issuer_pid: Principal,
141 pub cert_hash: [u8; 32],
142 pub issued_at_ns: u64,
143 pub expires_at_ns: u64,
144 pub aud: DelegationAudience,
145 pub grants: Vec<DelegatedRoleGrant>,
146 pub nonce: [u8; 16],
147 #[serde(default)]
148 pub ext: Option<Vec<u8>>,
149}
150
151#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
156pub struct DelegatedToken {
157 pub claims: DelegatedTokenClaims,
158 pub proof: DelegationProof,
159 pub issuer_proof: IssuerProof,
160}
161
162#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
167pub struct AuthRequestMetadata {
168 pub request_id: [u8; 32],
169 pub ttl_ns: u64,
170}
171
172#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
177pub struct DelegationProofIssueRequest {
178 #[serde(default)]
179 pub metadata: Option<AuthRequestMetadata>,
180 pub issuer_pid: Principal,
181 pub aud: DelegationAudience,
182 pub grants: Vec<DelegatedRoleGrant>,
183 pub cert_ttl_ns: u64,
184}
185
186#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
191pub struct DelegationProofPrepareResponse {
192 pub cert: DelegationCert,
193 pub cert_hash: [u8; 32],
194 pub retrieval_expires_at_ns: u64,
195}
196
197#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
202pub struct DelegationProofGetRequest {
203 pub cert_hash: [u8; 32],
204}
205
206#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
211pub struct DelegatedTokenPrepareRequest {
212 #[serde(default)]
213 pub metadata: Option<AuthRequestMetadata>,
214 pub subject: Principal,
215 pub aud: DelegationAudience,
216 pub grants: Vec<DelegatedRoleGrant>,
217 pub ttl_ns: u64,
218 pub nonce: [u8; 16],
219 #[serde(default)]
220 pub ext: Option<Vec<u8>>,
221}
222
223#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
228pub struct DelegatedTokenPrepareResponse {
229 pub claims: DelegatedTokenClaims,
230 pub claims_hash: [u8; 32],
231 pub retrieval_expires_at_ns: u64,
232}
233
234#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
239pub struct DelegatedTokenGetRequest {
240 pub claims_hash: [u8; 32],
241}
242
243#[derive(CandidType, Clone, Debug, Deserialize)]
248pub struct RoleAttestationRequest {
249 pub subject: Principal,
250 pub role: CanisterRole,
251 #[serde(default)]
252 pub subnet_id: Option<Principal>,
253 pub audience: Principal,
254 pub ttl_ns: u64,
255 pub epoch: u64,
256 #[serde(default)]
257 pub metadata: Option<RootRequestMetadata>,
258}
259
260#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
265pub struct RoleAttestation {
266 pub subject: Principal,
267 pub role: CanisterRole,
268 #[serde(default)]
269 pub subnet_id: Option<Principal>,
270 pub audience: Principal,
271 pub issued_at_ns: u64,
272 pub expires_at_ns: u64,
273 pub epoch: u64,
274}
275
276#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
281pub struct RoleAttestationPrepareResponse {
282 pub payload: RoleAttestation,
283 pub payload_hash: [u8; 32],
284 pub retrieval_expires_at_ns: u64,
285}
286
287#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
292pub struct RoleAttestationGetRequest {
293 pub payload_hash: [u8; 32],
294}
295
296#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
301pub struct SignedRoleAttestation {
302 pub payload: RoleAttestation,
303 pub root_proof: RootProof,
304}
305
306#[cfg(test)]
307mod tests {
308 #[test]
309 fn auth_dtos_remain_passive_boundary_types() {
310 let source = include_str!("auth.rs");
311 let production_source = source
312 .split("#[cfg(test)]")
313 .next()
314 .expect("production source exists");
315
316 for marker in [
317 "impl DelegatedToken",
318 "impl DelegatedTokenClaims",
319 "impl RoleAttestation",
320 "impl SignedRoleAttestation",
321 "fn verify",
322 "fn sign",
323 "fn resolve",
324 "fn replay",
325 "fn consume",
326 "fn policy",
327 "fn validate",
328 ] {
329 assert!(
330 !production_source.contains(marker),
331 "auth DTOs must stay passive; found marker `{marker}`"
332 );
333 }
334 }
335}