I have set up AWS Cognito to authenticate a website served through CloudFront. I can direct users to the login and get the sign-in/sign-up pages in Cognito to appear. However, Cognito sets a cookie for its domain, not the website's domain. Therefore the cookie is not sent back to the website on subsequent requests. My domains are similar to this.
mywebsite.com = Cloudfront distribution
auth.mywebsite.com = Cognito custom domain
My cookie is for auth.mywebsite.com
, which is invalid for the parent domain. I don't think I can use auth.mywebsite.com as an alternate domain in Cloudfront because that domain is assigned as my custom Cognito domain. I'm not sure how this is supposed to work in any case.
You cannot use the cookie generated by Cognito Hosted UI.
Flow is Initial user action => www.my-domain.com Cloudfront Lambda Viewer Request checks auth (not authenticated) 302 redirect to Cognito Hosted UI Signin/Signup page www.auth.my-domain.com/login?client_id=${CLIENT_ID}&response_type=(code or token)&scope=${SCOPE}&redirect_uri=${REDIRECT_URI}
user authenticates with Cognito Hosted UI.
Cognito 302 redirects with either tokens or code depending on your configuration. Let's assume auth code flow. Cognito returns to your redirect www.my-domain.com/my-login/?code=123authcodeflow
Now, there are several ways to use the CODE in the url.
https://auth.my-domain.com/oauth2/token?grant_type=authorization_code&code=${code}&client_id=${client_id}&redirect_uri=${REDIRECT_URI} NOTE: same redirect_uri as before.
You'll now have all your tokens.
excellent article here: https://cloudonaut.io/authentication-at-the-edge-with-lambda-edge-cognito/
UPDATE
I was looking for a way to leverage CloudFront and Lambda@Edge functions to authenticate user via Cognito Hosted UI.
Found this LIB by AWS LABS and it works perfect with Cookie Auth.
https://github.com/awslabs/aws-jwt-verify
You can also copy the code and put it in your Lambda Index file and change anything you need to get different cookie names.
Works with just a Lambda@Edge Viewer request.
If you are also using AWS Gateway, you'll have to create another lambda that uses this LIB as well with a simple if/else like this one.
import { CognitoJwtVerifier } from 'aws-jwt-verify';
import { parseCookies } from './utilities/parse-cookie.mjs';
const verifier = CognitoJwtVerifier.create({
userPoolId: process.env.COGNITO_POOL_ID,
tokenUse: "access",
clientId: process.env.COGNITO_CLIENT_ID
});
const TOKEN_NAME = process.env.COGNITO_TOKEN_NAME;
export const handler = async (event) =>
{
if (event.cookies === null)
{
return {
isAuthorized: false,
};
}
const TOKEN = parseCookies(event.cookies, TOKEN_NAME);
if (TOKEN === null)
{
return {
isAuthorized: false,
};
}
try
{
await verifier.verify(TOKEN);
return {
isAuthorized: true,
};
}
catch(e)
{
return {
isAuthorized: false,
};
}
};