Skip to main content

AuthApi

Struct AuthApi 

Source
pub struct AuthApi { /* private fields */ }
Expand description

User registration and OTP authentication

Implementations§

Source§

impl AuthApi

Source

pub async fn apple_native_auth( &self, body: &AppleNativeAuthRequest, ) -> Result<AppleNativeAuthResponse>

Sign in with Apple — native iOS handshake

iOS drives the Apple authorization sheet via ASAuthorizationController and POSTs the resulting identity_token (Apple-signed JWT, RS256) here. Server fetches Apple JWKS (cached 24h), verifies signature/iss/aud/exp, extracts sub + email, then mints a session. The email is only present on first login — subsequent logins reuse the stored apple_sub_to_email mapping. is_private_email (@privaterelay.appleid.com) is honoured: relay address is stored as the canonical email.

POST /api/v1/auth/oauth/apple/native

Source

pub async fn complete_o_auth_login( &self, provider: &OAuthLoginProviderConfigStatusProvider, params: &CompleteOAuthLoginParams, ) -> Result<CompleteOAuthLoginResponse>

OAuth callback — exchange code, mint session

Provider redirects here. Server validates state (one-shot, 10 min TTL, provider-bound), exchanges code for tokens, fetches verified email + IdP sub, then mints a session via the shared post-verify path. On success: 302 to ${return_to}#api_key=...&email=... if a return_to was stored, else JSON {api_key, email}. Refuses to mint for super-admin email (Guideline-style separation: super-admin must use OTP).

GET /api/v1/auth/oauth/{provider}/callback

Source

pub async fn disable_mfa(&self) -> Result<DisableMfaResponse>

Remove MFA enrolment for the calling user

POST /api/v1/auth/mfa/disable

Source

pub async fn enrol_mfa(&self, body: &EnrolMfaRequest) -> Result<MfaEnrolment>

Begin MFA enrolment

Returns the TOTP secret (otpauth URL + base32 secret) and one-time recovery codes. Recovery codes are shown ONCE and never re-readable; user must store them. Optional body: { label?, issuer?, algorithm? }.

POST /api/v1/auth/mfa/enrol

Source

pub async fn exchange_o_auth_app_code( &self, body: &OAuthAppExchangeRequest, ) -> Result<OAuthAppExchangeResponse>

Trade a mobile hand-off code for the session

Second half of the mobile sign-in hand-off. When start is called with app_code_challenge, the callback redirects to the app with #code= instead of #api_key=, and the key is only released here, to a caller that presents the matching verifier. Single-use and short-lived: the code is consumed on the first attempt, successful or not.

POST /api/v1/auth/oauth/exchange

Source

pub async fn get_me(&self) -> Result<GetMeResponse>

Get the calling user + tenant context

Single source of truth for the browser to render account state, role badges, and the tenant header. Resolves the user via api-key.user_id, then JWT sub claim, then tenant_primary_email lookup.

Read role from the top level, never from user.role. The top-level field is required and always present; it resolves as user?.role ?? extractRole(auth), so it answers for every caller. user is nullable and NOT required — it is null whenever the caller authenticated with an api key rather than a signed-in session, and the nested role exists only in the other case.

Spelled out because the schema alone did not prevent it: two mobile clients independently modelled the response as {user, tenant}, read user.role, and so could not tell an owner from a viewer for any key-authed caller — one of them had gated no settings on role at all as a result. A client tested only against a JWT session sees user.role work perfectly and ships. scopes and auth_method are required for the same reason and answer for every caller too.

GET /api/v1/me

Source

pub async fn get_mfa_status(&self) -> Result<GetMfaStatusResponse>

MFA enrolment status for the calling user

GET /api/v1/auth/mfa/status

Source

pub async fn google_one_tap_auth( &self, body: &GoogleOneTapAuthRequest, ) -> Result<GoogleOneTapAuthResponse>

Sign in with Google — One Tap (FedCM) credential exchange

The browser-side Google Identity Services (GSI) script renders a FedCM One Tap prompt on /login and POSTs the resulting credential (a Google-signed JWT, RS256) here. Server fetches Google JWKS (cached 24h), verifies signature/iss/aud/exp against the configured Google OAuth client_id from admin KV, extracts sub + email, then mints a session via the shared post-verify path. Same session shape the /oauth/google/callback redirect flow returns.

POST /api/v1/auth/oauth/google/onetap

Source

pub async fn list_auth_providers(&self) -> Result<ListAuthProvidersResponse>

