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 #[serde(default)]
219 pub ext: Option<Vec<u8>>,
220}
221
222#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
227pub struct DelegatedTokenPrepareResponse {
228 pub claims: DelegatedTokenClaims,
229 pub claims_hash: [u8; 32],
230 pub retrieval_expires_at_ns: u64,
231}
232
233#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
238pub struct DelegatedTokenGetRequest {
239 pub claims_hash: [u8; 32],
240}
241
242#[derive(CandidType, Clone, Debug, Deserialize)]
247pub struct RoleAttestationRequest {
248 pub subject: Principal,
249 pub role: CanisterRole,
250 #[serde(default)]
251 pub subnet_id: Option<Principal>,
252 pub audience: Principal,
253 pub ttl_ns: u64,
254 pub epoch: u64,
255 #[serde(default)]
256 pub metadata: Option<RootRequestMetadata>,
257}
258
259#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
264pub struct RoleAttestation {
265 pub subject: Principal,
266 pub role: CanisterRole,
267 #[serde(default)]
268 pub subnet_id: Option<Principal>,
269 pub audience: Principal,
270 pub issued_at_ns: u64,
271 pub expires_at_ns: u64,
272 pub epoch: u64,
273}
274
275#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
280pub struct RoleAttestationPrepareResponse {
281 pub payload: RoleAttestation,
282 pub payload_hash: [u8; 32],
283 pub retrieval_expires_at_ns: u64,
284}
285
286#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
291pub struct RoleAttestationGetRequest {
292 pub payload_hash: [u8; 32],
293}
294
295#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
300pub struct SignedRoleAttestation {
301 pub payload: RoleAttestation,
302 pub root_proof: RootProof,
303}
304
305#[cfg(test)]
306mod tests {
307 #[test]
308 fn auth_dtos_remain_passive_boundary_types() {
309 let source = include_str!("auth.rs");
310 let production_source = source
311 .split("#[cfg(test)]")
312 .next()
313 .expect("production source exists");
314
315 for marker in [
316 "impl DelegatedToken",
317 "impl DelegatedTokenClaims",
318 "impl RoleAttestation",
319 "impl SignedRoleAttestation",
320 "fn verify",
321 "fn sign",
322 "fn resolve",
323 "fn replay",
324 "fn consume",
325 "fn policy",
326 "fn validate",
327 ] {
328 assert!(
329 !production_source.contains(marker),
330 "auth DTOs must stay passive; found marker `{marker}`"
331 );
332 }
333 }
334}