> ## 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.

# Authentication

> Authenticate non-custodial wallets with OIDC or email OTP.

Non-custodial wallets support multiple authentication flows. Each method resolves the wallet for the authenticated identity. If your app supports account linking, linked identities can access the same wallet.

## OIDC authentication

OMS Wallet supports three OIDC flows: fixed Google and Apple redirects, redirects configured for custom providers, and provider-issued ID-token authentication.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { OmsRelayOidcProviders } from '@polygonlabs/oms-wallet'

    await omsWallet.wallet.completeOidcRedirectAuth()

    if (omsWallet.wallet.walletAddress) {
      console.log('Wallet address:', omsWallet.wallet.walletAddress)
    }

    // Run this from the user's sign-in action.
    await omsWallet.wallet.signInWithOidcRedirect({
      provider: OmsRelayOidcProviders.google,
    })
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    import { OmsRelayOidcProviders } from '@polygonlabs/oms-wallet-react-native'

    const started = await omsWallet.wallet.startOidcRedirectAuth({
      provider: OmsRelayOidcProviders.google,
      omsRelayReturnUri: 'yourapp://auth/callback',
    })
    ```

    Open `started.authorizationUrl` in the platform authentication browser, then pass the returned callback URL to the SDK.

    ```typescript theme={null}
    const callback = await omsWallet.wallet.handleOidcRedirectCallback({
      callbackUrl,
    })

    if (
      callback.type === 'completed' &&
      callback.result.type === 'walletSelected'
    ) {
      console.log('Wallet address:', callback.result.walletAddress)
    }
    ```
  </Tab>

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

    Open `started.authorizationURL` in the platform authentication browser, then pass the returned callback URL to the SDK.

    ```swift theme={null}
    let callback = try await omsWallet.wallet.handleOIDCRedirectCallback(callbackURL)

    if case .completed(.walletSelected(let address, _, _, _)) = callback {
        print("Wallet address:", address)
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    Kotlin wallet APIs are `suspend` functions. Call them from a coroutine, such as `lifecycleScope.launch` in an Android UI.

    ```kotlin theme={null}
    import technology.polygon.omswallet.wallet.CompleteAuthResult
    import technology.polygon.omswallet.wallet.OidcRedirectAuthResult
    import technology.polygon.omswallet.wallet.OmsRelayOidcProviders

    val started = omsWallet.wallet.startOidcRedirectAuth(
        provider = OmsRelayOidcProviders.google,
        omsRelayReturnUri = "yourapp://auth/callback",
    )
    ```

    Open `started.authorizationUrl` in the platform authentication browser, then pass the returned callback URL to the SDK.

    ```kotlin theme={null}
    when (val callback = omsWallet.wallet.handleOidcRedirectCallback(callbackUrl)) {
        is OidcRedirectAuthResult.Completed -> {
            val auth = callback.result
            check(auth is CompleteAuthResult.WalletSelected)
            println("Wallet address: ${auth.wallet.address}")
        }
        else -> Unit
    }
    ```
  </Tab>
</Tabs>

On first login, OMS Wallet creates or resolves the wallet for the provider identity and returns the active wallet.

## Email OTP

Email OTP is ideal for financial products where users may not have a social account or prefer not to link one. The user enters their email, receives a one-time code, and a wallet is selected or created on verification.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    await omsWallet.wallet.startEmailAuth({ email: 'user@example.com' })

    const result = await omsWallet.wallet.completeEmailAuth({ code: '123456' })

    console.log('Wallet address:', result.walletAddress)
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    await omsWallet.wallet.startEmailAuth({ email: 'user@example.com' })

    const result = await omsWallet.wallet.completeEmailAuth({ code: '123456' })

    if (result.type !== 'walletSelected') {
      throw new Error('Select or create a wallet before continuing')
    }

    console.log('Wallet address:', result.wallet.address)
    ```
  </Tab>

  <Tab title="Swift">
    ```swift theme={null}
    try await omsWallet.wallet.startEmailAuth(email: "user@example.com")

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

    if let wallet = result.wallet {
        print("Wallet address:", wallet.address)
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    import technology.polygon.omswallet.wallet.CompleteAuthResult

    omsWallet.wallet.startEmailAuth("user@example.com")

    val result = omsWallet.wallet.completeEmailAuth("123456")
    check(result is CompleteAuthResult.WalletSelected)

    println("Wallet address: ${result.wallet.address}")
    ```
  </Tab>
</Tabs>

The SDK handles the full OTP flow. No additional backend is required for email OTP.

## Checking sign-in state

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    if (omsWallet.wallet.session.walletAddress) {
      console.log('Signed in:', omsWallet.wallet.session.walletAddress)
    } else {
      console.log('Not signed in')
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    const session = await omsWallet.wallet.getSession()

    if (session.walletAddress) {
      console.log('Signed in:', session.walletAddress)
    } else {
      console.log('Not signed in')
    }
    ```
  </Tab>

  <Tab title="Swift">
    ```swift theme={null}
    if let walletAddress = omsWallet.wallet.session.walletAddress {
        print("Signed in:", walletAddress)
    } else {
        print("Not signed in")
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val session = omsWallet.wallet.session

    if (session.walletAddress != null) {
        println("Signed in: ${session.walletAddress}")
    } else {
        println("Not signed in")
    }
    ```
  </Tab>
</Tabs>
