fastify-openid-auth
Advanced tools
Comparing version 5.0.0 to 5.1.0
@@ -0,1 +1,13 @@ | ||
# [5.1.0](https://github.com/mikaelkaron/fastify-openid-auth/compare/v5.0.0...v5.1.0) (2023-07-04) | ||
### Bug Fixes | ||
* **lint:** fix lint errors ([29fd586](https://github.com/mikaelkaron/fastify-openid-auth/commit/29fd58687d1948a566e5a9cf3706ec17ab803b66)) | ||
### Features | ||
* add `verified` to `write` ([d1dd878](https://github.com/mikaelkaron/fastify-openid-auth/commit/d1dd878c65c5259b1f5fecb6276c4860435aff15)) | ||
# [5.0.0](https://github.com/mikaelkaron/fastify-openid-auth/compare/v4.1.0...v5.0.0) (2023-06-29) | ||
@@ -2,0 +14,0 @@ |
@@ -1,4 +0,5 @@ | ||
import { RouteHandlerMethod } from 'fastify'; | ||
import { AuthorizationParameters, CallbackExtras, Client } from 'openid-client'; | ||
import { OpenIDWriteTokens } from './types'; | ||
import { type RouteHandlerMethod } from 'fastify'; | ||
import { type AuthorizationParameters, type CallbackExtras, type Client } from 'openid-client'; | ||
import { type OpenIDWriteTokens } from './types'; | ||
import { type OpenIDVerifyOptions } from './verify'; | ||
declare module 'fastify' { | ||
@@ -13,5 +14,3 @@ interface FastifyRequest { | ||
} | ||
export interface SessionData { | ||
[key: string]: any; | ||
} | ||
export type SessionData = Record<string, any>; | ||
export interface OpenIDLoginHandlerOptions { | ||
@@ -22,4 +21,6 @@ parameters?: AuthorizationParameters; | ||
sessionKey?: string; | ||
verify?: OpenIDVerifyOptions; | ||
write?: OpenIDWriteTokens; | ||
} | ||
export type OpenIDLoginHandlerFactory = (client: Client, options?: OpenIDLoginHandlerOptions) => RouteHandlerMethod; | ||
export declare const SessionKeyError: import("@fastify/error").FastifyErrorConstructor<{ | ||
@@ -37,2 +38,2 @@ code: "FST_SESSION_KEY"; | ||
}, [any?, any?, any?]>; | ||
export declare const openIDLoginHandlerFactory: (client: Client, options?: OpenIDLoginHandlerOptions) => RouteHandlerMethod; | ||
export declare const openIDLoginHandlerFactory: OpenIDLoginHandlerFactory; |
@@ -7,4 +7,6 @@ "use strict"; | ||
exports.openIDLoginHandlerFactory = exports.SupportedMethodError = exports.SessionValueError = exports.SessionKeyError = void 0; | ||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
const error_1 = __importDefault(require("@fastify/error")); | ||
const openid_client_1 = require("openid-client"); | ||
const verify_1 = require("./verify"); | ||
exports.SessionKeyError = (0, error_1.default)('FST_SESSION_KEY', 'client must have an issuer with an identifier', 500); | ||
@@ -59,3 +61,3 @@ exports.SessionValueError = (0, error_1.default)('FST_SESSION_VALUE', 'did not find expected authorization request details in req.session["%s"]', 500); | ||
: false; | ||
const { write } = { ...options }; | ||
const { verify, extras, write } = { ...options }; | ||
return async function openIDLoginHandler(request, reply) { | ||
@@ -104,4 +106,7 @@ const callbackParams = client.callbackParams(request.raw); | ||
request.session.set(sessionKey, undefined); | ||
const tokenset = await client.callback(redirect_uri, callbackParams, callbackChecks, options?.extras); | ||
return await write?.call(this, request, reply, tokenset); | ||
const tokenset = await client.callback(redirect_uri, callbackParams, callbackChecks, extras); | ||
const verified = verify !== undefined | ||
? await (0, verify_1.openIDJWTVerify)(tokenset, verify) | ||
: undefined; | ||
return await write?.call(this, request, reply, tokenset, verified); | ||
// #endregion | ||
@@ -108,0 +113,0 @@ }; |
@@ -1,9 +0,12 @@ | ||
import { RouteHandlerMethod } from 'fastify'; | ||
import { Client, EndSessionParameters } from 'openid-client'; | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types'; | ||
import { type RouteHandlerMethod } from 'fastify'; | ||
import { type Client, type EndSessionParameters } from 'openid-client'; | ||
import { type OpenIDReadTokens, type OpenIDWriteTokens } from './types'; | ||
import { type OpenIDVerifyOptions } from './verify'; | ||
export interface OpenIDLogoutHandlerOptions { | ||
parameters?: EndSessionParameters; | ||
verify?: OpenIDVerifyOptions; | ||
read: OpenIDReadTokens; | ||
write?: OpenIDWriteTokens; | ||
} | ||
export declare const openIDLogoutHandlerFactory: (client: Client, options: OpenIDLogoutHandlerOptions) => RouteHandlerMethod; | ||
export type OpenIDLogoutHandlerFactory = (client: Client, options: OpenIDLogoutHandlerOptions) => RouteHandlerMethod; | ||
export declare const openIDLogoutHandlerFactory: OpenIDLogoutHandlerFactory; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.openIDLogoutHandlerFactory = void 0; | ||
const openIDLogoutHandlerFactory = (client, options) => { | ||
const { parameters, read, write } = options; | ||
return async function openIDLogoutHandler(request, reply) { | ||
const tokenset = await read.call(this, request, reply); | ||
// #region authentication request | ||
if (Object.keys(request.query).length === 0) { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { id_token, session_state } = tokenset; | ||
if (id_token !== undefined) { | ||
return await reply.redirect(client.endSessionUrl({ | ||
id_token_hint: id_token, | ||
state: session_state, | ||
...parameters | ||
})); | ||
} | ||
const verify_1 = require("./verify"); | ||
const openIDLogoutHandlerFactory = (client, { parameters, verify, read, write }) => async function openIDLogoutHandler(request, reply) { | ||
const tokenset = await read.call(this, request, reply); | ||
// #region authentication request | ||
if (Object.keys(request.query).length === 0) { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { id_token, session_state } = tokenset; | ||
if (id_token !== undefined) { | ||
return await reply.redirect(client.endSessionUrl({ | ||
id_token_hint: id_token, | ||
state: session_state, | ||
...parameters | ||
})); | ||
} | ||
// #endregion | ||
// #region authentication response | ||
return await write?.call(this, request, reply, tokenset); | ||
// #endregion | ||
}; | ||
} | ||
// #endregion | ||
// #region authentication response | ||
const verified = verify !== undefined | ||
? await (0, verify_1.openIDJWTVerify)(tokenset, verify) | ||
: undefined; | ||
return await write?.call(this, request, reply, tokenset, verified); | ||
// #endregion | ||
}; | ||
exports.openIDLogoutHandlerFactory = openIDLogoutHandlerFactory; | ||
//# sourceMappingURL=logout.js.map |
@@ -1,7 +0,7 @@ | ||
import { FastifyPluginAsync, RouteHandlerMethod } from 'fastify'; | ||
import { Client } from 'openid-client'; | ||
import { OpenIDLoginHandlerOptions } from './login'; | ||
import { OpenIDLogoutHandlerOptions } from './logout'; | ||
import { OpenIDRefreshHandlerOptions } from './refresh'; | ||
import { OpenIDVerifyHandlerOptions } from './verify'; | ||
import { type FastifyPluginAsync, type RouteHandlerMethod } from 'fastify'; | ||
import { type Client } from 'openid-client'; | ||
import { type OpenIDLoginHandlerOptions } from './login'; | ||
import { type OpenIDLogoutHandlerOptions } from './logout'; | ||
import { type OpenIDRefreshHandlerOptions } from './refresh'; | ||
import { type OpenIDVerifyHandlerOptions } from './verify'; | ||
export interface FastifyOpenIDAuthPluginOptions { | ||
@@ -8,0 +8,0 @@ name: string; |
@@ -1,9 +0,12 @@ | ||
import { RouteHandlerMethod } from 'fastify'; | ||
import { Client, RefreshExtras } from 'openid-client'; | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types'; | ||
import { type RouteHandlerMethod } from 'fastify'; | ||
import { type Client, type RefreshExtras } from 'openid-client'; | ||
import { type OpenIDReadTokens, type OpenIDWriteTokens } from './types'; | ||
import { type OpenIDVerifyOptions } from './verify'; | ||
export interface OpenIDRefreshHandlerOptions { | ||
extras?: RefreshExtras; | ||
verify?: OpenIDVerifyOptions; | ||
read: OpenIDReadTokens; | ||
write?: OpenIDWriteTokens; | ||
} | ||
export declare const openIDRefreshHandlerFactory: (client: Client, options: OpenIDRefreshHandlerOptions) => RouteHandlerMethod; | ||
export type OpenIDRefreshHandlerFactory = (client: Client, options: OpenIDRefreshHandlerOptions) => RouteHandlerMethod; | ||
export declare const openIDRefreshHandlerFactory: OpenIDRefreshHandlerFactory; |
@@ -5,17 +5,18 @@ "use strict"; | ||
const openid_client_1 = require("openid-client"); | ||
const openIDRefreshHandlerFactory = (client, options) => { | ||
const { extras, read, write } = options; | ||
return async function openIDRefreshHandler(request, reply) { | ||
const oldTokenset = new openid_client_1.TokenSet(await read.call(this, request, reply)); | ||
if (oldTokenset.expired()) { | ||
request.log.trace(`OpenID token expired ${oldTokenset.expires_at !== undefined | ||
? new Date(oldTokenset.expires_at * 1000).toUTCString() | ||
: 'recently'}, refreshing`); | ||
const newTokenset = await client.refresh(oldTokenset, extras); | ||
request.log.trace('OpenID tokens refreshed'); | ||
return await write?.call(this, request, reply, newTokenset); | ||
} | ||
}; | ||
const verify_1 = require("./verify"); | ||
const openIDRefreshHandlerFactory = (client, { extras, verify, read, write }) => async function openIDRefreshHandler(request, reply) { | ||
const oldTokenset = new openid_client_1.TokenSet(await read.call(this, request, reply)); | ||
if (oldTokenset.expired()) { | ||
request.log.trace(`OpenID token expired ${oldTokenset.expires_at !== undefined | ||
? new Date(oldTokenset.expires_at * 1000).toUTCString() | ||
: 'recently'}, refreshing`); | ||
const newTokenset = await client.refresh(oldTokenset, extras); | ||
const verified = verify !== undefined | ||
? await (0, verify_1.openIDJWTVerify)(newTokenset, verify) | ||
: undefined; | ||
request.log.trace('OpenID tokens refreshed'); | ||
return await write?.call(this, request, reply, newTokenset, verified); | ||
} | ||
}; | ||
exports.openIDRefreshHandlerFactory = openIDRefreshHandlerFactory; | ||
//# sourceMappingURL=refresh.js.map |
@@ -1,4 +0,6 @@ | ||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; | ||
import { TokenSetParameters } from 'openid-client'; | ||
import { type FastifyInstance, type FastifyReply, type FastifyRequest } from 'fastify'; | ||
import { type JWTVerifyResult } from 'jose'; | ||
import { type TokenSetParameters } from 'openid-client'; | ||
export type OpenIDTokens = keyof Pick<TokenSetParameters, 'id_token' | 'access_token' | 'refresh_token'>; | ||
export type OpenIDReadTokens = (this: FastifyInstance, request: FastifyRequest, reply: FastifyReply) => Promise<TokenSetParameters> | TokenSetParameters; | ||
export type OpenIDWriteTokens = (this: FastifyInstance, request: FastifyRequest, reply: FastifyReply, tokenset: TokenSetParameters) => Promise<void> | void; | ||
export type OpenIDWriteTokens = (this: FastifyInstance, request: FastifyRequest, reply: FastifyReply, tokenset: TokenSetParameters, verified?: Map<OpenIDTokens, JWTVerifyResult>) => Promise<void> | void; |
@@ -1,13 +0,17 @@ | ||
import { RouteHandlerMethod } from 'fastify'; | ||
import { JWTVerifyGetKey, JWTVerifyOptions, KeyLike } from 'jose'; | ||
import { TokenSetParameters } from 'openid-client'; | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types'; | ||
export type OpenIDVerifyTokens = keyof Pick<TokenSetParameters, 'id_token' | 'access_token' | 'refresh_token'>; | ||
export interface OpenIDVerifyHandlerOptions { | ||
import { type RouteHandlerMethod } from 'fastify'; | ||
import { type JWTVerifyGetKey, type JWTVerifyOptions, type JWTVerifyResult, type KeyLike } from 'jose'; | ||
import { type TokenSetParameters } from 'openid-client'; | ||
import { type OpenIDReadTokens, type OpenIDTokens, type OpenIDWriteTokens } from './types'; | ||
export interface OpenIDVerifyOptions { | ||
options?: JWTVerifyOptions; | ||
key: JWTVerifyGetKey | KeyLike | Uint8Array; | ||
tokens?: OpenIDVerifyTokens[]; | ||
tokens: OpenIDTokens[]; | ||
} | ||
export type OpenIDJWTVerify = (tokenset: TokenSetParameters, options: OpenIDVerifyOptions) => Promise<Map<OpenIDTokens, JWTVerifyResult>>; | ||
export declare const openIDJWTVerify: OpenIDJWTVerify; | ||
export interface OpenIDVerifyHandlerOptions extends OpenIDVerifyOptions { | ||
read: OpenIDReadTokens; | ||
write?: OpenIDWriteTokens; | ||
} | ||
export declare const openIDVerifyHandlerFactory: (options: OpenIDVerifyHandlerOptions) => RouteHandlerMethod; | ||
export type OpenIDVerifyHandlerFactory = ({ options, key, tokens, read, write }: OpenIDVerifyHandlerOptions) => RouteHandlerMethod; | ||
export declare const openIDVerifyHandlerFactory: OpenIDVerifyHandlerFactory; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.openIDVerifyHandlerFactory = void 0; | ||
exports.openIDVerifyHandlerFactory = exports.openIDJWTVerify = void 0; | ||
const jose_1 = require("jose"); | ||
const openIDVerifyHandlerFactory = (options) => { | ||
const { options: jwtVerifyOptions, key, tokens = ['id_token'], read, write } = options; | ||
return async function openIDVerify(request, reply) { | ||
const tokenset = await read.call(this, request, reply); | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
for (const token of tokens) { | ||
const jwt = tokenset[token]; | ||
if (jwt !== undefined) { | ||
key instanceof Function | ||
? await (0, jose_1.jwtVerify)(jwt, key, jwtVerifyOptions) | ||
: await (0, jose_1.jwtVerify)(jwt, key, jwtVerifyOptions); | ||
} | ||
const openIDJWTVerify = async (tokenset, { key, options, tokens }) => { | ||
const verified = new Map(); | ||
for (const token of tokens) { | ||
const jwt = tokenset[token]; | ||
if (jwt !== undefined) { | ||
const result = key instanceof Function | ||
? await (0, jose_1.jwtVerify)(jwt, key, options) | ||
: await (0, jose_1.jwtVerify)(jwt, key, options); | ||
verified.set(token, result); | ||
} | ||
return await write?.call(this, request, reply, tokenset); | ||
}; | ||
} | ||
return verified; | ||
}; | ||
exports.openIDJWTVerify = openIDJWTVerify; | ||
const openIDVerifyHandlerFactory = ({ read, write, ...verify }) => async function openIDVerifyHandler(request, reply) { | ||
const tokenset = await read.call(this, request, reply); | ||
const verified = await (0, exports.openIDJWTVerify)(tokenset, verify); | ||
return await write?.call(this, request, reply, tokenset, verified); | ||
}; | ||
exports.openIDVerifyHandlerFactory = openIDVerifyHandlerFactory; | ||
//# sourceMappingURL=verify.js.map |
{ | ||
"name": "fastify-openid-auth", | ||
"version": "5.0.0", | ||
"version": "5.1.0", | ||
"description": "Fastify auth plugin for openid-client", | ||
@@ -38,3 +38,3 @@ "main": "dist/index.js", | ||
"eslint": "^8", | ||
"eslint-config-standard-with-typescript": "^35", | ||
"eslint-config-standard-with-typescript": "^36", | ||
"semantic-release": "^21", | ||
@@ -41,0 +41,0 @@ "shx": "^0", |
/* eslint-disable @typescript-eslint/naming-convention */ | ||
import { RouteHandlerMethod } from 'fastify' | ||
import createError from '@fastify/error' | ||
import { type RouteHandlerMethod } from 'fastify' | ||
import { | ||
AuthorizationParameters, | ||
CallbackExtras, | ||
Client, | ||
generators, | ||
Issuer, | ||
OpenIDCallbackChecks | ||
type AuthorizationParameters, | ||
type CallbackExtras, | ||
type Client, | ||
type Issuer, | ||
type OpenIDCallbackChecks | ||
} from 'openid-client' | ||
import { OpenIDWriteTokens } from './types' | ||
import { type OpenIDWriteTokens } from './types' | ||
import { openIDJWTVerify, type OpenIDVerifyOptions } from './verify' | ||
@@ -27,5 +28,3 @@ declare module 'fastify' { | ||
export interface SessionData { | ||
[key: string]: any | ||
} | ||
export type SessionData = Record<string, any> | ||
@@ -37,5 +36,11 @@ export interface OpenIDLoginHandlerOptions { | ||
sessionKey?: string | ||
verify?: OpenIDVerifyOptions | ||
write?: OpenIDWriteTokens | ||
} | ||
export type OpenIDLoginHandlerFactory = ( | ||
client: Client, | ||
options?: OpenIDLoginHandlerOptions | ||
) => RouteHandlerMethod | ||
export const SessionKeyError = createError( | ||
@@ -102,6 +107,6 @@ 'FST_SESSION_KEY', | ||
export const openIDLoginHandlerFactory = ( | ||
client: Client, | ||
options?: OpenIDLoginHandlerOptions | ||
): RouteHandlerMethod => { | ||
export const openIDLoginHandlerFactory: OpenIDLoginHandlerFactory = ( | ||
client, | ||
options | ||
) => { | ||
const redirect_uri = | ||
@@ -122,3 +127,3 @@ options?.parameters?.redirect_uri !== undefined | ||
const { write } = { ...options } | ||
const { verify, extras, write } = { ...options } | ||
@@ -191,7 +196,10 @@ return async function openIDLoginHandler (request, reply) { | ||
callbackChecks, | ||
options?.extras | ||
extras | ||
) | ||
return await write?.call(this, request, reply, tokenset) | ||
const verified = verify !== undefined | ||
? await openIDJWTVerify(tokenset, verify) | ||
: undefined | ||
return await write?.call(this, request, reply, tokenset, verified) | ||
// #endregion | ||
} | ||
} |
@@ -1,7 +0,9 @@ | ||
import { RouteHandlerMethod } from 'fastify' | ||
import { Client, EndSessionParameters } from 'openid-client' | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types' | ||
import { type RouteHandlerMethod } from 'fastify' | ||
import { type Client, type EndSessionParameters } from 'openid-client' | ||
import { type OpenIDReadTokens, type OpenIDWriteTokens } from './types' | ||
import { type OpenIDVerifyOptions, openIDJWTVerify } from './verify' | ||
export interface OpenIDLogoutHandlerOptions { | ||
parameters?: EndSessionParameters | ||
verify?: OpenIDVerifyOptions | ||
read: OpenIDReadTokens | ||
@@ -11,31 +13,40 @@ write?: OpenIDWriteTokens | ||
export const openIDLogoutHandlerFactory = ( | ||
export type OpenIDLogoutHandlerFactory = ( | ||
client: Client, | ||
options: OpenIDLogoutHandlerOptions | ||
): RouteHandlerMethod => { | ||
const { parameters, read, write } = options | ||
) => RouteHandlerMethod | ||
return async function openIDLogoutHandler (request, reply) { | ||
const tokenset = await read.call(this, request, reply) | ||
export const openIDLogoutHandlerFactory: OpenIDLogoutHandlerFactory = ( | ||
client, | ||
{ | ||
parameters, | ||
verify, | ||
read, | ||
write | ||
} | ||
) => async function openIDLogoutHandler (request, reply) { | ||
const tokenset = await read.call(this, request, reply) | ||
// #region authentication request | ||
if (Object.keys(request.query as object).length === 0) { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { id_token, session_state } = tokenset | ||
if (id_token !== undefined) { | ||
return await reply.redirect( | ||
client.endSessionUrl({ | ||
id_token_hint: id_token, | ||
state: session_state, | ||
...parameters | ||
}) | ||
) | ||
} | ||
// #region authentication request | ||
if (Object.keys(request.query as object).length === 0) { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { id_token, session_state } = tokenset | ||
if (id_token !== undefined) { | ||
return await reply.redirect( | ||
client.endSessionUrl({ | ||
id_token_hint: id_token, | ||
state: session_state, | ||
...parameters | ||
}) | ||
) | ||
} | ||
// #endregion | ||
} | ||
// #endregion | ||
// #region authentication response | ||
return await write?.call(this, request, reply, tokenset) | ||
// #endregion | ||
} | ||
// #region authentication response | ||
const verified = verify !== undefined | ||
? await openIDJWTVerify(tokenset, verify) | ||
: undefined | ||
return await write?.call(this, request, reply, tokenset, verified) | ||
// #endregion | ||
} |
@@ -1,16 +0,16 @@ | ||
import { FastifyPluginAsync, RouteHandlerMethod } from 'fastify' | ||
import { type FastifyPluginAsync, type RouteHandlerMethod } from 'fastify' | ||
import fp from 'fastify-plugin' | ||
import { Client } from 'openid-client' | ||
import { openIDLoginHandlerFactory, OpenIDLoginHandlerOptions } from './login' | ||
import { type Client } from 'openid-client' | ||
import { openIDLoginHandlerFactory, type OpenIDLoginHandlerOptions } from './login' | ||
import { | ||
openIDLogoutHandlerFactory, | ||
OpenIDLogoutHandlerOptions | ||
type OpenIDLogoutHandlerOptions | ||
} from './logout' | ||
import { | ||
openIDRefreshHandlerFactory, | ||
OpenIDRefreshHandlerOptions | ||
type OpenIDRefreshHandlerOptions | ||
} from './refresh' | ||
import { | ||
openIDVerifyHandlerFactory, | ||
OpenIDVerifyHandlerOptions | ||
type OpenIDVerifyHandlerOptions | ||
} from './verify' | ||
@@ -17,0 +17,0 @@ |
@@ -1,7 +0,9 @@ | ||
import { RouteHandlerMethod } from 'fastify' | ||
import { Client, RefreshExtras, TokenSet } from 'openid-client' | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types' | ||
import { type RouteHandlerMethod } from 'fastify' | ||
import { TokenSet, type Client, type RefreshExtras } from 'openid-client' | ||
import { type OpenIDReadTokens, type OpenIDWriteTokens } from './types' | ||
import { type OpenIDVerifyOptions, openIDJWTVerify } from './verify' | ||
export interface OpenIDRefreshHandlerOptions { | ||
extras?: RefreshExtras | ||
verify?: OpenIDVerifyOptions | ||
read: OpenIDReadTokens | ||
@@ -11,23 +13,31 @@ write?: OpenIDWriteTokens | ||
export const openIDRefreshHandlerFactory = ( | ||
export type OpenIDRefreshHandlerFactory = ( | ||
client: Client, | ||
options: OpenIDRefreshHandlerOptions | ||
): RouteHandlerMethod => { | ||
const { extras, read, write } = options | ||
) => RouteHandlerMethod | ||
return async function openIDRefreshHandler (request, reply) { | ||
const oldTokenset = new TokenSet(await read.call(this, request, reply)) | ||
if (oldTokenset.expired()) { | ||
request.log.trace( | ||
`OpenID token expired ${ | ||
oldTokenset.expires_at !== undefined | ||
? new Date(oldTokenset.expires_at * 1000).toUTCString() | ||
: 'recently' | ||
}, refreshing` | ||
) | ||
const newTokenset = await client.refresh(oldTokenset, extras) | ||
request.log.trace('OpenID tokens refreshed') | ||
return await write?.call(this, request, reply, newTokenset) | ||
} | ||
export const openIDRefreshHandlerFactory: OpenIDRefreshHandlerFactory = ( | ||
client, | ||
{ | ||
extras, | ||
verify, | ||
read, | ||
write | ||
} | ||
) => async function openIDRefreshHandler (request, reply) { | ||
const oldTokenset = new TokenSet(await read.call(this, request, reply)) | ||
if (oldTokenset.expired()) { | ||
request.log.trace( | ||
`OpenID token expired ${oldTokenset.expires_at !== undefined | ||
? new Date(oldTokenset.expires_at * 1000).toUTCString() | ||
: 'recently' | ||
}, refreshing` | ||
) | ||
const newTokenset = await client.refresh(oldTokenset, extras) | ||
const verified = verify !== undefined | ||
? await openIDJWTVerify(newTokenset, verify) | ||
: undefined | ||
request.log.trace('OpenID tokens refreshed') | ||
return await write?.call(this, request, reply, newTokenset, verified) | ||
} | ||
} |
@@ -1,4 +0,10 @@ | ||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify' | ||
import { TokenSetParameters } from 'openid-client' | ||
import { type FastifyInstance, type FastifyReply, type FastifyRequest } from 'fastify' | ||
import { type JWTVerifyResult } from 'jose' | ||
import { type TokenSetParameters } from 'openid-client' | ||
export type OpenIDTokens = keyof Pick< | ||
TokenSetParameters, | ||
'id_token' | 'access_token' | 'refresh_token' | ||
> | ||
export type OpenIDReadTokens = ( | ||
@@ -14,3 +20,4 @@ this: FastifyInstance, | ||
reply: FastifyReply, | ||
tokenset: TokenSetParameters | ||
tokenset: TokenSetParameters, | ||
verified?: Map<OpenIDTokens, JWTVerifyResult> | ||
) => Promise<void> | void |
@@ -1,15 +0,29 @@ | ||
import { RouteHandlerMethod } from 'fastify' | ||
import { jwtVerify, JWTVerifyGetKey, JWTVerifyOptions, KeyLike } from 'jose' | ||
import { TokenSetParameters } from 'openid-client' | ||
import { OpenIDReadTokens, OpenIDWriteTokens } from './types' | ||
import { type RouteHandlerMethod } from 'fastify' | ||
import { jwtVerify, type JWTVerifyGetKey, type JWTVerifyOptions, type JWTVerifyResult, type KeyLike } from 'jose' | ||
import { type TokenSetParameters } from 'openid-client' | ||
import { type OpenIDReadTokens, type OpenIDTokens, type OpenIDWriteTokens } from './types' | ||
export type OpenIDVerifyTokens = keyof Pick< | ||
TokenSetParameters, | ||
'id_token' | 'access_token' | 'refresh_token' | ||
> | ||
export interface OpenIDVerifyHandlerOptions { | ||
export interface OpenIDVerifyOptions { | ||
options?: JWTVerifyOptions | ||
key: JWTVerifyGetKey | KeyLike | Uint8Array | ||
tokens?: OpenIDVerifyTokens[] | ||
tokens: OpenIDTokens[] | ||
} | ||
export type OpenIDJWTVerify = (tokenset: TokenSetParameters, options: OpenIDVerifyOptions) => Promise<Map<OpenIDTokens, JWTVerifyResult>> | ||
export const openIDJWTVerify: OpenIDJWTVerify = async (tokenset, { key, options, tokens }) => { | ||
const verified = new Map<OpenIDTokens, JWTVerifyResult>() | ||
for (const token of tokens) { | ||
const jwt = tokenset[token] | ||
if (jwt !== undefined) { | ||
const result = key instanceof Function | ||
? await jwtVerify(jwt, key, options) | ||
: await jwtVerify(jwt, key, options) | ||
verified.set(token, result) | ||
} | ||
} | ||
return verified | ||
} | ||
export interface OpenIDVerifyHandlerOptions extends OpenIDVerifyOptions { | ||
read: OpenIDReadTokens | ||
@@ -19,26 +33,22 @@ write?: OpenIDWriteTokens | ||
export const openIDVerifyHandlerFactory = ( | ||
options: OpenIDVerifyHandlerOptions | ||
): RouteHandlerMethod => { | ||
const { | ||
options: jwtVerifyOptions, | ||
export type OpenIDVerifyHandlerFactory = ( | ||
{ | ||
options, | ||
key, | ||
tokens = ['id_token'], | ||
tokens, | ||
read, | ||
write | ||
} = options | ||
}: OpenIDVerifyHandlerOptions | ||
) => RouteHandlerMethod | ||
return async function openIDVerify (request, reply) { | ||
const tokenset = await read.call(this, request, reply) | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
for (const token of tokens) { | ||
const jwt = tokenset[token] | ||
if (jwt !== undefined) { | ||
key instanceof Function | ||
? await jwtVerify(jwt, key, jwtVerifyOptions) | ||
: await jwtVerify(jwt, key, jwtVerifyOptions) | ||
} | ||
} | ||
return await write?.call(this, request, reply, tokenset) | ||
export const openIDVerifyHandlerFactory: OpenIDVerifyHandlerFactory = ( | ||
{ | ||
read, | ||
write, | ||
...verify | ||
} | ||
) => async function openIDVerifyHandler (request, reply) { | ||
const tokenset = await read.call(this, request, reply) | ||
const verified = await openIDJWTVerify(tokenset, verify) | ||
return await write?.call(this, request, reply, tokenset, verified) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
57176
778