Mitigate CSRF attacks by using the state, nonce, signed nonce and pkce cookies
Encode and store redirect uri in state to be used later to send users to where they wanted to go, after oauth token exchange is done. (See next section for more details)
// _getRedirectToCognitoUserPoolResponse would generate and store nonce, signed nonce, pkce and state in the browser cookie
const nonce = generateNonce();
const state = {
nonce,
nonceHmac: common.sign(
nonce,
CONFIG.nonceSigningSecret,
CONFIG.nonceLength
),
...generatePkceVerifier(),
};
// _fetchTokensFromCode would verify that `state` returned by AWS Cognito is related to the one we set in the previous step
function validateQueryStringAndCookies(props: {
querystring: string;
cookies: ReturnType<typeof common.extractAndParseCookies>;
}) {
// Check if Cognito threw an Error. Cognito puts the error in the query string
const {
code,
state,
error: cognitoError,
error_description,
} = parseQueryString(props.querystring);
if (cognitoError) {
throw new Error(`[Cognito] ${cognitoError}: ${error_description}`);
}
// The querystring needs to have an authorization code and state
if (
!code ||
!state ||
typeof code !== "string" ||
typeof state !== "string"
) {
throw new Error(
[
'Invalid query string. Your query string does not include parameters "state" and "code".',
"This can happen if your authentication attempt did not originate from this site.",
].join(" ")
);
}
Why is this needed:
We are planning to use this library for our new authentication gateway application. As opposed to the intended use case of this library, which is to use the handle method to put static S3 files behind an authentication gate, we are planning to use the individual handler methods directly in our application. Our auth gateway app will be a set of Lambda@Edge handlers that work as an intermediary between React frontend clients and AWS Cognito to do
authentication duties,
exchange code for tokens, and
sending tokens as HttpOnly cookies, which clients can use to communicate with some Amazon internal API's
Handlers
/signIn: Mapped to the existing method _getRedirectToCognitoUserPoolResponse
/parseAuth: Mapped to existing method _fetchTokensFromCode
/refreshToken: Mapped to existing method _fetchTokensFromRefreshToken
In our Cloudfront distribution setup, we'd do something like this
What would you like to be added:
state
to be used later to send users to where they wanted to go, after oauth token exchange is done. (See next section for more details)https://auth0.com/docs/secure/attack-protection/state-parameters
https://github.com/aws-samples/cloudfront-authorization-at-edge/blob/master/src/lambda-edge/check-auth/index.ts#L71-L83
https://github.com/aws-samples/cloudfront-authorization-at-edge/blob/017089d8aea9239f22f4bd8bbe8a7b607eb1fe5b/src/lambda-edge/parse-auth/index.ts#L177
Why is this needed:
We are planning to use this library for our new authentication gateway application. As opposed to the intended use case of this library, which is to use the
handle
method to put static S3 files behind an authentication gate, we are planning to use the individual handler methods directly in our application. Our auth gateway app will be a set of Lambda@Edge handlers that work as an intermediary between React frontend clients and AWS Cognito to doHandlers
/signIn
: Mapped to the existing method_getRedirectToCognitoUserPoolResponse
/parseAuth
: Mapped to existing method_fetchTokensFromCode
/refreshToken
: Mapped to existing method_fetchTokensFromRefreshToken
In our Cloudfront distribution setup, we'd do something like this
Slack or email me on vikred@amazon.com for additional details