BETTER-AUTH. UI
Plugins

Device Authorization

Approve CLI, TV, and limited-input device sign-ins with Solid and Zaidan.

The Device Authorization plugin adds the browser half of Better Auth's device authorization flow. A user enters the short code shown by a CLI, TV, or another limited-input device, signs in if needed, then approves or denies access.

It contributes:

  • A copied <DeviceAuthorization /> view at /auth/device
  • Code verification with the user_code query parameter prefilled when present
  • Sign-in redirection that preserves the pending code
  • Approve and deny confirmation states
  • Solid Query mutation options for verifying, approving, and denying requests

The requesting device remains responsible for calling Better Auth's /device/code endpoint and polling /device/token.

Setup

Configure the Better Auth server

Add the Device Authorization plugin to your Better Auth server. Set verificationUri to the public route that renders the UI view:

src/lib/auth.ts
import { betterAuth } from "better-auth"
import { deviceAuthorization } from "better-auth/plugins"

export const auth = betterAuth({
  // ...
  plugins: [
    deviceAuthorization({ 
      verificationUri: "/auth/device"
    }) 
  ]
})

Generate or migrate your Better Auth schema after enabling the plugin:

bunx auth@latest migrate

The plugin adds the deviceCode model used to track pending requests.

Configure the Solid client

Add deviceAuthorizationClient() to the auth client:

src/lib/auth-client.ts
import { createAuthClient } from "@better-auth-ui/solid"
import { deviceAuthorizationClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
  plugins: [deviceAuthorizationClient()] 
})

Install the Solid and Zaidan view

bunx --bun shadcn@latest add https://better-auth-ui.com/r/solid/device-authorization.json

This copies the following files into your project:

  • src/lib/auth/device-authorization-plugin.ts
  • src/components/auth/device-authorization/device-authorization.tsx
  • Local Zaidan UI primitives under src/components/ui/**

After install, the view and plugin factory belong to your application. You can adapt their layout or behavior without waiting for a package release.

Register the UI plugin

Pass deviceAuthorizationPlugin() to the copied <AuthProvider>:

src/components/providers.tsx
import { AuthProvider } from "@/components/auth/auth-provider"
import { deviceAuthorizationPlugin } from "@/lib/auth/device-authorization-plugin"

<AuthProvider
  authClient={authClient}
  plugins={[deviceAuthorizationPlugin()]} 
>
  {children}
</AuthProvider>

Allow the device route

Include the plugin path in the route that renders <Auth />. Keep it aligned with the server's verificationUri:

src/routes/auth/$path.tsx
import { viewPaths } from "@better-auth-ui/core"
import { createFileRoute, redirect } from "@tanstack/solid-router"

import { Auth } from "@/components/auth/auth"
import { deviceAuthorizationPlugin } from "@/lib/auth/device-authorization-plugin"

const validAuthPathSegments = new Set([
  ...Object.values(viewPaths.auth),
  deviceAuthorizationPlugin().viewPaths.auth.deviceAuthorization
])

export const Route = createFileRoute("/auth/$path")({
  beforeLoad({ params: { path } }) {
    if (!validAuthPathSegments.has(path)) {
      throw redirect({ to: "/" })
    }
  },
  component: AuthPage
})

function AuthPage() {
  const { path } = Route.useParams()()
  return <Auth path={path} />
}

Component

The copied component is rendered automatically at /auth/device when the plugin is registered. You can also render it directly:

import { DeviceAuthorization } from "@/components/auth/device-authorization/device-authorization"

<DeviceAuthorization />

Prop

Type

Options

deviceAuthorizationPlugin({
  // Override the URL segment. Default: "device"
  path: "activate",
  // Match Better Auth's server-side userCodeLength. Default: 8
  userCodeLength: 8,
  localization: {
    approveDevice: "Allow this device?"
  }
})

Prop

Type

Keep userCodeLength equal to the value passed to Better Auth's server plugin. A mismatched length prevents valid codes from being submitted.

Localization

Prop

Type

Solid APIs

The copied view uses these Solid Query option factories:

Sessions and revocation

An approved device token creates an ordinary Better Auth session. There is no separate device registry in the Device Authorization plugin. Use <ActiveSessions /> to list sessions and revoke access for an approved device.

Last updated on

On this page