Docs

Build a custom sign-out flow

Warning

This guide is for users who want to build a custom user interface using the Clerk API. To use a prebuilt UI, use the Account Portal pages or prebuilt components.

Clerk's <UserButton /> and <SignOutButton /> components provide an out-of-the-box solution for signing out users. However, if you're building a custom solution, you can use the signOut() function to handle the sign-out process.

The signOut() function signs a user out of all sessions in a multi-session application, or only the current session in a single-session context. You can also specify a specific session to sign out by passing the sessionId parameter.

Note

The sign-out flow deactivates only the current session. Other valid sessions associated with the same user (e.g., if the user is signed in on another device) will remain active.

The useClerk() hook is used to access the signOut() function, which is called when the user clicks the sign-out button.

The Next.js useRouter() hook is used to redirect the user to the home page after they sign out.

This example is written for Next.js App Router but can be adapted for any React meta framework, such as Remix.

app/components/SignOutButton.tsx
'use client'

import { useClerk } from '@clerk/nextjs'

export const SignOutButton = () => {
  const { signOut } = useClerk()

  return (
    // Clicking this button signs out a user
    // and redirects them to the home page "/".
    <button onClick={() => signOut({ redirectUrl: '/' })}>Sign out</button>
  )
}
index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/clerk.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Clerk + JavaScript App</title>
  </head>

  <body>
    <div id="app"></div>
    <button id="sign-out">Sign out</button>
    <script type="module" src="main.js" async crossorigin="anonymous"></script>
  </body>
</html>
main.js
import { Clerk } from '@clerk/clerk-js'

const pubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

const clerk = new Clerk(pubKey)
await clerk.load()

if (clerk.user) {
  // Attach signOut function to the sign-out button
  document.getElementById('sign-out').addEventListener('click', async () => {
    await clerk.signOut()
    // Optional: refresh page after sign-out
    window.location.reload()
  })
}
SignOutButton.tsx
import { useClerk } from '@clerk/clerk-react'
import * as Linking from 'expo-linking'
import { Button } from 'react-native'

export const SignOutButton = () => {
  const { signOut } = useClerk()

  const handleSignOut = async () => {
    try {
      await signOut()
      // Redirect to your desired page
      Linking.openURL(Linking.createURL('/'))
    } catch (err) {
      // See https://clerk.com/docs/custom-flows/error-handling
      // for more info on error handling
      console.error(JSON.stringify(err, null, 2))
    }
  }

  return <Button title="Sign out" onPress={handleSignOut} />
}
SignOutView.swift
import SwiftUI
import ClerkSDK

struct SignOutView: View {
  @ObservedObject private var clerk = Clerk.shared

  var body: some View {
    if let session = clerk.session {
      Text("Active Session: \(session.id)")
      Button("Sign out") {
        Task { await signOut() }
      }
    } else {
      Text("You are signed out")
    }
  }
}

extension SignOutView {

  func signOut() async {
    do {
      try await clerk.signOut()
    } catch {
      // See https://clerk.com/docs/custom-flows/error-handling
      // for more info on error handling.
      dump(error)
    }
  }
}

Feedback

What did you think of this content?

Last updated on