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
redirectTourl withstateparameter 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
stateand other parameters from the url and redirects to the SPA route specified instateparameter. 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;