Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adamjmcgrath committed Jun 14, 2023
1 parent 62d4962 commit fab6609
Show file tree
Hide file tree
Showing 24 changed files with 3,919 additions and 3,363 deletions.
9 changes: 9 additions & 0 deletions jest-base.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('jest').Config} */
module.exports = {
rootDir: '.',
moduleFileExtensions: ['ts', 'tsx', 'js'],
preset: 'ts-jest/presets/js-with-ts',
globalSetup: './tests/global-setup.ts',
setupFilesAfterEnv: ['./tests/setup.ts'],
transformIgnorePatterns: ['/node_modules/(?!oauth4webapi)']
};
16 changes: 16 additions & 0 deletions jest-edge.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const base = require('./jest-base.config');

/** @type {import('jest').Config} */
module.exports = {
...base,
testEnvironment: '@edge-runtime/jest-environment',
testMatch: [
'**/tests/handlers/login.test.ts',
'**/tests/handlers/logout.test.ts',
'**/tests/handlers/callback.test.ts',
'**/tests/handlers/profile.test.ts',
'**/tests/http/auth0-next-request.test.ts',
'**/tests/http/auth0-next-response.test.ts',
'**/tests/helpers/with-middleware-auth-required.test.ts'
]
};
7 changes: 7 additions & 0 deletions jest-node.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const base = require('./jest-base.config');

/** @type {import('jest').Config} */
module.exports = {
...base,
testEnvironment: 'jest-environment-node-single-context'
};
4,085 changes: 2,291 additions & 1,794 deletions package-lock.json

Large diffs are not rendered by default.