List linked OAuth identity providers + OTP fallback

Returns one entry per supported login method (otp, github, google, apple) with linked: true|false. Used by the Settings UI to render link/unlink buttons.

GET /api/v1/me/auth-providers

Source

pub async fn list_me_sessions(&self) -> Result<ListMeSessionsResponse>

List active api_keys (devices) for the calling user

Returns the user’s active api_keys across all devices (browser, iOS, CLI). is_current flags the key making this call so UI can highlight ‘this device’. Sorted by last_used_at desc.

GET /api/v1/me/sessions

Source

pub async fn list_o_auth_login_providers( &self, ) -> Result<OAuthLoginProvidersList>

List OAuth identity providers (for login UI)

Public, IP-rate-limited (60/min). Returns the list of configured OAuth login providers with their enabled status — UI uses this to render only the buttons that will work. apple is always advertised as enabled (App Store Guideline 4.8 placement requirement); github/google enabled depends on whether super-admin has provisioned client_id+client_secret.

GET /api/v1/auth/oauth/providers

Source

pub async fn logout(&self) -> Result<LogoutResponse>

Revoke the calling api_key

Revokes the api_key used to make this call. Idempotent — re-call returns 200 with already_revoked: true. Cookie/JWT-only sessions return {ok: true, key_id: null} since there’s no server-side key to revoke.

POST /api/v1/auth/logout

Source

pub async fn mint_sse_token(&self) -> Result<MintSSETokenResponse>

Mint a 60-second SSE token scoped to events:read

Mints a short-lived (60 s) API key carrying only events:read scope, for use as the ?token= query param on browser SSE/WebSocket subscriptions which cannot set Authorization headers. Token does not appear in the tenant key dashboard and auto-purges from KV.

POST /api/v1/auth/sse-tokens

Source

pub async fn register( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Register new user

POST /api/v1/register

Source

pub async fn request_otp_code( &self, body: &Map<String, Value>, ) -> Result<Map<String, Value>>

Request OTP code

POST /api/v1/auth/request-code

Source

pub async fn revoke_me_session( &self, key_id: &str, ) -> Result<RevokeMeSessionResponse>

Revoke a specific device session

Revokes one of the user’s api_keys. Refuses to revoke another user’s key (403). Idempotent — re-revoking a revoked key returns {ok: true, already_revoked: true}.

DELETE /api/v1/me/sessions/{keyId}

Source

pub async fn start_o_auth_login( &self, provider: &OAuthLoginProviderConfigStatusProvider, params: &StartOAuthLoginParams, ) -> Result<Value>

Begin browser OAuth login (302 to provider)

Redirects the browser to GitHub/Google authorize URL. Server stores a one-shot state record (10 min TTL) keyed by the state query the provider will echo back. PKCE codeVerifier is generated server-side. return_to defaults to nothing (response is JSON); when set, must satisfy the allow-list (same-origin paths, configured Universal-Link hosts, or snaga://). device_label is captured here and surfaces on the minted api_key for /me/sessions.

GET /api/v1/auth/oauth/{provider}/start

Unlink an OAuth provider from the user

Refuses to drop the user’s last sign-in factor (counts other linked providers + OTP recovery email). Idempotent — unlinking an already-unlinked provider returns 200 with already_unlinked: true.

DELETE /api/v1/me/auth-providers/{provider}

Source

pub async fn verify_email(&self) -> Result<Map<String, Value>>

Verify email link

GET /api/v1/verify-email

Source

pub async fn verify_mfa( &self, body: &VerifyMfaRequest, ) -> Result<VerifyMfaResponse>

Verify a TOTP code

Used both during enrolment confirmation and on subsequent logins. Burns no recovery code; for recovery use /auth/mfa/recovery.

POST /api/v1/auth/mfa/verify

Source

pub async fn verify_mfa_recovery( &self, body: &VerifyMfaRecoveryRequest, ) -> Result<VerifyMfaRecoveryResponse>

Verify a one-time recovery code (burns it on success)

POST /api/v1/auth/mfa/recovery

Source

pub async fn verify_otp_code( &self, body: &AuthVerifyCodeRequest, ) -> Result<AuthVerifyCodeResponse>

Verify OTP code

Expects body with email and code only (no request_id). Returns api_key to use as Bearer token.

POST /api/v1/auth/verify-code

Trait Implementations§

Source§

impl Clone for AuthApi

Source§

fn clone(&self) -> AuthApi

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AuthApi

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more