Skip to content

Commit

Permalink
[SDK-3887] Always honor auth0Logout config (#1104)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamjmcgrath authored Mar 13, 2023
2 parents ee0e5ad + ba6829e commit 765b835
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 20 deletions.
10 changes: 7 additions & 3 deletions src/auth0-session/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,12 @@ export default function get(config: Config, { name, version }: Telemetry): Clien
);
client[custom.clock_tolerance] = config.clockTolerance;

if (config.idpLogout && !issuer.end_session_endpoint) {
if (config.auth0Logout || (url.parse(issuer.metadata.issuer).hostname as string).match('\\.auth0\\.com$')) {
if (config.idpLogout) {
if (
config.auth0Logout ||
((url.parse(issuer.metadata.issuer).hostname as string).match('\\.auth0\\.com$') &&
config.auth0Logout !== false)
) {
Object.defineProperty(client, 'endSessionUrl', {
value(params: EndSessionParameters) {
const { id_token_hint, post_logout_redirect_uri, ...extraParams } = params;
Expand All @@ -128,7 +132,7 @@ export default function get(config: Config, { name, version }: Telemetry): Clien
return url.format(parsedUrl);
}
});
} else {
} else if (!issuer.end_session_endpoint) {
debug('the issuer does not support RP-Initiated Logout');
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/auth0-session/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface Config {
/**
* Boolean value to enable Auth0's logout feature.
*/
auth0Logout: boolean;
auth0Logout?: boolean;

/**
* URL parameters used when redirecting users to the authorization server to log in.
Expand Down
2 changes: 1 addition & 1 deletion src/auth0-session/get-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const paramsSchema = Joi.object({
})
.default()
.unknown(false),
auth0Logout: Joi.boolean().optional().default(false),
auth0Logout: Joi.boolean().optional(),
authorizationParams: Joi.object({
response_type: Joi.string().optional().valid('id_token', 'code id_token', 'code').default('id_token'),
scope: Joi.string()
Expand Down
2 changes: 1 addition & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface BaseConfig {
* Boolean value to enable Auth0's proprietary logout feature.
* Since this SDK is for Auth0, it's set to `true`by default.
*/
auth0Logout: boolean;
auth0Logout?: boolean;

/**
* URL parameters used when redirecting users to the authorization server to log in.
Expand Down
60 changes: 60 additions & 0 deletions tests/auth0-session/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,66 @@ describe('clientFactory', function () {
expect(client.id_token_signed_response_alg).toEqual('RS256');
});

it('should use discovered logout endpoint by default', async function () {
const client = await getClient({ ...defaultConfig, idpLogout: true });
expect(client.endSessionUrl({})).toEqual('https://op.example.com/session/end?client_id=__test_client_id__');
});

it('should use auth0 logout endpoint if configured', async function () {
const client = await getClient({ ...defaultConfig, idpLogout: true, auth0Logout: true });
expect(client.endSessionUrl({})).toEqual('https://op.example.com/v2/logout?client_id=__test_client_id__');
});

it('should use auth0 logout endpoint if domain is auth0.com', async function () {
nock('https://foo.auth0.com')
.get('/.well-known/openid-configuration')
.reply(200, { ...wellKnown, issuer: 'https://foo.auth0.com/' });
const client = await getClient({ ...defaultConfig, idpLogout: true, issuerBaseURL: 'https://foo.auth0.com' });
expect(client.endSessionUrl({})).toEqual('https://foo.auth0.com/v2/logout?client_id=__test_client_id__');
});

it('should use auth0 logout endpoint if domain is auth0.com and configured', async function () {
nock('https://foo.auth0.com')
.get('/.well-known/openid-configuration')
.reply(200, { ...wellKnown, issuer: 'https://foo.auth0.com/' });
const client = await getClient({
...defaultConfig,
issuerBaseURL: 'https://foo.auth0.com',
idpLogout: true,
auth0Logout: true
});
expect(client.endSessionUrl({})).toEqual('https://foo.auth0.com/v2/logout?client_id=__test_client_id__');
});

it('should use discovered logout endpoint if domain is auth0.com but configured with auth0logout false', async function () {
nock('https://foo.auth0.com')
.get('/.well-known/openid-configuration')
.reply(200, {
...wellKnown,
issuer: 'https://foo.auth0.com/',
end_session_endpoint: 'https://foo.auth0.com/oidc/logout'
});
const client = await getClient({
...defaultConfig,
issuerBaseURL: 'https://foo.auth0.com',
idpLogout: true,
auth0Logout: false
});
expect(client.endSessionUrl({})).toEqual('https://foo.auth0.com/oidc/logout?client_id=__test_client_id__');
});

it('should create client with no end_session_endpoint', async function () {
nock('https://op2.example.com')
.get('/.well-known/openid-configuration')
.reply(200, {
...wellKnown,
issuer: 'https://op2.example.com',
end_session_endpoint: undefined
});
const client = await getClient({ ...defaultConfig, issuerBaseURL: 'https://op2.example.com' });
expect(() => client.endSessionUrl({})).toThrowError();
});

it('should create custom logout for auth0', async function () {
nock('https://test.eu.auth0.com')
.get('/.well-known/openid-configuration')
Expand Down
14 changes: 5 additions & 9 deletions tests/auth0-session/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,19 @@ describe('Config', () => {
});
});

it('auth0Logout and idpLogout should default to false', () => {
it('auth0Logout should default to undefined and idpLogout should default to false', () => {
const config = getConfig(defaultConfig);
expect(config).toMatchObject({
auth0Logout: false,
idpLogout: false
});
expect(config.idpLogout).toBe(false);
expect(config.auth0Logout).toBeUndefined();
});

it('should not set auth0Logout to true when idpLogout is true', () => {
const config = getConfig({
...defaultConfig,
idpLogout: true
});
expect(config).toMatchObject({
auth0Logout: false,
idpLogout: true
});
expect(config.idpLogout).toBe(true);
expect(config.auth0Logout).toBeUndefined();
});

it('should set default route paths', () => {
Expand Down
33 changes: 28 additions & 5 deletions tests/handlers/logout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { setup, teardown, login } from '../fixtures/setup';
describe('logout handler', () => {
afterEach(teardown);

test('should redirect to the identity provider', async () => {
test('should redirect to auth0', async () => {
const baseUrl = await setup(withoutApi);
const cookieJar = await login(baseUrl);

Expand All @@ -30,7 +30,7 @@ describe('logout handler', () => {
});
});

test('should pass logout params to the identity provider', async () => {
test('should pass logout params to auth0', async () => {
const baseUrl = await setup(withoutApi, { logoutOptions: { logoutParams: { foo: 'bar' } } });
const cookieJar = await login(baseUrl);

Expand Down Expand Up @@ -74,7 +74,30 @@ describe('logout handler', () => {
});
});

test('should use end_session_endpoint if available', async () => {
test('should use end_session_endpoint when configured', async () => {
const baseUrl = await setup(
{ ...withoutApi, auth0Logout: false },
{
discoveryOptions: { end_session_endpoint: 'https://my-end-session-endpoint/logout' }
}
);
const cookieJar = await login(baseUrl);

const {
res: { statusCode, headers }
} = await get(baseUrl, '/api/auth/logout', {
cookieJar,
fullResponse: true
});

expect(statusCode).toBe(302);
expect(parseUrl(headers['location'])).toMatchObject({
host: 'my-end-session-endpoint',
pathname: '/logout'
});
});

test('should use auth0 logout by default even when end_session_endpoint is discovered', async () => {
const baseUrl = await setup(withoutApi, {
discoveryOptions: { end_session_endpoint: 'https://my-end-session-endpoint/logout' }
});
Expand All @@ -89,8 +112,8 @@ describe('logout handler', () => {

expect(statusCode).toBe(302);
expect(parseUrl(headers['location'])).toMatchObject({
host: 'my-end-session-endpoint',
pathname: '/logout'
host: 'acme.auth0.local',
pathname: '/v2/logout'
});
});

Expand Down

0 comments on commit 765b835

Please sign in to comment.