Skip to content

Commit

Permalink
Address feedback from @Widcket
Browse files Browse the repository at this point in the history
  • Loading branch information
adamjmcgrath committed Jun 28, 2023
1 parent 141ec7b commit 0bb1e4a
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 17 deletions.
10 changes: 7 additions & 3 deletions src/auth0-session/client/edge-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
EndSessionParameters,
Telemetry
} from './abstract-client';
import { ApplicationError, DiscoveryError, IdentityProviderError } from '../utils/errors';
import { ApplicationError, DiscoveryError, IdentityProviderError, UserInfoError } from '../utils/errors';
import { AccessTokenError, AccessTokenErrorCode } from '../../utils/errors';
import urlJoin from 'url-join';
import { Config } from '../config';
Expand Down Expand Up @@ -185,7 +185,7 @@ export class EdgeClient extends AbstractClient {
return auth0LogoutUrl.toString();
}
if (!as.end_session_endpoint) {
throw new Error('no rp inititated logout');
throw new Error('RP Initiated Logout is not supported on your Authorization Server.');
}
const oidcLogoutUrl = new URL(as.end_session_endpoint);
Object.entries(parameters).forEach(([key, value]: [string, string]) => {
Expand All @@ -203,7 +203,11 @@ export class EdgeClient extends AbstractClient {
const [as, client] = await this.getClient();
const response = await oauth.userInfoRequest(as, client, accessToken, this.httpOptions());

return oauth.processUserInfoResponse(as, client, oauth.skipSubjectCheck, response);
try {
return await oauth.processUserInfoResponse(as, client, oauth.skipSubjectCheck, response);
} catch (e) {
throw new UserInfoError(e.message);
}
}

async refresh(refreshToken: string, extras: { exchangeBody: Record<string, any> }): Promise<TokenEndpointResponse> {
Expand Down
8 changes: 6 additions & 2 deletions src/auth0-session/client/node-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
generators,
Issuer
} from 'openid-client';
import { ApplicationError, DiscoveryError, EscapedError, IdentityProviderError } from '../utils/errors';
import { ApplicationError, DiscoveryError, EscapedError, IdentityProviderError, UserInfoError } from '../utils/errors';
import { createPrivateKey } from 'crypto';
import { exportJWK } from 'jose';
import urlJoin from 'url-join';
Expand Down Expand Up @@ -202,7 +202,11 @@ export class NodeClient extends AbstractClient {

async userinfo(accessToken: string): Promise<Record<string, unknown>> {
const client = await this.getClient();
return client.userinfo(accessToken);
try {
return await client.userinfo(accessToken);
} catch (e) {
throw new UserInfoError(e.message);
}
}

async refresh(refreshToken: string, extras: { exchangeBody: Record<string, any> }): Promise<TokenEndpointResponse> {
Expand Down
8 changes: 8 additions & 0 deletions src/auth0-session/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ export class DiscoveryError extends EscapedError {
}
}

export class UserInfoError extends EscapedError {
constructor(msg: string) {
/* c8 ignore next */
super(`Userinfo request failing with: ${msg}`);
Object.setPrototypeOf(this, UserInfoError.prototype);
}
}

// eslint-disable-next-line max-len
// Basic escaping for putting untrusted data directly into the HTML body, per: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-1-html-encode-before-inserting-untrusted-data-into-html-element-content.
export function htmlSafe(input?: string): string | undefined {
Expand Down
6 changes: 2 additions & 4 deletions src/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import {
SessionCache,
UpdateSession,
WithApiAuthRequired,
WithPageAuthRequired
WithPageAuthRequired,
telemetry
} from './shared';
import { _initAuth } from './init';
import { setIsUsingNamedExports, setIsUsingOwnInstance } from './utils/instance-check';
import { getConfig, getLoginUrl } from './config';
import { withPageAuthRequiredFactory } from './helpers';
import { EdgeClient } from './auth0-session/client/edge-client';
import version from './version';
import { WithMiddlewareAuthRequired } from './helpers/with-middleware-auth-required';

const genId = () => {
Expand All @@ -29,8 +29,6 @@ const genId = () => {
.join('');
};

const telemetry = { name: 'nextjs-auth0', version };

let instance: Auth0Server & { sessionCache: SessionCache };

/**
Expand Down
6 changes: 2 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ import {
SessionCache,
UpdateSession,
WithApiAuthRequired,
WithPageAuthRequired
WithPageAuthRequired,
telemetry
} from './shared';
import { _initAuth } from './init';
import { setIsUsingNamedExports, setIsUsingOwnInstance } from './utils/instance-check';
import { getConfig, getLoginUrl } from './config';
import { withPageAuthRequiredFactory } from './helpers';
import { NodeClient } from './auth0-session/client/node-client';
import version from './version';

const genId = () => crypto.randomBytes(16).toString('hex');

const telemetry = { name: 'nextjs-auth0', version };

export type Auth0Server = Omit<Auth0ServerShared, 'withMiddlewareAuthRequired'>;

let instance: Auth0ServerShared & { sessionCache: SessionCache };
Expand Down
3 changes: 3 additions & 0 deletions src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { SessionCache, GetSession, GetAccessToken, Session, TouchSession, Update
import { WithApiAuthRequired, WithPageAuthRequired } from './helpers';
import { ConfigParameters } from './config';
import { WithMiddlewareAuthRequired } from './helpers/with-middleware-auth-required';
import version from './version';

export const telemetry = { name: 'nextjs-auth0', version };

/**
* The SDK server instance.
Expand Down
10 changes: 9 additions & 1 deletion src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,15 @@ export class AccessTokenError extends AuthError {
/**
* @ignore
*/
export type HandlerErrorCause = Error | AuthError | (Error & { status: number; statusCode: number });
interface HttpError extends Error {
status: number;
statusCode: number;
}

/**
* @ignore
*/
export type HandlerErrorCause = Error | AuthError | HttpError;

type HandlerErrorOptions = {
code: string;
Expand Down
9 changes: 9 additions & 0 deletions tests/auth0-session/client/edge-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { mockFetch } from '../../fixtures/app-router-helpers';
import { Auth0Request } from '../../../src/auth0-session/http';
import { readFileSync } from 'fs';
import { join } from 'path';
import { UserInfoError } from '../../../src/auth0-session/utils/errors';

class TestReq extends Auth0Request<null> {
constructor() {
Expand Down Expand Up @@ -283,6 +284,14 @@ describe('edge client', function () {
);
});

it('should throw UserInfoError when userinfo fails', async () => {
nock.cleanAll();
nock('https://op.example.com').get('/.well-known/openid-configuration').reply(200, wellKnown);
nock('https://op.example.com').get('/userinfo').reply(500, {});
const client = await getClient();
await expect(client.userinfo('__test_token__')).rejects.toThrow(UserInfoError);
});

it('should only support code flow', async () => {
await expect(getClient({ authorizationParams: { response_type: 'id_token' } })).rejects.toThrow(
'This SDK only supports `response_type=code` when used in an Edge runtime.'
Expand Down
8 changes: 8 additions & 0 deletions tests/auth0-session/client/node-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import pkg from '../../../package.json';
import wellKnown from '../fixtures/well-known.json';
import version from '../../../src/version';
import { NodeClient } from '../../../src/auth0-session/client/node-client';
import { UserInfoError } from '../../../src/auth0-session/utils/errors';

const defaultConfig = {
secret: '__test_session_secret__',
Expand Down Expand Up @@ -212,4 +213,11 @@ describe('node client', function () {
'Discovery requests failing for https://op.example.com, expected 200 OK, got: 500 Internal Server Error'
);
});

it('should throw UserInfoError when userinfo fails', async () => {
nock.cleanAll();
nock('https://op.example.com').get('/.well-known/openid-configuration').reply(200, wellKnown);
nock('https://op.example.com').get('/userinfo').reply(500, {});
await expect((await getClient()).userinfo('token')).rejects.toThrow(UserInfoError);
});
});
3 changes: 1 addition & 2 deletions tests/fixtures/app-router-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ const isEdgeRuntime =
export const initAuth0 = (config: ConfigParameters) => {
if (isEdgeRuntime) {
return edgeInitAuth0(config);
} else {
return nodeInitAuth0(config);
}
return nodeInitAuth0(config);
};

export const mockFetch = () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/handlers/login-page-router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Cookie, CookieJar } from 'tough-cookie';
describe('login handler (page router)', () => {
afterEach(teardown);

test('should create a state', async () => {
test('should create a state, nonce, and code verifier', async () => {
const baseUrl = await setup(withoutApi);
const cookieJar = new CookieJar();
await get(baseUrl, '/api/auth/login', { cookieJar });
Expand Down

0 comments on commit 0bb1e4a

Please sign in to comment.