āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/clerk/clerk-docs/guides/development/verifying-oauth-access-tokens ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
When building a resource server that needs to accept and verify OAuth access tokens issued by Clerk, it's crucial to verify these tokens on your backend to ensure the request is coming from an authenticated client.
<Include src="_partials/machine-token-pricing-callout" />Clerk's Next.js SDK provides a built-in auth() function that supports token validation via the acceptsToken parameter. This lets you specify which type(s) of token your API route should accept. You can also use the auth.protect() method to check if a request includes a valid machine token (e.g. API key or OAuth token) and enforce access rules accordingly.
By default, acceptsToken is set to session_token, which means OAuth tokens will not be accepted unless explicitly configured. You can pass either a single token type or an array of token types to acceptsToken. To learn more about the supported token types, see the auth() parameters documentation.
Below are two examples of verifying OAuth access tokens in a Next.js API route using Clerk's SDK:
In the following example, the acceptsToken parameter is set to only accept oauth_tokens.
auth() will return null for userId and other properties, and the request will be rejected with a 401 response.userId is returned and the token claims are available for use in the application logic.import { auth } from '@clerk/nextjs/server'
export async function GET() {
const { isAuthenticated, claims, userId } = await auth({ acceptsToken: 'oauth_token' })
// If auth() returns null, the token is invalid
if (!isAuthenticated) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
return NextResponse.json({ userId, claims })
}
In the following example, the acceptsToken option allows both session_tokens and oauth_tokens.
auth() will return false for isAuthenticated and null for other properties, like userId.oauth_token, the code checks that it includes the required 'profile' scope. If not, an error is thrown.isAuthenticated is true and userId is returned and available for use in the application logic. This example includes pseudo-code that uses the userId to get data from a database.import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@clerk/nextjs/server'
export async function POST(req: NextRequest) {
// Accept both session_token and oauth_token types
const { isAuthenticated, tokenType, userId, scopes } = await auth({
acceptsToken: ['session_token', 'oauth_token'],
})
// If auth() returns null, the token is invalid
if (!isAuthenticated) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Check if the token is an oauth_token and if it doesn't have the required scope
if (tokenType === 'oauth_token' && !scopes?.includes('profile')) {
return NextResponse.json({ error: 'OAuth token missing the "profile" scope' }, { status: 401 })
}
// If the token includes the required scope, move forward with the application logic
// This example includes pseudo-code for getting data from a database using the userId
const data = db.select().from(user).where(eq(user.id, userId))
return NextResponse.json({ data })
}
You can also protect entire route groups using clerkMiddleware(). See how to implement this in the middleware docs.
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā