Swift: Authentication
Sign app users in with passwords, magic links, SMS and email codes, OAuth/SSO and passkeys; keep and refresh the session; handle deep links with the Swift SDK.
Sign app users in with passwords, magic links, SMS and email codes, OAuth/SSO and passkeys; keep and refresh the session; handle deep links. Every call runs as the client's signed-in user, so your project's policies and row-level security apply. Types and members are listed in source order; each one links to its HTTP endpoint where it maps to one.
#Types and members
SovariaAuth
Sign-in, sign-up and the session for an app user. Mirrors the Dart/TS/Python clients.
public final class SovariaAuth: @unchecked SendableSovariaAuth.currentSession
A property.
public var currentSession: Session?SovariaAuth.passkeys
Passkeys (WebAuthn): add one for the signed-in user, sign in with one, list and remove them.
public var passkeys: SovariaPasskeysSovariaAuth.changes
Emits sign-in / refresh / sign-out events (for updating UI).
public var changes: AsyncStream<AuthState>Each new listener first gets .initialSession with the current session (nil when signed out), as in the Dart and TypeScript clients.
SovariaAuth.restoreSession
public func restoreSession() async throws -> Session?SovariaAuth.currentAccessToken
The token to sign requests with: the session's (refreshed first when near expiry) or nil.
public func currentAccessToken() async -> String?SovariaAuth.refreshSession
public func refreshSession(silent: Bool = false) async throws -> Session?SovariaAuth.signUp
public func signUp(email: String, password: String, name: String = "") async throws -> [String: Any]SovariaAuth.signInWithPassword
public func signInWithPassword(email: String, password: String, captchaToken: String? = nil) async throws -> SessionSovariaAuth.signInAnonymously
public func signInAnonymously() async throws -> SessionSovariaAuth.verifyMfa
public func verifyMfa(_ code: String, method: String = "") async throws -> SessionSovariaAuth.sendSmsOtp
public func sendSmsOtp(_ phone: String) async throwsSovariaAuth.verifySmsOtp
public func verifySmsOtp(phone: String, code: String) async throws -> SessionSovariaAuth.sendMagicLink
Email a sign-in link plus a 6-digit code.
public func sendMagicLink(_ email: String, redirectTo: String? = nil, pkce: Bool? = nil, captchaToken: String? = nil) async throwsA link that opens your app (redirectTo with your app's scheme, or a universal link with pkce: true) is bound to this install with PKCE.
SovariaAuth.verifyMagicLink
Sign in with the token from a magic link (usually through handleDeepLink).
public func verifyMagicLink(_ token: String, codeVerifier: String? = nil) async throws -> SessionSovariaAuth.verifyEmailCode
public func verifyEmailCode(email: String, code: String) async throws -> SessionSovariaAuth.resetPasswordForEmail
Email a password-reset link (PKCE-bound when it opens your app).
public func resetPasswordForEmail(_ email: String, redirectTo: String? = nil, pkce: Bool? = nil) async throwsSovariaAuth.confirmPasswordReset
Set the new password with the token from a type=recovery link.
public func confirmPasswordReset(token: String, newPassword: String, codeVerifier: String? = nil) async throwsSovariaAuth.handleDeepLink
Handle a deep link / universal link that opened the app: provider sign-in (type=sso), magic links, email confirmations; for recovery the token is returned for the new-password screen.
public func handleDeepLink(_ url: URL) async throws -> AuthLinkResult?Returns nil when the link isn't an auth link. Call it from onOpenURL / application(_:open:).
SovariaAuth.getOAuthSignInURL
Where the OAuth sign-in should take the user (an app scheme such as com.acme.app://callback, or a web URL).
public func getOAuthSignInURL(_ provider: String, redirectTo: String? = nil) async throws -> OAuthStartAsks for the JSON answer (the route redirects otherwise) and starts PKCE: the verifier is kept in the session storage until exchangeCodeForSession (audit SDK2-M2).
SovariaAuth.exchangeCodeForSession
Finish an OAuth sign-in with the code from the redirect.
public func exchangeCodeForSession(_ code: String, codeVerifier: String? = nil) async throws -> SessionThe PKCE verifier saved by getOAuthSignInURL is used when none is passed.
SovariaAuth.listProviders
public func listProviders() async throws -> [[String: Any]]SovariaAuth.getUser
public func getUser() async throws -> [String: Any]SovariaAuth.listDevices
public func listDevices() async throws -> [[String: Any]]SovariaAuth.signOut
public func signOut() async throwsAuthState
public struct AuthState: @unchecked SendableAuthState.event
A property.
public let event: AuthEventAuthState.session
A property.
public let session: Session?AuthLinkResult
What an auth link did. type is sso, magiclink, recovery, signup, email_change_current or email_change_new; session is set when the link signed the user in; for recovery pass token to confirmPasswordReset with the new password.
public struct AuthLinkResult: @unchecked SendableAuthLinkResult.type
A property.
public let type: StringAuthLinkResult.session
A property.
public let session: Session?AuthLinkResult.token
A property.
public let token: String?AuthLinkResult.error
A property.
public let error: String?AuthLinkResult.errorDescription
A property.
public let errorDescription: String?OAuthStart
public struct OAuthStart: SendableOAuthStart.url
A property.
public let url: StringOAuthStart.codeVerifier
A property.
public let codeVerifier: String?SovariaPasskeys
Passkey calls. Run the platform ceremony with ASAuthorizationPlatformPublicKeyCredentialProvider (iOS 15+, macOS 12+): build its request from the options a start… call returns, then send the credential as WebAuthn JSON (base64url fields) to the matching finish… call.
public struct SovariaPasskeys: @unchecked SendableSovariaPasskeys.startRegistration
Registration options (WebAuthn JSON) for a new passkey for the signed-in user.
public func startRegistration(name: String = "") async throws -> [String: Any]SovariaPasskeys.finishRegistration
Save the passkey the authenticator created (its WebAuthn JSON).
public func finishRegistration(credential: [String: Any], name: String = "") async throws -> [String: Any]SovariaPasskeys.startSignIn
Sign-in options.
public func startSignIn(userId: String? = nil) async throws -> SignInStartPass userId to offer only that user's passkeys.
SovariaPasskeys.finishSignIn
Verify the signed challenge and sign the user in (two-factor when the device checked the user).
public func finishSignIn(challengeId: String, credential: [String: Any]) async throws -> SessionSovariaPasskeys.list
The signed-in user's passkeys: id, name, created_at, last_used_at.
public func list() async throws -> [[String: Any]]SovariaPasskeys.remove
Remove one of the signed-in user's passkeys.
public func remove(_ passkeyId: String) async throwsSignInStart
public struct SignInStart: @unchecked SendableSignInStart.challengeId
A property.
public let challengeId: StringSignInStart.options
A property.
public let options: [String: Any]Session
A signed-in app user's tokens.
public struct Session: @unchecked SendableSession.accessToken
A property.
public let accessToken: StringSession.refreshToken
A property.
public let refreshToken: StringSession.expiresAt
A property.
public let expiresAt: DateSession.raw
The full token response (actor lane, MFA flags, …), minus the refresh token.
public let raw: [String: Any]Session.Session.init
Create an instance.
public init(accessToken: String, refreshToken: String, expiresAt: Date, raw: [String: Any] = [:])Session.userId
The user id (sub of the access token).
public var userId: String?Session.claims
The access token's claims (not verified here; the server verifies on every request).
public var claims: [String: Any]Session.expiresWithin
public func expiresWithin(_ margin: TimeInterval, now: Date = Date()) -> BoolSessionStorage
Where the client keeps the session across launches. Use the Keychain in apps; the default keeps it in memory only (lost on relaunch).
public protocol SessionStorage: AnyObject, SendableSessionStorage.read
func read(_ key: String) async -> String?SessionStorage.write
func write(_ key: String, _ value: String) asyncSessionStorage.delete
func delete(_ key: String) asyncMemorySessionStorage
public final class MemorySessionStorage: SessionStorage, @unchecked SendableMemorySessionStorage.MemorySessionStorage.init
Create an instance.
public init()MemorySessionStorage.read
public func read(_ key: String) async -> String?MemorySessionStorage.write
public func write(_ key: String, _ value: String) asyncMemorySessionStorage.delete
public func delete(_ key: String) asyncSovariaDevice
The device a session belongs to (sent as headers so sign-outs and attestation can target it).
public struct SovariaDevice: SendableSovariaDevice.id
A property.
public let id: StringSovariaDevice.platform
A property.
public let platform: StringSovariaDevice.name
A property.
public let name: StringSovariaDevice.SovariaDevice.init
Create an instance.
public init(id: String, platform: String, name: String = "")AuthEvent
public enum AuthEvent: SendableValues: initialSession, signedIn, tokenRefreshed, signedOut, mfaRequired.
Pkce
A PKCE pair (RFC 7636, S256): keep verifier on the device, send challenge with the request.
public struct Pkce: SendablePkce.verifier
A property.
public let verifier: StringPkce.challenge
A property.
public let challenge: StringPkce.generate
A fresh pair from 32 random bytes (a 43-character verifier).
public static func generate() -> PkcePkce.challengeFor
BASE64URL(SHA-256(verifier)) without padding.
public static func challengeFor(_ verifier: String) -> String