Skip to content

Commit

Permalink
fix(adapter-nextjs): wrong spot for checking app origin and auth conf…
Browse files Browse the repository at this point in the history
…ig (#14119)
  • Loading branch information
HuiSF authored Jan 8, 2025
1 parent 4ad8e92 commit 7499b16
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,45 +75,49 @@ describe('createAuthRoutesHandlersFactory', () => {
mockIsValidOrigin.mockReturnValue(true);
});

it('throws an error if the `amplifyAppOrigin` param has value of `undefined`', () => {
expect(() =>
createAuthRouteHandlersFactory({
describe('the created createAuthRouteHandlers function', () => {
it('throws an error if the AMPLIFY_APP_ORIGIN environment variable is not defined', () => {
const throwingFunc = createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
amplifyAppOrigin: undefined,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
}),
).toThrow('Could not find the AMPLIFY_APP_ORIGIN environment variable.');
});
});
expect(() => throwingFunc()).toThrow(
'Could not find the AMPLIFY_APP_ORIGIN environment variable.',
);
});

it('throws an error if the AMPLIFY_APP_ORIGIN environment variable is invalid', () => {
mockIsValidOrigin.mockReturnValueOnce(false);
expect(() =>
createAuthRouteHandlersFactory({
it('throws an error if the AMPLIFY_APP_ORIGIN environment variable is invalid', () => {
mockIsValidOrigin.mockReturnValueOnce(false);
const throwingFunc = createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
amplifyAppOrigin: 'domain-without-protocol.com',
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
}),
).toThrow(
'AMPLIFY_APP_ORIGIN environment variable contains an invalid origin string.',
);
});

it('calls config assertion functions to validate the Auth configuration', () => {
createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
amplifyAppOrigin: AMPLIFY_APP_ORIGIN,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});
expect(() => throwingFunc()).toThrow(
'AMPLIFY_APP_ORIGIN environment variable contains an invalid origin string.',
);
});

expect(mockAssertTokenProviderConfig).toHaveBeenCalledWith(
mockAmplifyConfig.Auth?.Cognito,
);
expect(mockAssertOAuthConfig).toHaveBeenCalledWith(
mockAmplifyConfig.Auth!.Cognito,
);
it('calls config assertion functions to validate the Auth configuration', () => {
const func = createAuthRouteHandlersFactory({
config: mockAmplifyConfig,
runtimeOptions: mockRuntimeOptions,
amplifyAppOrigin: AMPLIFY_APP_ORIGIN,
runWithAmplifyServerContext: mockRunWithAmplifyServerContext,
});

func();

expect(mockAssertTokenProviderConfig).toHaveBeenCalledWith(
mockAmplifyConfig.Auth?.Cognito,
);
expect(mockAssertOAuthConfig).toHaveBeenCalledWith(
mockAmplifyConfig.Auth!.Cognito,
);
});
});

