Skip to content

Commit cca96e7

Browse files
committed
lots of improvements
1 parent 08edb92 commit cca96e7

File tree

16 files changed

+162
-166
lines changed

16 files changed

+162
-166
lines changed

epicshop/epic-me/app/routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ export default [
55
route('/authorize', 'routes/authorize.tsx'),
66
route('/healthcheck', 'routes/healthcheck.tsx'),
77
route('/db-api', 'routes/db-api.tsx'),
8-
route('/introspect', 'routes/introspect.tsx'),
8+
route('/introspect', 'routes/introspect.ts'),
99
route('/test-auth', 'routes/test-auth.tsx'),
1010
] satisfies RouteConfig

epicshop/epic-me/app/routes/authorize.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ const requestParamsSchema = z
2222
code_challenge: z.string(),
2323
code_challenge_method: z.string(),
2424
redirect_uri: z.string(),
25-
scope: z.string().array().optional().default([]),
25+
scope: z
26+
.string()
27+
.default('')
28+
.transform((s) => s.split(' ')),
2629
state: z.string().optional().default(''),
2730
})
2831
.passthrough()

epicshop/epic-me/app/routes/introspect.tsx renamed to epicshop/epic-me/app/routes/introspect.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1+
import { invariantResponse } from '@epic-web/invariant'
12
import { type Token } from '#types/helpers'
23
import { type Route } from './+types/introspect'
34

4-
export async function loader({ request, context }: Route.LoaderArgs) {
5-
const tokenInfo = await getTokenInfo(request, context.cloudflare.env)
6-
if (!tokenInfo) return new Response('Unauthorized', { status: 401 })
7-
8-
return Response.json({
9-
userId: tokenInfo.userId,
10-
clientId: tokenInfo.grant.clientId,
11-
scopes: tokenInfo.grant.scope,
12-
expiresAt: tokenInfo.expiresAt,
13-
})
14-
}
15-
16-
async function getTokenInfo(
17-
request: Request,
18-
env: Env,
19-
): Promise<Token | undefined> {
20-
const token = request.headers.get('authorization')?.slice('Bearer '.length)
21-
if (!token) return undefined
22-
return resolveTokenInfo(token, env)
5+
export async function introspectLoader({ request, context }: Route.LoaderArgs) {
6+
const token = (await request.formData()).get('token')?.toString()
7+
console.log({ token })
8+
invariantResponse(token, 'invalid_request')
9+
10+
const info = await resolveTokenInfo(token, context.cloudflare.env).catch(
11+
() => undefined,
12+
)
13+
14+
if (!info) return { active: false }
15+
16+
return {
17+
active: true,
18+
client_id: info.grant.clientId,
19+
scope: info.grant.scope.join(' '),
20+
sub: info.userId,
21+
exp: Math.floor(info.expiresAt / 1000), // if you store ms
22+
// aud, iss, token_type, iat ... add as useful
23+
}
2324
}
2425

2526
async function resolveTokenInfo(

epicshop/epic-me/package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

epicshop/epic-me/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
},
2222
"dependencies": {
2323
"@cloudflare/workers-oauth-provider": "^0.0.6",
24-
"zod": "^3.25.67",
24+
"@epic-web/invariant": "^1.0.0",
2525
"isbot": "^5.1.29",
2626
"react": "^19.1.1",
2727
"react-dom": "^19.1.1",
28-
"react-router": "^7.8.0"
28+
"react-router": "^7.8.0",
29+
"zod": "^3.25.67"
2930
},
3031
"devDependencies": {
3132
"@cloudflare/vite-plugin": "^1.11.2",

epicshop/epic-me/workers/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const oauthProvider = new OAuthProvider({
2727
authorizeEndpoint: '/authorize',
2828
tokenEndpoint: '/token',
2929
clientRegistrationEndpoint: '/register',
30+
scopesSupported: ['read', 'write'],
3031
})
3132

3233
export default {
@@ -36,6 +37,7 @@ export default {
3637
return {
3738
'Access-Control-Allow-Origin': '*',
3839
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
40+
'Access-Control-Allow-Headers': 'mcp-protocol-version',
3941
'Cross-Origin-Resource-Policy': 'cross-origin',
4042
}
4143
}

epicshop/epic-me/workers/utils.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ export function withCors({
1515

1616
// Handle CORS preflight requests
1717
if (request.method === 'OPTIONS') {
18-
return new Response(null, {
19-
status: 200,
20-
headers: mergeHeaders(corsHeaders, {
21-
'Access-Control-Max-Age': '86400',
22-
}),
18+
const headers = mergeHeaders(corsHeaders, {
19+
'Access-Control-Max-Age': '86400',
2320
})
21+
22+
return new Response(null, { status: 204, headers })
2423
}
2524

2625
// Call the original handler

exercises/03.initialize-flow/01.problem/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function withCors({
1616
// Handle CORS preflight requests
1717
if (request.method === 'OPTIONS') {
1818
return new Response(null, {
19-
status: 200,
19+
status: 204,
2020
headers: mergeHeaders(corsHeaders, {
2121
'Access-Control-Max-Age': '86400',
2222
}),

exercises/04.auth-requests/01.problem/src/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { z } from 'zod'
22
import { EPIC_ME_SERVER_URL } from './client.ts'
33

44
export type AuthInfo = Exclude<
5-
Awaited<ReturnType<typeof getAuthInfoFromOAuthFromRequest>>,
5+
Awaited<ReturnType<typeof getAuthInfo>>,
66
undefined
77
>
88

9-
export async function getAuthInfoFromOAuthFromRequest(request: Request) {
9+
export async function getAuthInfo(request: Request) {
1010
const authHeader = request.headers.get('authorization')
1111
if (!authHeader?.startsWith('Bearer ')) return undefined
1212

exercises/04.auth-requests/01.problem/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { McpAgent } from 'agents/mcp'
99
import {
1010
type AuthInfo,
11-
getAuthInfoFromOAuthFromRequest,
11+
getAuthInfo,
1212
handleOAuthAuthorizationServerRequest,
1313
handleOAuthProtectedResourceRequest,
1414
initiateOAuthFlow,
@@ -87,7 +87,7 @@ export default {
8787
return handleOAuthProtectedResourceRequest(request)
8888
}
8989

90-
const authInfo = await getAuthInfoFromOAuthFromRequest(request)
90+
const authInfo = await getAuthInfo(request)
9191

9292
if (!authInfo) return initiateOAuthFlow(request)
9393

0 commit comments

Comments
 (0)