21 changes: 5 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"jest": "^27.2.0",
"jest": "^27.5.1",
"jest-environment-node-single-context": "^27.3.0",
"next": "^13.4.5",
"nock": "^13.0.5",
Expand All @@ -114,7 +114,7 @@
"start-server-and-test": "^1.11.7",
"timekeeper": "^2.2.0",
"tough-cookie": "^4.0.0",
"ts-jest": "^27.0.5",
"ts-jest": "^27.1.5",
"typedoc": "^0.24.1",
"typescript": "^4.1.3"
},
Expand All @@ -133,13 +133,6 @@
"next": ">=10"
},
"jest": {
"testEnvironment": "jest-environment-node-single-context",
"rootDir": ".",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"collectCoverageFrom": [
"<rootDir>/src/**/*.*",
"!<rootDir>/src/edge.ts",
Expand All @@ -163,13 +156,9 @@
}
},
"coverageProvider": "v8",
"preset": "ts-jest/presets/js-with-ts",
"globalSetup": "./tests/global-setup.ts",
"setupFilesAfterEnv": [
"./tests/setup.ts"
],
"transformIgnorePatterns": [
"/node_modules/(?!oauth4webapi)"
"projects": [
"<rootDir>/jest-node.config.js",
"<rootDir>/jest-edge.config.js"
]
}
}
9 changes: 7 additions & 2 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 { DiscoveryError, IdentityProviderError } from '../utils/errors';
import { ApplicationError, DiscoveryError, IdentityProviderError } from '../utils/errors';
import { AccessTokenError, AccessTokenErrorCode } from '../../utils/errors';
import urlJoin from 'url-join';
import { Config } from '../config';
Expand Down Expand Up @@ -104,7 +104,12 @@ export class EdgeClient extends AbstractClient {
const [as, client] = await this.getClient();
const url =
req.getMethod().toUpperCase() === 'GET' ? new URL(req.getUrl()) : new URLSearchParams(await req.getBody());
const result = oauth.validateAuthResponse(as, client, url, expectedState);
let result: ReturnType<typeof oauth.validateAuthResponse>;
try {
result = oauth.validateAuthResponse(as, client, url, expectedState);
} catch (e) {
throw new ApplicationError(e);
}
if (oauth.isOAuth2Error(result)) {
throw new IdentityProviderError({
message: result.error_description || result.error,
Expand Down
10 changes: 9 additions & 1 deletion src/auth0-session/handlers/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,15 @@ export default function callbackHandlerFactory(
throw new MissingStateCookieError();
}

const callbackParams = await client.callbackParams(req, expectedState);
let callbackParams: URLSearchParams;
try {
callbackParams = await client.callbackParams(req, expectedState);
} catch (err) {
err.status = 400;
err.statusCode = 400;
err.openIdState = decodeState(expectedState);
throw err;
}

if (!callbackParams.get('state')) {
throw new MissingStateParamError();
Expand Down
4 changes: 2 additions & 2 deletions src/auth0-session/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export class EscapedError extends Error {

export class MissingStateParamError extends Error {
static message = 'Missing state parameter in Authorization Response.';
status = 404;
statusCode = 404;
status = 400;
statusCode = 400;

constructor() {
/* c8 ignore next */
Expand Down
4 changes: 2 additions & 2 deletions tests/auth0-session/fixtures/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { IncomingMessage, request as nodeHttpRequest } from 'http';
import { request as nodeHttpsRequest } from 'https';
import { Cookie, CookieJar } from 'tough-cookie';
import { signing } from '../../../src/auth0-session/utils/hkdf';
import { generateCookieValue } from '../../../src/auth0-session/utils/signed-cookies';
import { IncomingMessage, request as nodeHttpRequest } from 'http';
import { request as nodeHttpsRequest } from 'https';
import { ConfigParameters } from '../../../src/auth0-session';
import { base64url } from 'jose';

Expand Down
5 changes: 4 additions & 1 deletion tests/auth0-session/transient-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,17 @@ describe('TransientStore', () => {
it('should set SameSite=None, Secure=False for fallback cookie by default for http', async () => {
const baseURL: string = await setup(
defaultConfig,
(req: NodeRequest, res: NodeResponse) => transientStore.save('test_key', req, res, { value: 'foo' }),
(req: NodeRequest, res: NodeResponse) => {
return transientStore.save('test_key', req, res, { value: 'foo' });
},
false
);
const transientStore = new TransientStore(getConfig({ ...defaultConfig, baseURL }));
const cookieJar = new CookieJar();
const { value } = await get(baseURL, '/', { cookieJar });
const fallbackCookie = getCookie('_test_key', cookieJar, baseURL);
expect(value).toEqual(expect.any(String));
// TODO: figure out why this is sameSite 'none' (and why it's passing in main)
expect(fallbackCookie).toMatchObject({
sameSite: 'none',
secure: false,
Expand Down
8 changes: 4 additions & 4 deletions tests/fixtures/app-router-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import nock from 'nock';
import { default as nodeFetch } from 'node-fetch';
import { NextRequest, NextResponse } from 'next/server';
import {
Auth0Server,
CallbackOptions,
Expand All @@ -13,7 +14,6 @@ import {
import { initAuth0 as edgeInitAuth0 } from '../../src/edge';
import { withApi } from './default-settings';
import { setupNock } from './setup';
import { NextRequest, NextResponse } from 'next/server';
import { StatelessSession } from '../../src/auth0-session';
import { getConfig } from '../../src/config';
import { Auth0NextRequest } from '../../src/http';
Expand Down Expand Up @@ -120,14 +120,14 @@ export const getSession = async (config: any, res: NextResponse) => {

export const login = async (opts: LoginOpts = {}) => {
const state = encodeState({ returnTo: '/' });
const res = await getResponse({
return await getResponse({
...opts,
url: `/api/auth/callback?state=${state}&code=code`,
cookies: {
...opts.cookies,
state: await signCookie('state', state),
nonce: await signCookie('nonce', '__test_nonce__')
nonce: await signCookie('nonce', '__test_nonce__'),
code_verifier: await signCookie('code_verifier', '__test_code_verifier__')
}
});
return res;
};
17 changes: 10 additions & 7 deletions tests/fixtures/oidc-nocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ export function jwksEndpoint(params: ConfigParameters, keyset: JSONWebKeySet): n

export function codeExchange(params: ConfigParameters, idToken: string, code = 'code'): nock.Scope {
return nock(`${params.issuerBaseURL}`)
.post(
'/oauth/token',
`grant_type=authorization_code&code=${code}&redirect_uri=${encodeURIComponent(
`${params.baseURL}api/auth/callback`
)}`
)
.post('/oauth/token', (body: any) => {
return (
body.grant_type === 'authorization_code' &&
body.code === code &&
body.redirect_uri === `${params.baseURL}api/auth/callback`
);
})
.reply(200, {
access_token: 'eyJz93a...k4laUWw',
expires_in: 750,
Expand Down Expand Up @@ -145,7 +146,9 @@ export async function refreshTokenRotationExchange(
});

return nock(`${params.issuerBaseURL}`)
.post('/oauth/token', `grant_type=refresh_token&refresh_token=${refreshToken}`)
.post('/oauth/token', (body) => {
return body.grant_type === 'refresh_token' && body.refresh_token === refreshToken;
})
.reply(200, {
access_token: newToken || 'eyJz93a...k4laUWw',
refresh_token: newrefreshToken || 'GEbRxBN...edjnXbL',
Expand Down
Loading

0 comments on commit fab6609

Please sign in to comment.