Skip to main content

ic_auth_wire/
lib.rs

1//! Controlled portable-session transport. No endpoint installation, authority,
2//! cryptography, session storage or delivery/retry policy is supplied here.
3pub mod model;
4use ic_auth_protocol_types::limits::{MAX_LABEL_BYTES, MAX_SESSION_SCOPES};
5pub use ic_wire as wire;
6use ic_wire::{Limits, List, Text};
7use model::{LogoutResult, PortableCredential};
8
9/// Default browser retention cap for a complete credential frame. Larger
10/// certified envelopes require an explicitly selected client cap; Wire's own
11/// frame/field budgets continue to apply. Refusal is client `invalid_material`.
12pub const BROWSER_DEFAULT_CREDENTIAL_BYTES: usize = 131_072;
13/// Maximum configurable browser retention cap, not an override of Wire limits.
14/// Preserves the client option range; actual frames remain bounded by the codec.
15pub const BROWSER_MAX_CONFIGURED_CREDENTIAL_BYTES: usize = 1_048_576;
16/// Browser logout response frame cap. All current reply variants fit; extensions
17/// must review this intentionally narrower policy than the shared reply budget.
18pub const BROWSER_LOGOUT_RESPONSE_BYTES: usize = 1024;
19
20/// Admission narrowing accompanies the exact opaque signed credential.
21#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
22#[cfg_attr(feature = "typescript", derive(ic_wire::Wire))]
23pub struct SessionInput {
24    pub credential: PortableCredential,
25    pub scopes: List<Text<MAX_LABEL_BYTES>, MAX_SESSION_SCOPES>,
26    pub ttl_secs: Option<u64>,
27}
28/// A receiver's authenticated local reply, never a transferable authorization.
29#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
30#[cfg_attr(feature = "typescript", derive(ic_wire::Wire))]
31pub struct SessionView {
32    pub caller: ic_wire::Bytes<29>,
33    pub issuer: ic_wire::Bytes<29>,
34    pub subject: ic_wire::Bytes<29>,
35    pub expires_at_ns: u64,
36}
37const CREDENTIAL_LIMITS: Limits = Limits {
38    bytes: 524288,
39    allocation: 2097152,
40    nodes: 65536,
41    depth: 32,
42};
43const REPLY_LIMITS: Limits = Limits {
44    bytes: 4096,
45    allocation: 16384,
46    nodes: 128,
47    depth: 8,
48};
49const EMPTY_LIMITS: Limits = Limits {
50    bytes: 11,
51    allocation: 128,
52    nodes: 8,
53    depth: 4,
54};
55
56// Keep method identities and limits explicit; only the four native codec
57// forwarders are mechanical. This macro is private and emits the existing API.
58macro_rules! codecs {
59    ($request:ty, $response:ty) => {
60        pub fn encode_request(value: &$request) -> Result<Vec<u8>, ic_wire::Error> {
61            ic_wire::native::encode_request(Self::ID, value, Self::REQUEST_LIMITS)
62        }
63        pub fn decode_request(bytes: &[u8]) -> Result<$request, ic_wire::Error> {
64            ic_wire::native::decode_request(Self::ID, bytes, Self::REQUEST_LIMITS)
65        }
66        pub fn encode_response(value: &$response) -> Result<Vec<u8>, ic_wire::Error> {
67            ic_wire::native::encode_response(Self::ID, value, Self::RESPONSE_LIMITS)
68        }
69        pub fn decode_response(bytes: &[u8]) -> Result<$response, ic_wire::Error> {
70            ic_wire::native::decode_response(Self::ID, bytes, Self::RESPONSE_LIMITS)
71        }
72    };
73}
74
75/// Data-envelope identity, not a callable issuer method or signing format.
76pub struct CredentialEnvelope;
77impl CredentialEnvelope {
78    pub const ID: u64 = 0x415554480001;
79    pub const NAME: &'static str = "credential";
80    pub const REQUEST_LIMITS: Limits = CREDENTIAL_LIMITS;
81    pub const RESPONSE_LIMITS: Limits = CREDENTIAL_LIMITS;
82    codecs!(PortableCredential, PortableCredential);
83}
84/// Controlled admission contract; consumers bind it to their own update export.
85pub struct EstablishSession;
86impl EstablishSession {
87    pub const ID: u64 = 0x415554480012;
88    pub const NAME: &'static str = "establish_portable_session";
89    pub const REQUEST_LIMITS: Limits = CREDENTIAL_LIMITS;
90    pub const RESPONSE_LIMITS: Limits = REPLY_LIMITS;
91    codecs!(SessionInput, Result<SessionView, model::AdmissionRefusal>);
92}
93/// Proof-free local read contract; the runtime caller selects the session.
94pub struct ReadSession;
95impl ReadSession {
96    pub const ID: u64 = 0x415554480003;
97    pub const NAME: &'static str = "portable_session_read";
98    pub const REQUEST_LIMITS: Limits = EMPTY_LIMITS;
99    pub const RESPONSE_LIMITS: Limits = REPLY_LIMITS;
100    codecs!((), Result<SessionView, Text<256>>);
101}
102/// Caller-authenticated logout; no submitted proof or caller identity is trusted.
103pub struct Logout;
104impl Logout {
105    pub const ID: u64 = 0x415554480004;
106    pub const NAME: &'static str = "logout_portable_session";
107    pub const REQUEST_LIMITS: Limits = EMPTY_LIMITS;
108    pub const RESPONSE_LIMITS: Limits = REPLY_LIMITS;
109    codecs!((), LogoutResult);
110}