Auth0 email verification flow allows developers to set a redirectTo
url. Once the application users verify their email, they are redirected to redirectTo
url specified in the Emails > Templates > Email Verification
settings.
For single page apps, urls sometimes contain hash and the route for particular state/view in the app and followed by any route parameters. Using such url as redirectTo
causes following issue.
For eg. setting following url as redirectTo url
http://localhost:3000/#/register
results in user getting redirected to following url
http://localhost:3000/?supportSignUp=true&supportForgotPassword=true&email=ashish.dasnurkar%40gmail.com&message=Your%20email%20was%20verified.%20You%20can%20continue%20using%20the%20application.&success=true#/register
This is per the RFC 3986 spec that defines expected order of url as scheme|authority|path|query|fragment
However SPA frameworks such as Angular typically expect urls in scheme|authority|path|fragment|query
format (note the querystring parameters being at the end instead of in the middle as expected in the spec). This causes the SPA app to not enter the state as expected. For eg. in abvoe example url, instead of routing to /#/register
, app is routed to /
.
To get around this limitation of SPA frameworks such as Angular, it is recommended to use a server-side callback url as a redirectTo
url with a state
that preserves which SPA app route the user is required to be redirected to. Once in this server-side url, simply redirect to SPA route in state
parameter along with rest of the querystring parameters.
Here is a step-by-step process to get it working.
- Add a server-side url as
redirectTo
url withstate
parameter that records the SPA route user is required to be redirected to.
http://localhost:3001/register?state=register
- Create a server-side route controller that reads the
state
and other parameters from the url and redirects to the SPA route specified instate
parameter. Also remember to append all rest of the parameters received from auth0.
var express = require('express');
var router = express.Router();
var qs = require('qs'); // to read querystring params and stringify them
router.get('/register', function(req, res, next) {
var state = req.query.state; // retrieve the state param that contains the SPA client side route user needs to be redirected to.
delete req.query.state; // remove it from query params.
res.redirect('http://localhost:3000/#/' + state + '?' + qs.stringify(req.query)); // Send a 302 redirect that makes browser kick off the expected SPA client-side route.
});
module.exports = router;