> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift SDK authentication

> Authenticate with a provider ID token, email OTP, or an OIDC redirect and activate a wallet.

Authentication establishes an OMS access credential. Wallet selection then activates a wallet and completes the session. Protected wallet operations require that completed session.

Starting any new authentication flow clears the current wallet session and invalidates earlier pending authentication or wallet-selection state.

## Sign in with OIDC token

Prefer native ID-token authentication when an iOS provider SDK supplies an OIDC ID token. Your app owns provider setup, consent UI, and token acquisition. Pass the provider token to OMS with the issuer and audience that minted it.

```swift theme={null}
let auth = try await omsWallet.wallet.signInWithOidcIdToken(
    idToken: googleIdToken,
    issuer: "https://accounts.google.com",
    audience: "YOUR_WEB_CLIENT_ID",
    provider: "google",
    providerLabel: "Google"
)

if case .walletSelected(let walletAddress, _, _, _) = auth {
    print("Active wallet:", walletAddress)
}
```

`googleIdToken` is an identity-provider input. It is not the wallet ID token returned by `getIdToken()`, which proves the active OMS wallet to your backend. See [sessions and access](/wallets/sdk/swift/sessions-and-access#request-a-wallet-id-token).

The maintained `Examples/sdk-demo` app in the [Swift SDK repository](https://github.com/0xsequence/swift-sdk) shows Google Sign-In acquiring the provider ID token before calling `signInWithOidcIdToken`.

The default session lifetime is one week. Set `sessionLifetimeSeconds` from `1` through `2_592_000` when you need a different lifetime.

## Use email OTP

Email authentication is a two-step flow. The lifetime is chosen when the OTP is sent and reused when the code is completed.

```swift theme={null}
try await omsWallet.wallet.startEmailAuth(
    email: "user@example.com",
    sessionLifetimeSeconds: 604_800
)

let auth = try await omsWallet.wallet.completeEmailAuth(code: "123456")
```

With the default automatic selection, `auth` contains the activated wallet, all wallets returned for the credential, and `CredentialInfo` for the new access credential.

## Use an OIDC redirect

Use redirect authentication when the provider does not supply a token through a native SDK or when you need a browser authorization-code flow.

### Fixed Google and Apple relay providers

`OMSRelayOIDCProviders.google` and `.apple` are fixed SDK values. Their client IDs, scopes, PKCE mode, authorization parameters, and provider callback URLs are not configurable. Supply only the URL where the OMS relay should return to your app.

Start the redirect through the wallet client:

```swift theme={null}
let started = try await omsWallet.wallet.startOIDCRedirectAuth(
    provider: OMSRelayOIDCProviders.google,
    omsRelayReturnURI: "yourapp://auth/callback"
)
```

Open `started.authorizationURL` with SwiftUI's `openURL` environment action or the authentication browser used by your application. Register `yourapp` as a URL scheme, or use an associated universal link, before starting the flow.

### Route the callback in SwiftUI

Pass incoming URLs directly to the SDK from SwiftUI's `onOpenURL`.

```swift theme={null}
ContentView()
    .onOpenURL { url in
        Task {
            let callback = try await omsWallet.wallet.handleOIDCRedirectCallback(
                url.absoluteString
            )

            if case .completed(.walletSelected(let address, _, _, _)) = callback {
                print("Active wallet:", address)
            }
        }
    }
```

The handler is safe to call for unrelated app links. It returns `.notOIDCRedirectCallback` for a URL that does not belong to OMS and `.noPendingAuth` when no matching attempt is stored. If the application also uses other URL-based provider SDKs, route each URL to its owner. After the OMS handler validates the callback URL and OAuth state, it consumes the stored redirect flow before completing authentication. A completed, failed, or canceled callback cannot be reused; start a new redirect flow.

Values for `walletSelection` and `sessionLifetimeSeconds` passed to `startOIDCRedirectAuth` are stored with the pending callback. Arguments passed to `handleOIDCRedirectCallback` override them.

### Configure a custom provider

Custom providers use their own callback directly and default to authorization code with PKCE. The app owns this configuration.

```swift theme={null}
let provider = CustomOIDCProviderConfiguration(
    issuer: "https://issuer.example.com",
    clientID: "YOUR_OIDC_CLIENT_ID",
    authorizationURL: "https://issuer.example.com/oauth2/authorize",
    providerRedirectURI: "yourapp://auth/callback",
    provider: "corporate",
    providerLabel: "Corporate SSO",
    scopes: ["openid", "email", "profile"]
)

let started = try await omsWallet.wallet.startOIDCRedirectAuth(
    provider: provider
)
```

`providerRedirectURI` is both the OAuth redirect URI and the callback URL expected by the SDK.

## Choose a wallet automatically or manually

Automatic selection is the default for every auth method. It activates the first wallet matching `.ethereum`, or creates one when none exists.

Set `walletSelection: .manual` when your app needs to present a wallet picker.

```swift theme={null}
let auth = try await omsWallet.wallet.signInWithOidcIdToken(
    idToken: googleIdToken,
    issuer: "https://accounts.google.com",
    audience: "YOUR_WEB_CLIENT_ID",
    walletSelection: .manual
)

guard case .walletSelection(let pending) = auth else {
    return
}

if let wallet = pending.wallets.first {
    try await pending.selectWallet(walletId: wallet.id)
} else {
    try await pending.createAndSelectWallet(reference: "primary")
}
```

`PendingWalletSelection` is pending, single-use, and held in memory until activation. It is not a completed or restorable wallet session, and protected wallet operations are unavailable until you select or create a wallet. A new auth flow, sign-out, expiry, or a completed selection makes the pending value stale.
