Verify API keys in your TanStack React Start application with Clerk
When building a resource server that needs to accept and verify API keys issued by Clerk, it's crucial to verify these keys on your backend to ensure the request is coming from an authenticated client.
Clerk's TanStack React Start 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 server function or API route should accept.
By default, acceptsToken is set to session_token, which means API keys 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 API keys in a TanStack React Start API route using Clerk's SDK:
Example 1: Accepting a single token type
In the following example, the acceptsToken parameter is set to only accept api_keys.
- If the API key is invalid or missing,
auth()will returnfalseforisAuthenticated, and the request will be rejected with a401response. - If the API key is valid,
subject,scopes, andclaimsare returned. API keys are scoped to either a user or an Organization, sosubjectis the user ID or Organization ID associated with the key.
import { json } from '@tanstack/react-start'
import { createFileRoute } from '@tanstack/react-router'
import { auth } from '@clerk/tanstack-react-start/server'
export const ServerRoute = createFileRoute('/api/example')({
server: {
handlers: {
GET: async () => {
const authObject = await auth({
acceptsToken: 'api_key',
})
// If isAuthenticated is false, the token is invalid
if (!authObject.isAuthenticated) {
return json({ error: 'Unauthorized' }, { status: 401 })
}
const { subject, scopes, claims } = authObject
return json({ subject, scopes, claims })
},
},
},
})In the following example, the acceptsToken parameter allows session_tokens, oauth_tokens, and api_keys.
- If the token is invalid or missing,
auth()will returnfalseforisAuthenticated. CheckisAuthenticatedbefore reading the other properties, likeuserId. - If the token is an
api_key, usesubjectto identify the user or Organization associated with the key. - If the token is valid,
isAuthenticatedistrue. This example includes pseudo-code that usessubjectfor API keys oruserIdfor session and OAuth tokens to get data from a database.
import { json } from '@tanstack/react-start'
import { createFileRoute } from '@tanstack/react-router'
import { auth } from '@clerk/tanstack-react-start/server'
export const ServerRoute = createFileRoute('/api/example')({
server: {
handlers: {
POST: async () => {
// Accept session_token, oauth_token, and api_key types
const authObject = await auth({
acceptsToken: ['session_token', 'oauth_token', 'api_key'],
})
// If the token is invalid or missing
if (!authObject.isAuthenticated) {
return json({ error: 'Unauthorized' }, { status: 401 })
}
// Check if the token is an api key and if it doesn't have the required scope
if (authObject.tokenType === 'api_key' && !authObject.scopes.includes('read:data')) {
return json({ error: 'API Key missing the "read:data" scope' }, { status: 401 })
}
// If the token is valid, move forward with the application logic
// This example includes pseudo-code for getting data from a database using the resource owner ID
const ownerId = authObject.tokenType === 'api_key' ? authObject.subject : authObject.userId
const data = db.select().from(resources).where(eq(resources.ownerId, ownerId))
return json({ data })
},
},
},
})Feedback
Last updated on