-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
153 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export { createNextAuthAllAccess as default } from './pages/index.js' | ||
export { createNextAuthAllAccess as default } from './v4/index.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,51 @@ | ||
import type { NextAuthConfig } from 'next-auth' | ||
import fs from 'node:fs' | ||
import { createSessionCallback } from './callbacks.js' | ||
import { importPkcs8 } from './key.js' | ||
import type { CreateSigningFnsParameters } from './token.js' | ||
import type { HandlerOptions, NextAuthAllAccessOptions } from './types.js' | ||
import { isJsonWebKeySet } from './types.js' | ||
import { getIssuer, getOrigin, sanitizeKey } from './utils.js' | ||
|
||
/** | ||
* Wraps NextAuth with AllAccess code, which adds AllAccess endpoints and inserts | ||
* access tokens into the session object. | ||
*/ | ||
export function createInitializer(handler: any) { | ||
return (options: NextAuthAllAccessOptions) => { | ||
const _jwks = options.jwks | ||
const jwksPath = options.jwksPath ?? process.env['ALLACCESS_JWKS_PATH'] | ||
const privateKey = options.privateKey ?? process.env['ALLACCESS_PRIVATE_KEY'] | ||
export function createInitializerOptions(options: NextAuthAllAccessOptions) { | ||
const _jwks = options.jwks | ||
const jwksPath = options.jwksPath ?? process.env['ALLACCESS_JWKS_PATH'] | ||
const privateKey = options.privateKey ?? process.env['ALLACCESS_PRIVATE_KEY'] | ||
|
||
if ((!jwksPath && !_jwks) || !privateKey) { | ||
throw new Error('JWKS file path and private key are required') | ||
} | ||
|
||
let jwks | ||
|
||
if (jwksPath) { | ||
jwks = JSON.parse(fs.readFileSync(jwksPath, 'utf-8')) as unknown | ||
} else { | ||
jwks = _jwks | ||
} | ||
|
||
if (!isJsonWebKeySet(jwks)) { | ||
throw new Error('JWKS file is invalid') | ||
} | ||
if ((!jwksPath && !_jwks) || !privateKey) { | ||
throw new Error('JWKS file path and private key are required') | ||
} | ||
|
||
const kid = jwks.keys[0]?.kid | ||
let jwks | ||
|
||
if (!kid) { | ||
throw new Error('JWKS file is invalid') | ||
} | ||
if (jwksPath) { | ||
jwks = JSON.parse(fs.readFileSync(jwksPath, 'utf-8')) as unknown | ||
} else { | ||
jwks = _jwks | ||
} | ||
|
||
const issuer = getIssuer(options.issuer) | ||
if (!isJsonWebKeySet(jwks)) { | ||
throw new Error('JWKS file is invalid') | ||
} | ||
|
||
const handlerOptions: HandlerOptions = { | ||
issuer, | ||
origin: getOrigin(options.origin), | ||
jwks, | ||
} | ||
const kid = jwks.keys[0]?.kid | ||
|
||
const signingOptions: CreateSigningFnsParameters = { | ||
clients: options.clients, | ||
privateKey: importPkcs8(sanitizeKey(privateKey)), | ||
issuer, | ||
kid, | ||
} | ||
if (!kid) { | ||
throw new Error('JWKS file is invalid') | ||
} | ||
|
||
return (createNextAuth: (opt: NextAuthConfig) => any, nextAuthOptions: NextAuthConfig) => { | ||
const sessionCallback = createSessionCallback(signingOptions, nextAuthOptions) | ||
const issuer = getIssuer(options.issuer) | ||
|
||
nextAuthOptions.callbacks = { | ||
...nextAuthOptions.callbacks, | ||
session: sessionCallback, | ||
} | ||
const handlerOptions: HandlerOptions = { | ||
issuer, | ||
origin: getOrigin(options.origin), | ||
jwks, | ||
} | ||
|
||
return handler(handlerOptions, createNextAuth(nextAuthOptions)) | ||
} | ||
const signingOptions: CreateSigningFnsParameters = { | ||
clients: options.clients, | ||
privateKey: importPkcs8(sanitizeKey(privateKey)), | ||
issuer, | ||
kid, | ||
} | ||
|
||
return { handlerOptions, signingOptions } | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' | ||
import { NextAuthConfig } from 'next-auth' | ||
import { createSessionCallback } from '../callbacks.js' | ||
import jwksHandler from '../handlers/jwks.js' | ||
import openidConfigurationHandler from '../handlers/openid-configuration.js' | ||
import { createInitializerOptions } from '../next-auth-all-access.js' | ||
import type { HandlerOptions, NextAuthAllAccessOptions } from '../types.js' | ||
|
||
/** | ||
* Wrap NextAuth returning a v4-style API handler | ||
*/ | ||
function wrapNextAuth(options: HandlerOptions, nextAuth: NextApiHandler): NextApiHandler { | ||
return async (req: NextApiRequest, res: NextApiResponse) => { | ||
let { | ||
query: { nextauth: route }, | ||
} = req | ||
|
||
route = (Array.isArray(route) ? route : [route]).join('/') | ||
|
||
switch (route) { | ||
case 'all-access/jwks.json': { | ||
const response = jwksHandler(options) | ||
res.send(response) | ||
return | ||
} | ||
|
||
case 'all-access/.well-known/openid-configuration': { | ||
const response = openidConfigurationHandler(options) | ||
res.send(response) | ||
return | ||
} | ||
|
||
default: { | ||
await nextAuth(req, res) | ||
} | ||
} | ||
} | ||
} | ||
|
||
export const createNextAuthAllAccess = (options: NextAuthAllAccessOptions) => { | ||
const { handlerOptions, signingOptions } = createInitializerOptions(options) | ||
|
||
return ( | ||
createNextAuth: (options: Pick<NextAuthConfig, 'callbacks'>) => any, | ||
nextAuthOptions: Pick<NextAuthConfig, 'callbacks'>, | ||
): NextApiHandler => { | ||
const sessionCallback = createSessionCallback(signingOptions, nextAuthOptions) | ||
|
||
nextAuthOptions.callbacks = { | ||
...nextAuthOptions.callbacks, | ||
session: sessionCallback, | ||
} | ||
|
||
return wrapNextAuth(handlerOptions, createNextAuth(nextAuthOptions)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import type NextAuth from 'next-auth' | ||
import type { NextAuthConfig, NextAuthResult } from 'next-auth' | ||
import type { NextRequest } from 'next/server' | ||
import { createSessionCallback } from '../callbacks.js' | ||
import jwksHandler from '../handlers/jwks.js' | ||
import openidConfigurationHandler from '../handlers/openid-configuration.js' | ||
import { createInitializerOptions } from '../next-auth-all-access.js' | ||
import type { HandlerOptions, NextAuthAllAccessOptions } from '../types.js' | ||
|
||
/** | ||
* Wrap NextAuth returning a v5-style `NextAuthResult` | ||
*/ | ||
function wrapNextAuth(options: HandlerOptions, nextAuth: NextAuthResult) { | ||
const { GET } = nextAuth.handlers | ||
|
||
const getWrapper = async (req: NextRequest) => { | ||
const { pathname } = req.nextUrl | ||
|
||
if (pathname.endsWith('all-access/jwks.json')) { | ||
const response = jwksHandler(options) | ||
return Response.json(response) | ||
} | ||
|
||
if (pathname.endsWith('all-access/.well-known/openid-configuration')) { | ||
const response = openidConfigurationHandler(options) | ||
return Response.json(response) | ||
} | ||
|
||
return GET(req) | ||
} | ||
|
||
return { | ||
...nextAuth, | ||
handlers: { | ||
...nextAuth.handlers, | ||
GET: getWrapper, | ||
}, | ||
} | ||
} | ||
|
||
export const createNextAuthAllAccess = (options: NextAuthAllAccessOptions) => { | ||
const { handlerOptions, signingOptions } = createInitializerOptions(options) | ||
|
||
return (createNextAuth: typeof NextAuth, nextAuthOptions: NextAuthConfig): NextAuthResult => { | ||
const sessionCallback = createSessionCallback(signingOptions, nextAuthOptions) | ||
|
||
nextAuthOptions.callbacks = { | ||
...nextAuthOptions.callbacks, | ||
session: sessionCallback, | ||
} | ||
|
||
return wrapNextAuth(handlerOptions, createNextAuth(nextAuthOptions)) | ||
} | ||
} |