Device Authorization
Approve CLI, TV, and limited-input device sign-ins from an authenticated browser.
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
<DeviceAuthorization />view at/auth/device - Code verification with the
user_codequery parameter prefilled when present - Sign-in redirection that preserves the pending code
- Approve and deny confirmation states
- React Query hooks for verifying, approving, and denying device 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:
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 migrateThe plugin adds the deviceCode model used to track pending requests.
Configure the browser client
Add deviceAuthorizationClient() to your browser auth client:
import { createAuthClient } from "better-auth/react"
import { deviceAuthorizationClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [deviceAuthorizationClient()]
})Install the device authorization view
bunx --bun shadcn@latest add https://better-auth-ui.com/r/device-authorization.jsonThis installs:
src/lib/auth/device-authorization-plugin.tssrc/components/auth/device-authorization/device-authorization.tsx- The required shadcn UI primitives
Register the UI plugin
Pass deviceAuthorizationPlugin() to <AuthProvider>:
import { AuthProvider } from "@/components/auth/auth-provider"
import { deviceAuthorizationPlugin } from "@/lib/auth/device-authorization-plugin"
<AuthProvider
authClient={authClient}
navigate={navigate}
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:
import { viewPaths } from "@better-auth-ui/core"
import { createFileRoute, notFound } from "@tanstack/react-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 notFound()
}
},
component: AuthPage
})
function AuthPage() {
const { path } = Route.useParams()
return <Auth path={path} />
}Component
Enter any eight-character code in the preview to exercise the approval flow.
The 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 />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?"
}
})Keep userCodeLength equal to the value passed to Better Auth's server plugin. A mismatched length prevents valid codes from being submitted.
Localization
React APIs
The view uses these React Query hooks:
useVerifyDeviceCodeverifies and claims the submitted code for the current session.useApproveDevicegrants the requesting device access.useDenyDevicerejects the request.
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