-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): validate if access and id tokens are valid cognito tokens (…
…#13385) * feat(adapter-nextjs): validate if access and id tokens are valid cognito tokens * add unit tests and cleanups * increase bundle size * increase bundle size * Update packages/core/src/adapterCore/serverContext/types/KeyValueStorageValidator.ts Co-authored-by: Hui Zhao <[email protected]> * Update packages/adapter-nextjs/__tests__/utils/createTokenValidator.test.ts Co-authored-by: Hui Zhao <[email protected]> * Update packages/core/src/adapterCore/serverContext/types/KeyValueStorageValidator.ts Co-authored-by: Hui Zhao <[email protected]> * address feedback * address feedback * Update packages/adapter-nextjs/src/utils/createTokenValidator.ts Co-authored-by: israx <[email protected]> * address feedback --------- Co-authored-by: Ashwin Kumar <[email protected]> Co-authored-by: Hui Zhao <[email protected]> Co-authored-by: israx <[email protected]>
- Loading branch information
1 parent
d7d33da
commit 0b72b32
Showing
15 changed files
with
339 additions
and
35 deletions.
There are no files selected for viewing
88 changes: 88 additions & 0 deletions
88
packages/adapter-nextjs/__tests__/utils/createTokenValidator.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { isValidCognitoToken } from '@aws-amplify/core/internals/utils'; | ||
|
||
import { createTokenValidator } from '../../src/utils/createTokenValidator'; | ||
|
||
jest.mock('@aws-amplify/core/internals/utils', () => ({ | ||
...jest.requireActual('@aws-amplify/core/internals/utils'), | ||
isValidCognitoToken: jest.fn(), | ||
})); | ||
const mockIsValidCognitoToken = isValidCognitoToken as jest.Mock; | ||
|
||
const userPoolId = 'userPoolId'; | ||
const userPoolClientId = 'clientId'; | ||
const tokenValidatorInput = { | ||
userPoolId, | ||
userPoolClientId, | ||
}; | ||
const accessToken = { | ||
key: 'CognitoIdentityServiceProvider.clientId.usersub.accessToken', | ||
value: | ||
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMTEiLCJpc3MiOiJodHRwc', | ||
}; | ||
const idToken = { | ||
key: 'CognitoIdentityServiceProvider.clientId.usersub.idToken', | ||
value: 'eyJzdWIiOiIxMTEiLCJpc3MiOiJodHRwc.XAiOiJKV1QiLCJhbGciOiJIUzI1NiJ', | ||
}; | ||
|
||
const tokenValidator = createTokenValidator({ | ||
userPoolId, | ||
userPoolClientId, | ||
}); | ||
|
||
describe('Validator', () => { | ||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
it('should return a validator', () => { | ||
expect(createTokenValidator(tokenValidatorInput)).toBeDefined(); | ||
}); | ||
|
||
it('should return true for non-token keys', async () => { | ||
const result = await tokenValidator.getItem?.('mockKey', 'mockValue'); | ||
expect(result).toBe(true); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledTimes(0); | ||
}); | ||
|
||
it('should return true for valid accessToken', async () => { | ||
mockIsValidCognitoToken.mockImplementation(() => Promise.resolve(true)); | ||
|
||
const result = await tokenValidator.getItem?.( | ||
accessToken.key, | ||
accessToken.value, | ||
); | ||
|
||
expect(result).toBe(true); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledTimes(1); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledWith({ | ||
userPoolId, | ||
clientId: userPoolClientId, | ||
token: accessToken.value, | ||
tokenType: 'access', | ||
}); | ||
}); | ||
|
||
it('should return true for valid idToken', async () => { | ||
mockIsValidCognitoToken.mockImplementation(() => Promise.resolve(true)); | ||
|
||
const result = await tokenValidator.getItem?.(idToken.key, idToken.value); | ||
expect(result).toBe(true); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledTimes(1); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledWith({ | ||
userPoolId, | ||
clientId: userPoolClientId, | ||
token: idToken.value, | ||
tokenType: 'id', | ||
}); | ||
}); | ||
|
||
it('should return false if invalid tokenType is access', async () => { | ||
mockIsValidCognitoToken.mockImplementation(() => Promise.resolve(false)); | ||
|
||
const result = await tokenValidator.getItem?.(idToken.key, idToken.value); | ||
expect(result).toBe(false); | ||
expect(mockIsValidCognitoToken).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { isValidCognitoToken } from '@aws-amplify/core/internals/utils'; | ||
import { KeyValueStorageMethodValidator } from '@aws-amplify/core/internals/adapter-core'; | ||
|
||
interface CreateTokenValidatorInput { | ||
userPoolId?: string; | ||
userPoolClientId?: string; | ||
} | ||
/** | ||
* Creates a validator object for validating methods in a KeyValueStorage. | ||
*/ | ||
export const createTokenValidator = ({ | ||
userPoolId, | ||
userPoolClientId: clientId, | ||
}: CreateTokenValidatorInput): KeyValueStorageMethodValidator => { | ||
return { | ||
// validate access, id tokens | ||
getItem: async (key: string, value: string): Promise<boolean> => { | ||
const tokenType = key.includes('.accessToken') | ||
? 'access' | ||
: key.includes('.idToken') | ||
? 'id' | ||
: null; | ||
if (!tokenType) return true; | ||
|
||
if (!userPoolId || !clientId) return false; | ||
|
||
return isValidCognitoToken({ | ||
clientId, | ||
userPoolId, | ||
tokenType, | ||
token: value, | ||
}); | ||
}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.