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
useVerifyDeviceCode,useApproveDevice, anduseDenyDevicemutation hooks
The requesting device remains responsible for calling Better Auth's /device/code endpoint and polling /device/token.
Setup
Install the Better Auth plugin
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 the Better Auth schema after enabling the server plugin. It adds the deviceCode model used to track pending requests.
Install the matching client plugin
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()]
})Register the UI plugin
Pass deviceAuthorizationPlugin() to <AuthProvider>:
import { AuthProvider } from "@better-auth-ui/heroui"
import { deviceAuthorizationPlugin } from "@better-auth-ui/heroui/plugins"
<AuthProvider
authClient={authClient}
navigate={navigate}
plugins={[deviceAuthorizationPlugin()]}
>
{children}
</AuthProvider>Allow the new auth path
Include the plugin's path in the route that renders <Auth />. Keep this path aligned with the server's verificationUri:
import { viewPaths } from "@better-auth-ui/core"
import { Auth } from "@better-auth-ui/heroui"
import { deviceAuthorizationPlugin } from "@better-auth-ui/heroui/plugins"
import { createFileRoute, notFound } from "@tanstack/react-router"
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} />
}Components
<DeviceAuthorization />
Device Authorization
Enter the code displayed on your device.
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 use it directly:
import { DeviceAuthorization } from "@better-auth-ui/heroui/plugins"
<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
Read these values from useAuthPlugin(deviceAuthorizationPlugin).localization inside custom plugin views.
Sessions and revocation
The device token creates an ordinary Better Auth session after approval. 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