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 issued_at_ns: u64,
82 pub not_before_ns: u64,
83 pub expires_at_ns: u64,
84 pub max_token_ttl_ns: u64,
85 pub aud: DelegationAudience,
86 pub grants: Vec<DelegatedRoleGrant>,
87}
88
89#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94pub struct DelegationProof {
95 pub cert: DelegationCert,
96 pub root_proof: RootProof,
97}
98
99#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
104pub struct ActiveDelegationProof {
105 pub proof: DelegationProof,
106 pub cert_hash: [u8; 32],
107 pub not_before_ns: u64,
108 pub expires_at_ns: u64,
109 pub refresh_after_ns: u64,
110 pub installed_at_ns: u64,
111 pub installed_by: Principal,
112}
113
114#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct InstallActiveDelegationProofRequest {
120 pub proof: DelegationProof,
121}
122
123#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
128pub struct InstallActiveDelegationProofResponse {
129 pub active_proof: ActiveDelegationProof,
130}
131
132#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
137pub struct DelegatedTokenClaims {
138 pub subject: Principal,
139 pub issuer_pid: Principal,
140 pub cert_hash: [u8; 32],
141 pub issued_at_ns: u64,
142 pub expires_at_ns: u64,
143 pub aud: DelegationAudience,
144 pub grants: Vec<DelegatedRoleGrant>,
145 pub nonce: [u8; 16],
146 #[serde(default)]
147 pub ext: Option<Vec<u8>>,
148}
149
150#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
155pub struct DelegatedToken {
156 pub claims: DelegatedTokenClaims,
157 pub proof: DelegationProof,
158 pub issuer_proof: IssuerProof,
159}
160
161#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
166pub struct AuthRequestMetadata {
167 pub request_id: [u8; 32],
168 pub ttl_ns: u64,
169}
170
171#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
176pub struct DelegationProofIssueRequest {
177 #[serde(default)]
178 pub metadata: Option<AuthRequestMetadata>,
179 pub issuer_pid: Principal,
180 pub aud: DelegationAudience,
181 pub grants: Vec<DelegatedRoleGrant>,
182 pub cert_ttl_ns: u64,
183}
184
185#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
190pub struct DelegationProofPrepareResponse {
191 pub cert: DelegationCert,
192 pub cert_hash: [u8; 32],
193 pub retrieval_expires_at_ns: u64,
194}
195
196#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
201pub struct DelegationProofGetRequest {
202 pub cert_hash: [u8; 32],
203}
204
205#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
210pub struct DelegatedTokenPrepareRequest {
211 #[serde(default)]
212 pub metadata: Option<AuthRequestMetadata>,
213 pub subject: Principal,
214 pub aud: DelegationAudience,
215 pub grants: Vec<DelegatedRoleGrant>,
216 pub ttl_ns: u64,
217 #[serde(default)]
218 pub ext: Option<Vec<u8>>,
219}
220
221#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
226pub struct DelegatedTokenPrepareResponse {
227 pub claims: DelegatedTokenClaims,
228 pub claims_hash: [u8; 32],
229 pub retrieval_expires_at_ns: u64,
230}
231
232#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
237pub struct DelegatedTokenGetRequest {
238 pub claims_hash: [u8; 32],
239}
240
241#[derive(CandidType, Clone, Debug, Deserialize)]
246pub struct RoleAttestationRequest {
247 pub subject: Principal,
248 pub role: CanisterRole,
249 #[serde(default)]
250 pub subnet_id: Option<Principal>,
251 pub audience: Principal,
252 pub ttl_ns: u64,
253 pub epoch: u64,
254 #[serde(default)]
255 pub metadata: Option<RootRequestMetadata>,
256}
257
258#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
263pub struct RoleAttestation {
264 pub subject: Principal,
265 pub role: CanisterRole,
266 #[serde(default)]
267 pub subnet_id: Option<Principal>,
268 pub audience: Principal,
269 pub issued_at_ns: u64,
270 pub expires_at_ns: u64,
271 pub epoch: u64,
272}
273
274#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
279pub struct RoleAttestationPrepareResponse {
280 pub payload: RoleAttestation,
281 pub payload_hash: [u8; 32],
282 pub retrieval_expires_at_ns: u64,
283}
284
285#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
290pub struct RoleAttestationGetRequest {
291 pub payload_hash: [u8; 32],
292}
293
294#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
299pub struct SignedRoleAttestation {
300 pub payload: RoleAttestation,
301 pub root_proof: RootProof,
302}
303
304#[cfg(test)]
305mod tests {
306 #[test]
307 fn auth_dtos_remain_passive_boundary_types() {
308 let source = include_str!("auth.rs");
309 let production_source = source
310 .split("#[cfg(test)]")
311 .next()
312 .expect("production source exists");
313
314 for marker in [
315 "impl DelegatedToken",
316 "impl DelegatedTokenClaims",
317 "impl RoleAttestation",
318 "impl SignedRoleAttestation",
319 "fn verify",
320 "fn sign",
321 "fn resolve",
322 "fn replay",
323 "fn consume",
324 "fn policy",
325 "fn validate",
326 ] {
327 assert!(
328 !production_source.contains(marker),
329 "auth DTOs must stay passive; found marker `{marker}`"
330 );
331 }
332 }
333}