I’m using Auth0 to protect a simple html website hosted in S3 (served via Cloudfront).
I want users to be able to log in with various identity providers which I have setup in the Social section under Authorisation in the tenant admin area.
I have created a Lambda@edge function that will run on any request to Cloudfront. If no session cookie is present it will redirect user to /authorize endpoint of my auth0 tenant, then on successful login it will get token from /oauth/token endpoint in Auth0 and store the returned token in a session cookie, while this cookie exists requests will be allowed through without further calls/redirects to Auth0.
The thing I’m confused about is the purpose of this token, as I’m never doing anything with it or checking it is valid. Should I be calling an endpoint in Auth0 on each page request passing the token to check it’s still valid and not expired (or indeed a fake hacked one)?
I believe the token I’m receiving from Auth0 is opaque so I can’t check its expiry myself. From reading documentation it looks like I would need to setup an API and pass an audience to receive a JWT instead, but Application seemed the right thing to create seeing as I’m not actually calling or providing any APIs from my website?
Yes, it is important to call /oauth/token even if you’re not explicitly using the token for API access. Here’s why:
Security Verification
The token exchange verifies that the authorization code hasn’t been intercepted or reused
Without this step, an attacker could potentially replay the authorization code
Session Management
The token represents a valid authenticated session
Even if you don’t use the token directly, storing and validating it ensures the user’s session is legitimate
Think of it like this: The authorization code you get after login is like a one-time ticket, and the token exchange is like trading that ticket for a proper session pass. Without completing this exchange:
You can’t verify if the login was completed successfully
You’re vulnerable to authorization code replay attacks
You don’t have a proper way to validate the session
You can validate the token by making call you /userinfo endpoint.
async function validateRequest(event) {
const request = event.Records[0].cf.request;
const cookies = parseCookies(request.headers.cookie || []);
// If no session cookie, redirect to login
if (!cookies.session) {
return redirectToAuth0();
}
try {
// Call Auth0's userinfo endpoint to validate the token
const response = await fetch('https://YOUR_TENANT.auth0.com/userinfo', {
headers: {
'Authorization': `Bearer ${cookies.session.accessToken}`
}
});
if (!response.ok) {
// Token is invalid or expired
return redirectToAuth0();
}
// Token is valid, allow the request through
return request;
} catch (error) {
console.error('Error validating token:', error);
return redirectToAuth0();
}
}
Note: Your implementation may look different than mine.
This ensures that only valid Auth0 tokens can access your site. It’s effectively using Auth0 as your “source of truth” for session validation.
One optimization: Since Lambda@Edge has a timeout limit and you probably don’t want to call Auth0 on every single request (images, CSS, etc.), you might want to:
Only validate requests for HTML pages
Cache the validation result for a short period (e.g., 5 minutes or whatever suits your requirements)