> ## 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 Google sign-in and 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.

## Social login

Social login is the recommended flow for consumer-facing fintechs and payment apps. Users authenticate via their existing Google account. No password or seed phrase is involved.

Use the SDK's default Google redirect flow when your app can authenticate through a browser redirect. Mobile apps start the redirect, open the returned authorization URL, and complete authentication from the deep-link callback URL.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await oms.wallet.signInWithOidcRedirect({
      provider: 'google',
    })

    if (result && 'walletAddress' in result) {
      console.log('Wallet address:', result.walletAddress)
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    import { OidcProviders } from '@0xsequence/oms-react-native-sdk'

    const started = await oms.wallet.startOidcRedirectAuth({
      provider: OidcProviders.google(),
      redirectUri: 'yourapp://auth/callback',
    })

    openSystemAuth(started.authorizationUrl)

    const result = await oms.wallet.handleOidcRedirectCallback({
      callbackUrl,
    })

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

  <Tab title="Swift">
    ```swift theme={null}
    let started = try await oms.wallet.startOidcRedirectAuth(
        provider: OidcProviders.google(),
        redirectUri: "yourapp://auth/callback"
    )

    openSystemAuth(started.authorizationUrl)

    let result = try await oms.wallet.handleOidcRedirectCallback(callbackUrl)

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

  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.omsclient.kotlin_sdk.wallet.OidcProviders
    import com.omsclient.kotlin_sdk.wallet.OidcRedirectAuthResult

    val started = client.wallet.startOidcRedirectAuth(
        provider = OidcProviders.google(),
        redirectUri = "yourapp://auth/callback",
    )

    openCustomTab(started.authorizationUrl)

    when (val result = client.wallet.handleOidcRedirectCallback(callbackUrl)) {
        is OidcRedirectAuthResult.Completed -> {
            println("Wallet address: ${result.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 the wallet is created on verification.

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

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

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

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

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

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

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

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

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

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

  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.omsclient.kotlin_sdk.wallet.CompleteAuthResult

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

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

    println("Wallet address: ${result.walletAddress}")
    ```
  </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 (oms.wallet.session.walletAddress) {
      console.log('Signed in:', oms.wallet.session.walletAddress)
    } else {
      console.log('Not signed in')
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    const session = await oms.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 = oms.wallet.session.walletAddress {
        print("Signed in:", walletAddress)
    } else {
        print("Not signed in")
    }
    ```
  </Tab>

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

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