Suprnova exposes OAuth, Sign in with Apple, and passwordless magic links through
the framework-owned Auth facade. Magnetar supplies the credential, ceremony,
identity, factor-gate, and session engines behind that facade.
The public entry points are:
Auth::oauth(provider)for OAuth and Apple.Auth::magic_link()for passwordless email login.
Suprnova does not install routes for these flows. Applications provide small start and callback handlers and decide how to deliver magic-link email.
Initialize Magnetar with OAuth
Configure OAuth on the same MagnetarConfig that initializes password,
passkey, session, lockout, and two-factor services. The provider registry is
published atomically with those services: if any service cannot be built, none
of them becomes visible.
use Arc;
use ;
pub async
The framework re-exports the OAuthProvider contract, the five first-party
providers and configuration types, and every type needed to implement a custom
provider. ReqwestOAuthTransport supplies production token, userinfo, and
revocation I/O. FrameworkAbuseLimiter uses the application's configured
RateLimiterDriver. Applications need neither a direct suprnova-magnetar
dependency nor hand-written transport and limiter adapters.
MagnetarConfig creates its schema when apply_migrations is enabled, which is
the default. Use .apply_migrations(false) only when deployment prepares the
same schema separately. A second initialization returns an error instead of
replacing any installed engine.
Keep an existing user and session stack
An application can use Magnetar for OAuth ceremonies and provider proof without
making Magnetar authoritative for password, passkey, framework-session, or
remember-me state. Build the same MagnetarOAuthHostConfig, then install it
through the OAuth-only initializer:
use ;
let database = DBconnection?;
init_magnetar_oauth_only
.await?;
Start the ceremony normally with Auth::oauth(provider).begin(). In the
callback, call verify_oauth_identity(code, state), map the verified provider
subject into the application's own user table, and establish the existing
framework session with Auth::login. Do not call complete in this mode:
complete applies Magnetar's default account and session mapping, while the
purpose of OAuth-only initialization is to leave those decisions with the
application.
OAuth-only and full default initialization are alternatives. A second initializer fails instead of mixing session authorities.
GitHub provider requirements
GitHub's REST user endpoint requires a User-Agent; a community provider adds
it, and any media-type Accept value it needs, through
OAuthProvider::userinfo_headers. Suprnova adds the bearer Authorization
header separately and rejects provider attempts to override it.
GitHub's /user response includes an email only when the user made it public.
The verified primary address requires a second /user/emails request, while
resolve_identity deliberately performs no I/O and receives one userinfo
response. A GitHub provider can return email: None and use Suprnova's email
completion ceremony, or point userinfo_endpoint at a host adapter that
combines /user with the verified primary email. Do not treat an unverified or
merely public address as account ownership.
Session binding
OAuth begin requires SessionMiddleware. Magnetar binds the ceremony to a
digest of the initiating framework session, so the callback cannot be moved to
another browser session.
Successful password, magic-link, passkey, and OAuth sign-in rotates the framework session ID and CSRF token, records the application user ID, and stores an opaque Magnetar web binding. Remember-me hydration rotates both the Magnetar credential and the framework session binding.
Start an OAuth flow
Use begin in the provider's start handler:
use Auth;
let kickoff = oauth.begin.await?;
// Return an HTTP redirect to kickoff.authorization_url.
The returned OAuthKickoff contains:
authorization_url, the URL to send to the browser.state, the single-use selector bound to the initiating session.
Magnetar owns state generation, PKCE policy, ceremony persistence, provider exchange, identity verification, and abuse limiting. The host controller owns the HTTP redirect and callback route.
Verify or complete the callback
The callback has two entry points:
| Method | Result | Side effects |
|---|---|---|
verify_oauth_identity(code, state) |
OAuthIdentity |
Verifies the provider proof and returns the provider, subject, verified email, and display name without creating an application session. |
complete(code, state) |
(User, Session) |
Resolves the identity through the installed host engine, applies account-link policy and the factor gate, rotates the framework session, and returns the framework-owned user and Magnetar session values. |
let identity = oauth
.verify_oauth_identity
.await?;
let = oauth
.complete
.await?;
OAuthIdentity.email is present only when the provider supplied a verified
email. Persist the provider and subject as the stable external identity. Email
is not a stable provider identifier.
Account-link policy
OAuth completion does not treat possession of an unverified email string as proof that the caller owns an existing application account.
The completion result can require more work instead of issuing a session:
- Email completion required returns HTTP 409 when the provider identity needs a separate verified-email ceremony.
- Explicit link required returns HTTP 409 when an existing verified account must authorize the link.
- Factor required returns HTTP 401 when account policy requires a second factor before session issuance.
A verified-email completion that wins the first-email-proof boundary reclaims an unverified squatted account atomically. The transaction advances the auth epoch, removes provisional credentials, revokes old sessions and remember credentials, and attaches the verified provider account. A verified account is never auto-linked by email alone.
Sign in with Apple
Apple uses the same Auth::oauth("apple") facade, but its callback commonly
uses response_mode=form_post. Register the callback as a POST route and
pass the optional Apple user form field through the Apple-specific methods:
let identity = oauth
.verify_apple_identity
.await?;
let = oauth
.complete_with_apple_form_post
.await?;
AppleIdentity includes the stable subject, optional verified email,
email_verified, and is_private_email. Persist the subject as the stable key.
Apple can supply the display name only during the first authorization, so the
provider adapter must preserve that first form_post value.
Apple token and identity verification belongs to the installed provider implementation. Current Magnetar providers require signature, issuer, audience, expiry, and nonce checks rather than trusting an ID token's decoded JSON.
Magic-link login
Magic-link login uses the installed Magnetar password/session engine. The framework returns the plaintext single-use token, while the application owns mail composition and URL shape:
use ;
let token = magic_link
.send
.await?;
let url = format!;
to
.send
.await?;
let = magic_link.consume.await?;
send applies the authentication abuse budget before token issuance. consume
is single-use, applies the factor gate, binds the resulting session into the
framework request session, and returns the user and Magnetar session.
For an unverified pre-existing account, successful magic-link consumption is a first email proof. The transaction reclaims the account and removes provisional password, passkey, linked-account, two-factor, session, and remember state so a prior squatter cannot retain access.
Routes to add
A typical application adds these routes:
get!,
get!,
post!,
post!,
get!,
Apply SessionMiddleware to every OAuth and passkey start/callback route. The
session carries the ceremony selector and binds the round trip to the browser
that started it.
Authentication migration
The suprnova-magnetar crate includes a shape-aware migration engine for
Torii, Suprnova web, Suprnova API, and existing Magnetar schemas. It is a
library surface and example, not a suprnova CLI subcommand.
Enable the migration feature plus the source database driver and run a dry
plan before applying. For PostgreSQL:
cargo run -p suprnova-magnetar \
--features migration,seaorm-postgres \
--example migrate -- \
--source-shape torii \
--database-url "$SOURCE_DATABASE_URL" \
--app-database-url "$DATABASE_URL"
Use seaorm-mysql or seaorm-sqlite instead when that is the source and
application database driver.
Add --apply to apply the reviewed plan. The runner rechecks source and schema
fingerprints before import, records retry state, refuses identity collisions,
and uses transactional imports. MySQL same-database migrations use a
write-barrier-protected shadow swap with resumable restore and abort paths.
Keep the generated plan and report in deployment records. Do not apply a plan whose source fingerprint changed after review.
Reference
- Default boot:
MagnetarConfig,PasskeyConfig, andinit_magnetar. - Facades:
Auth::oauth(provider)andAuth::magic_link(). - OAuth installation:
MagnetarConfig::oauth,ReqwestOAuthTransport, andFrameworkAbuseLimiter. - Migration library:
magnetar::migrationfrom thesuprnova-magnetarcrate. - Bearer authentication:
BearerTokenMiddleware.
Next
- Authentication covers password, passkey, guards, framework sessions, and engine initialization.
- Auth flows covers email verification, password reset, lockout, and two-factor authentication.
- Mail covers application-owned magic-link delivery.
- Session covers the browser session that binds OAuth and passkey ceremonies.
