@starportal/cf-workers-openid-connect
v0.1.1
Published
Provide OpenID connect for Cloudflare Workers
Downloads
15
Readme
Cloudflare Workers OpenID Connect
This package implements the minimum required logic to let Cloudflare Workers / Pages can support OpenID Connect authentication.
Installation
npm install @starportal/cf-workers-openid-connect
Usage
buildAuthenticator
The factory to create Authenticator
object
Will load client options from env
| Environment name | Description |
|--------------------------------------|-----------------------------------------------|
| OIDC_ISSUER
| The issuer url e.g. http://user.example.com
|
| OIDC_DISCOVERY_CACHE_TTL
| The fetch
cache when use discovery endpoint |
| OIDC_CLIENT_ID
| The application client ID |
| OIDC_CLIENT_SECRET
| The application secret |
| OIDC_CLIENT_REDIRECT_URI
| The callback url to redirect back |
| OIDC_CLIENT_AUTHORIZATION_ENDPOINT
| The authorization endpoint |
| OIDC_CLIENT_TOKEN_ENDPOINT
| The endpoint to exchange code |
| OIDC_CLIENT_KEYS_ENDPOINT
| The endpoint to get JWKS to verify ID token |
Examples
Add GET /oidc
nd GET /oidc/callback
to manage the flows
// functions/oidc/index.ts
// mounted to `GET /oidc`
import { buildAuthenticator } from '@starportal/cf-workers-openid-connect'
export async function onRequestGet({ request, env, data }) {
// The factory to build Authenticator from environment variable
const auth = buildAuthenticator(env)
try {
// If the endpoint is provided this is optional
await auth.discovery()
} catch(e: any) {
// Return error if issuer unavailable
return new Response(null, { status: 500 })
}
// Save state to verify response
const state = crypto.randomUUID()
await env.StateKV.put(`state-${state}`, state, { expirationTtl: ttl || 60 })
return auth.authorizeWith(state, ['openid', 'email']);
}
// functions/oidc/callback.ts
// mounted to `GET /oidc/callback`
import { JWT, buildAuthenticator, extractAuthReturn } from '@starportal/pages-openid-connect'
export async function onRequestGet({ request, env }) {
const auth = buildAuthenticator(env)
try {
await auth.discovery()
} catch(e: any) {
return new Response(null, { status: 500 })
}
const [code, state] = extractAuthReturn(request)
// Return state mismatch
const savedState = await env.StateKV.get(`state-${state}`)
if (sate != savedState) {
return new Response(null, { status: 401 })
}
// User reject authorize application
if(!code) {
return new Response(null, { status: 401 })
}
// Exchange ID Token
const token: JWT = await auth.exchange(code)
// Redirect user to `/`
const response = new Response(null, { status: 302, headers: new Headers() })
response.headers.append('Location', '/')
// Save ID token in your way
setCookieHelper(response, '_session', token.toJWT())
return response;
}