describe('the created route handler function', () => {
Expand Down
99 changes: 64 additions & 35 deletions packages/adapter-nextjs/src/auth/createAuthRouteHandlersFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {
assertTokenProviderConfig,
} from '@aws-amplify/core/internals/utils';
import { NextApiRequest, NextApiResponse } from 'next';
import { AmplifyServerContextError } from '@aws-amplify/core/internals/adapter-core';
import {
AmplifyServerContextError,
CookieStorage,
} from '@aws-amplify/core/internals/adapter-core';
import { OAuthConfig } from '@aws-amplify/core';

import {
AuthRoutesHandlerContext,
Expand All @@ -31,35 +35,23 @@ export const createAuthRouteHandlersFactory = ({
amplifyAppOrigin,
runWithAmplifyServerContext,
}: CreateAuthRouteHandlersFactoryInput): InternalCreateAuthRouteHandlers => {
if (!amplifyAppOrigin) {
throw new AmplifyServerContextError({
message: 'Could not find the AMPLIFY_APP_ORIGIN environment variable.',
recoverySuggestion:
'Add the AMPLIFY_APP_ORIGIN environment variable to the `.env` file of your Next.js project.',
});
}

if (!isValidOrigin(amplifyAppOrigin)) {
throw new AmplifyServerContextError({
message:
'AMPLIFY_APP_ORIGIN environment variable contains an invalid origin string.',
recoverySuggestion:
'Ensure the AMPLIFY_APP_ORIGIN environment variable is a valid origin string.',
});
}

assertTokenProviderConfig(resourcesConfig.Auth?.Cognito);
assertOAuthConfig(resourcesConfig.Auth.Cognito);

const { userPoolClientId } = resourcesConfig.Auth.Cognito;
const { oauth: oAuthConfig } = resourcesConfig.Auth.Cognito.loginWith;
const { cookies: setCookieOptions = {} } = runtimeOptions;

const handleRequest = async (
request: NextRequest | NextApiRequest,
contextOrResponse: AuthRoutesHandlerContext | NextApiResponse,
handlerInput: CreateAuthRoutesHandlersInput,
): Promise<Response | undefined> => {
const handleRequest = async ({
request,
contextOrResponse,
handlerInput,
userPoolClientId,
oAuthConfig,
setCookieOptions,
origin,
}: {
request: NextRequest | NextApiRequest;
contextOrResponse: AuthRoutesHandlerContext | NextApiResponse;
handlerInput: CreateAuthRoutesHandlersInput;
userPoolClientId: string;
oAuthConfig: OAuthConfig;
setCookieOptions: CookieStorage.SetCookieOptions;
origin: string;
}): Promise<Response | undefined> => {
if (isNextApiRequest(request) && isNextApiResponse(contextOrResponse)) {
// In pages router the response is sent via calling `response.end()` or
// `response.send()`. The response is not returned from the handler.
Expand All @@ -72,7 +64,7 @@ export const createAuthRouteHandlersFactory = ({
userPoolClientId,
oAuthConfig,
setCookieOptions,
origin: amplifyAppOrigin,
origin,
runWithAmplifyServerContext,
});

Expand All @@ -92,7 +84,7 @@ export const createAuthRouteHandlersFactory = ({
userPoolClientId,
oAuthConfig,
setCookieOptions,
origin: amplifyAppOrigin,
origin,
runWithAmplifyServerContext,
});
}
Expand All @@ -103,8 +95,45 @@ export const createAuthRouteHandlersFactory = ({
);
};

return (createAuthRoutesHandlersInput = {}) =>
return (createAuthRoutesHandlersInput = {}) => {
// origin validation should happen when createAuthRouteHandlers is being called to create
// Auth API routes.
if (!amplifyAppOrigin) {
throw new AmplifyServerContextError({
message: 'Could not find the AMPLIFY_APP_ORIGIN environment variable.',
recoverySuggestion:
'Add the AMPLIFY_APP_ORIGIN environment variable to the `.env` file of your Next.js project.',
});
}

if (!isValidOrigin(amplifyAppOrigin)) {
throw new AmplifyServerContextError({
message:
'AMPLIFY_APP_ORIGIN environment variable contains an invalid origin string.',
recoverySuggestion:
'Ensure the AMPLIFY_APP_ORIGIN environment variable is a valid origin string.',
});
}

// OAuth config validation should happen when createAuthRouteHandlers is being called to create
// Auth API routes.
assertTokenProviderConfig(resourcesConfig.Auth?.Cognito);
assertOAuthConfig(resourcesConfig.Auth.Cognito);

const { userPoolClientId } = resourcesConfig.Auth.Cognito;
const { oauth: oAuthConfig } = resourcesConfig.Auth.Cognito.loginWith;
const { cookies: setCookieOptions = {} } = runtimeOptions;

// The call-site of this returned function is the Next.js API route file
(request, contextOrRequest) =>
handleRequest(request, contextOrRequest, createAuthRoutesHandlersInput);
return (request, contextOrResponse) =>
handleRequest({
request,
contextOrResponse,
handlerInput: createAuthRoutesHandlersInput,
userPoolClientId,
oAuthConfig,
setCookieOptions,
origin: amplifyAppOrigin,
});
};
};

0 comments on commit 7499b16

Please sign in to comment.