-
Notifications
You must be signed in to change notification settings - Fork 99
Open
Description
Here's what I'm doing right now (I've got React Router set up in my worker alongside @cloudflare/workers-oauth-provider):
import { invariantResponse } from '@epic-web/invariant'
import { type Token } from '#types/helpers'
import { type Route } from './+types/introspection.ts'
export async function action({ request, context }: Route.LoaderArgs) {
const token = (await request.formData()).get('token')?.toString()
invariantResponse(token, 'invalid_request')
const parts = token.split(':')
if (parts.length !== 3) return { active: false }
const [userId, grantId] = parts
const tokenId = await generateTokenId(token)
const tokenKey = `token:${userId}:${grantId}:${tokenId}`
const tokenData = await context.cloudflare.env.OAUTH_KV.get(tokenKey, {
type: 'json',
})
if (!tokenData) return { active: false }
const info = tokenData as Token
if (info.expiresAt * 1000 < Date.now()) {
return { active: false }
}
return {
active: true,
client_id: info.grant.clientId,
scope: info.grant.scope.join(' '),
sub: info.userId,
exp: info.expiresAt,
iat: info.createdAt,
}
}
// copied from @cloudflare/workers-oauth-provider
async function generateTokenId(token: string) {
const encoder = new TextEncoder()
const data = encoder.encode(token)
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
return hashHex
}It technically works, but I would rather not have to rely on undocumented tokenKey formats and copy/pasted code 😅
Even better if it could work like other auth providers so I could easily swap out this for WorkOS/etc if the code in my resource server were set up like this:
import { jwtVerify, createRemoteJWKSet } from 'jose';
const JWKS = createRemoteJWKSet(new URL('https://whatever.authkit.app/oauth2/jwks'));
// ...
async function verifyToken(req: Request) {
const token = req.headers.get('authorization')?.match(/^Bearer (.+)$/)?.[1];
// ...
const { payload } = await jwtVerify(token, JWKS, {
issuer: 'https://whatever.authkit.app',
});
// Use access token claims to populate request context.
// i.e. `const userId = payload.sub;`
// ...
}Metadata
Metadata
Assignees
Labels
No labels