-
-
Save thameera/2dfb3dff6ed2ec461aef7a7a2e3d3250 to your computer and use it in GitHub Desktop.
| /** | |
| * Handler that will be called during the execution of a PostLogin flow. | |
| * | |
| * @param {Event} event - Details about the user and the context in which they are logging in. | |
| * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login. | |
| */ | |
| exports.onExecutePostLogin = async (event, api) => { | |
| // Craft a signed session token | |
| const token = api.redirect.encodeToken({ | |
| secret: 'keyboardcat', // IMPORTANT: Read this from event.secrets | |
| expiresInSeconds: 60, | |
| payload: { | |
| // Custom claims to be added to the token | |
| email: event.user.email, | |
| externalUserId: 1234, | |
| }, | |
| }); | |
| // Send the user to http://localhost:3000/redirect along | |
| // with a `session_token` query string param including | |
| // the email. | |
| api.redirect.sendUserTo("http://localhost:3000/redirect", { | |
| query: { session_token: token } | |
| }); | |
| }; | |
| /** | |
| * Handler that will be invoked when this action is resuming after an external redirect. If your | |
| * onExecutePostLogin function does not perform a redirect, this function can be safely ignored. | |
| * | |
| * @param {Event} event - Details about the user and the context in which they are logging in. | |
| * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login. | |
| */ | |
| exports.onContinuePostLogin = async (event, api) => { | |
| const payload = api.redirect.validateToken({ | |
| secret: 'keyboardcat', // IMPORTANT: Read this from event.secrets | |
| tokenParameterName: 'my_token', | |
| }); | |
| console.log(payload); | |
| }; |
| /* | |
| * IMPORTANT: | |
| * This code is meant for demo purposes only, and is not production-ready. | |
| * More info: https://auth0.com/docs/actions/triggers/post-login/redirect-with-actions | |
| */ | |
| const express = require('express') | |
| const jwt = require('jsonwebtoken') | |
| const PORT = process.env.PORT || 3000 | |
| const SECRET = 'keyboardcat' // For demo purposes only. Should not be committed in source file. | |
| const TENANT_DOMAIN = 'tham.auth0.com' | |
| const app = express() | |
| /* | |
| * Validate the incoming token from Auth0 | |
| * This can be generated in the Action by the api.redirect.encodeToken() method | |
| */ | |
| const validateIncomingToken = (req) => { | |
| if (!req.query || !req.query.session_token) { | |
| throw 'No session_token found' | |
| } | |
| try { | |
| const decoded = jwt.verify(req.query.session_token, SECRET) | |
| return decoded | |
| } catch (e) { | |
| throw 'Invalid session_token' | |
| } | |
| } | |
| /* | |
| * Generate new session token to be sent to Auth0 | |
| */ | |
| const generateNewToken = (data, state) => { | |
| const payload = { | |
| sub: data.sub, // Mandatory, must match incoming token's sub | |
| iss: 'my-redirect-app', // Optional, not validated | |
| state, // Mandatory, validated by Auth0 | |
| color: 'blue', // Optional custom parameters to be used in Actions | |
| } | |
| // Even though iat and exp are not added above, they are implicitly added by the jwt library | |
| const token = jwt.sign(payload, SECRET, { expiresIn: '60s' }) | |
| return token | |
| } | |
| app.get('/redirect', (req, res) => { | |
| try { | |
| const incomingData = validateIncomingToken(req) | |
| const newToken = generateNewToken(incomingData, req.query.state) | |
| const url = `https://${TENANT_DOMAIN}/continue?state=${req.query.state}&my_token=${newToken}` | |
| res.redirect(url) | |
| } catch (e) { | |
| res.send(e) | |
| } | |
| }) | |
| app.listen(PORT, () => { | |
| console.log(`App listening at http://localhost:${PORT}`) | |
| }) |
Thank you for this one, been fighting with this for a day now 😆
Do you generate token again from backend just in case the one from "Post Login" expires? @thameera
Do you generate token again from backend just in case the one from "Post Login" expires? @thameera
The token coming from the Action can/should be consumed immediately and verified. Even if the user stays a long time on the redirected page, you would generally not need to validate that token again. Also note that the token we send back to Auth0 is a new one and different from the one we received from Auth0.
So ideally there shouldn't be a situation where the token fails to validates due to expiry (unless some user is trying to replay a request, in which case it should rightly be denied).
Saved me from hours of going in circles. Cheers mate!