feat(oidc-auth): allow setting audience for oidc-auth (#1010)
parent
28ff8ed22d
commit
e6160a2f94
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/oidc-auth': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add support for setting audience in the OIDC_AUDIENCE environment variable
|
|
@ -46,7 +46,7 @@ npm i hono @hono/oidc-auth
|
||||||
The middleware requires the following variables to be set as either environment variables or by calling `initOidcAuthMiddleware`:
|
The middleware requires the following variables to be set as either environment variables or by calling `initOidcAuthMiddleware`:
|
||||||
|
|
||||||
| Variable | Description | Default Value |
|
| Variable | Description | Default Value |
|
||||||
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| OIDC_AUTH_SECRET | The secret key used for signing the session JWT. It is used to verify the JWT in the cookie and prevent tampering. (Must be at least 32 characters long) | None, must be provided |
|
| OIDC_AUTH_SECRET | The secret key used for signing the session JWT. It is used to verify the JWT in the cookie and prevent tampering. (Must be at least 32 characters long) | None, must be provided |
|
||||||
| OIDC_AUTH_REFRESH_INTERVAL | The interval (in seconds) at which the session should be implicitly refreshed. | 15 \* 60 (15 minutes) |
|
| OIDC_AUTH_REFRESH_INTERVAL | The interval (in seconds) at which the session should be implicitly refreshed. | 15 \* 60 (15 minutes) |
|
||||||
| OIDC_AUTH_EXPIRES | The interval (in seconds) after which the session should be considered expired. Once expired, the user will be redirected to the IdP for re-authentication. | 60 _ 60 _ 24 (1 day) |
|
| OIDC_AUTH_EXPIRES | The interval (in seconds) after which the session should be considered expired. Once expired, the user will be redirected to the IdP for re-authentication. | 60 _ 60 _ 24 (1 day) |
|
||||||
|
@ -58,6 +58,7 @@ The middleware requires the following variables to be set as either environment
|
||||||
| OIDC_COOKIE_PATH | The path to which the `oidc-auth` cookie is set. Restrict to not send it with every request to your domain | / |
|
| OIDC_COOKIE_PATH | The path to which the `oidc-auth` cookie is set. Restrict to not send it with every request to your domain | / |
|
||||||
| OIDC_COOKIE_NAME | The name of the cookie to be set | `oidc-auth` |
|
| OIDC_COOKIE_NAME | The name of the cookie to be set | `oidc-auth` |
|
||||||
| OIDC_COOKIE_DOMAIN | The custom domain of the cookie. For example, set this like `example.com` to enable authentication across subdomains (e.g., `a.example.com` and `b.example.com`). | Domain of the request |
|
| OIDC_COOKIE_DOMAIN | The custom domain of the cookie. For example, set this like `example.com` to enable authentication across subdomains (e.g., `a.example.com` and `b.example.com`). | Domain of the request |
|
||||||
|
| OIDC_AUDIENCE | The audience for the access token | No default, optional. Primarily intended for use with Auth0. [`audience`](https://community.auth0.com/t/what-is-the-audience/71414) is required by Auth0 to receive a non-opaque access token, for other providers you may not need this. |
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ beforeEach(() => {
|
||||||
delete process.env.OIDC_COOKIE_PATH
|
delete process.env.OIDC_COOKIE_PATH
|
||||||
delete process.env.OIDC_COOKIE_NAME
|
delete process.env.OIDC_COOKIE_NAME
|
||||||
delete process.env.OIDC_COOKIE_DOMAIN
|
delete process.env.OIDC_COOKIE_DOMAIN
|
||||||
|
delete process.env.OIDC_AUDIENCE
|
||||||
})
|
})
|
||||||
describe('oidcAuthMiddleware()', () => {
|
describe('oidcAuthMiddleware()', () => {
|
||||||
test('Should respond with 200 OK if session is active', async () => {
|
test('Should respond with 200 OK if session is active', async () => {
|
||||||
|
@ -374,6 +375,27 @@ describe('oidcAuthMiddleware()', () => {
|
||||||
expect(res.status).toBe(302)
|
expect(res.status).toBe(302)
|
||||||
expect(res.headers.get('set-cookie')).toMatch(`Domain=${MOCK_COOKIE_DOMAIN}`)
|
expect(res.headers.get('set-cookie')).toMatch(`Domain=${MOCK_COOKIE_DOMAIN}`)
|
||||||
})
|
})
|
||||||
|
test('Should use custom audience if defined', async () => {
|
||||||
|
process.env.OIDC_AUDIENCE = 'audience'
|
||||||
|
const req = new Request('http://localhost/', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { cookie: `oidc-auth=${MOCK_JWT_EXPIRED_SESSION}` },
|
||||||
|
})
|
||||||
|
const res = await app.request(req, {}, {})
|
||||||
|
expect(res).not.toBeNull()
|
||||||
|
expect(res.status).toBe(302)
|
||||||
|
expect(res.headers.get('location')).toMatch(/audience=audience/)
|
||||||
|
})
|
||||||
|
test('Should not set audience if not defined', async () => {
|
||||||
|
const req = new Request('http://localhost/', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { cookie: `oidc-auth=${MOCK_JWT_EXPIRED_SESSION}` },
|
||||||
|
})
|
||||||
|
const res = await app.request(req, {}, {})
|
||||||
|
expect(res).not.toBeNull()
|
||||||
|
expect(res.status).toBe(302)
|
||||||
|
expect(res.headers.get('location')).not.toMatch(/audience=/)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
describe('processOAuthCallback()', () => {
|
describe('processOAuthCallback()', () => {
|
||||||
test('Should successfully process the OAuth2.0 callback and redirect to the continue URL', async () => {
|
test('Should successfully process the OAuth2.0 callback and redirect to the continue URL', async () => {
|
||||||
|
|
|
@ -58,6 +58,7 @@ export type OidcAuthEnv = {
|
||||||
OIDC_COOKIE_PATH?: string
|
OIDC_COOKIE_PATH?: string
|
||||||
OIDC_COOKIE_NAME?: string
|
OIDC_COOKIE_NAME?: string
|
||||||
OIDC_COOKIE_DOMAIN?: string
|
OIDC_COOKIE_DOMAIN?: string
|
||||||
|
OIDC_AUDIENCE?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,6 +94,7 @@ const setOidcAuthEnv = (c: Context, config?: Partial<OidcAuthEnv>) => {
|
||||||
OIDC_COOKIE_PATH: config?.OIDC_COOKIE_PATH ?? ev.OIDC_COOKIE_PATH,
|
OIDC_COOKIE_PATH: config?.OIDC_COOKIE_PATH ?? ev.OIDC_COOKIE_PATH,
|
||||||
OIDC_COOKIE_NAME: config?.OIDC_COOKIE_NAME ?? ev.OIDC_COOKIE_NAME,
|
OIDC_COOKIE_NAME: config?.OIDC_COOKIE_NAME ?? ev.OIDC_COOKIE_NAME,
|
||||||
OIDC_COOKIE_DOMAIN: config?.OIDC_COOKIE_DOMAIN ?? ev.OIDC_COOKIE_DOMAIN,
|
OIDC_COOKIE_DOMAIN: config?.OIDC_COOKIE_DOMAIN ?? ev.OIDC_COOKIE_DOMAIN,
|
||||||
|
OIDC_AUDIENCE: config?.OIDC_AUDIENCE ?? ev.OIDC_AUDIENCE,
|
||||||
}
|
}
|
||||||
if (oidcAuthEnv.OIDC_AUTH_SECRET === undefined) {
|
if (oidcAuthEnv.OIDC_AUTH_SECRET === undefined) {
|
||||||
throw new HTTPException(500, { message: 'Session secret is not provided' })
|
throw new HTTPException(500, { message: 'Session secret is not provided' })
|
||||||
|
@ -345,6 +347,9 @@ const generateAuthorizationRequestUrl = async (
|
||||||
authorizationRequestUrl.searchParams.set('access_type', 'offline')
|
authorizationRequestUrl.searchParams.set('access_type', 'offline')
|
||||||
authorizationRequestUrl.searchParams.set('prompt', 'consent')
|
authorizationRequestUrl.searchParams.set('prompt', 'consent')
|
||||||
}
|
}
|
||||||
|
if (env.OIDC_AUDIENCE) {
|
||||||
|
authorizationRequestUrl.searchParams.set('audience', env.OIDC_AUDIENCE)
|
||||||
|
}
|
||||||
return authorizationRequestUrl.toString()
|
return authorizationRequestUrl.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue