Skip to main content

canic_core/dto/
auth.rs

1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3//
4// DelegationAudience
5//
6
7#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum DelegationAudience {
9    Canister(Principal),
10    CanicSubnet(Principal),
11    Project(String),
12}
13
14//
15// DelegatedRoleGrant
16//
17
18#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct DelegatedRoleGrant {
20    pub target: CanisterRole,
21    pub scopes: Vec<String>,
22}
23
24//
25// RootProof
26//
27
28#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
29pub enum RootProof {
30    IcCanisterSignatureV1(IcCanisterSignatureProofV1),
31}
32
33//
34// IssuerProof
35//
36
37#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub enum IssuerProof {
39    IcCanisterSignatureV1(IcCanisterSignatureProofV1),
40}
41
42//
43// IcCanisterSignatureProofV1
44//
45
46#[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//
53// IssuerProofAlgorithm
54//
55
56#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub enum IssuerProofAlgorithm {
58    IcCanisterSignatureV1,
59}
60
61//
62// IssuerProofBinding
63//
64
65#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
66pub enum IssuerProofBinding {
67    IcCanisterSignatureV1 { seed_hash: [u8; 32] },
68}
69
70//
71// DelegationCert
72//
73
74#[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//
90// DelegationProof
91//
92
93#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94pub struct DelegationProof {
95    pub cert: DelegationCert,
96    pub root_proof: RootProof,
97}
98
99//
100// ActiveDelegationProof
101//
102
103#[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//
115// InstallActiveDelegationProofRequest
116//
117
118#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct InstallActiveDelegationProofRequest {
120    pub proof: DelegationProof,
121}
122
123//
124// InstallActiveDelegationProofResponse
125//
126
127#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
128pub struct InstallActiveDelegationProofResponse {
129    pub active_proof: ActiveDelegationProof,
130}
131
132//
133// DelegatedTokenClaims
134//
135
136#[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//
151// DelegatedToken
152//
153
154#[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//
162// AuthRequestMetadata
163//
164
165#[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//
172// DelegationProofIssueRequest
173//
174
175#[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//
186// DelegationProofPrepareResponse
187//
188
189#[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//
197// DelegationProofGetRequest
198//
199
200#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
201pub struct DelegationProofGetRequest {
202    pub cert_hash: [u8; 32],
203}
204
205//
206// DelegatedTokenPrepareRequest
207//
208
209#[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//
222// DelegatedTokenPrepareResponse
223//
224
225#[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//
233// DelegatedTokenGetRequest
234//
235
236#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
237pub struct DelegatedTokenGetRequest {
238    pub claims_hash: [u8; 32],
239}
240
241//
242// RoleAttestationRequest
243//
244
245#[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//
259// RoleAttestation
260//
261
262#[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//
275// RoleAttestationPrepareResponse
276//
277
278#[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//
286// RoleAttestationGetRequest
287//
288
289#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
290pub struct RoleAttestationGetRequest {
291    pub payload_hash: [u8; 32],
292}
293
294//
295// SignedRoleAttestation
296//
297
298#[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}