Search code examples
reactjsauthenticationnext.jsauth0

NextJS-Auth0: How can I assign a role on signup with Auth0?


Using the library nextjs-auth0 (https://github.com/auth0/nextjs-auth0) I've been trying to make use of the handleAuth hook to grab a query arg to specify which role should be assigned to the user on signup.

An example of what I'm trying to do:

//pages/api/auth/[...auth0].js

const getLoginState = (req, loginOptions) => {
    const  { role } = req.query;
    return { role: role };
  };

export default handleAuth({
    async login(req, res) {
        try {
          await handleLogin(req, res, { getLoginState } );
        } catch (error) {
          res.status(error.status || 500).end(error.message);
        }
      }
});

The documentation for handleAuth makes it seem like it's possible to do this ( https://auth0.github.io/nextjs-auth0/modules/handlers_login.html#getloginstate )

// from the documentation
const getLoginState = (req, loginOptions) => {
  return { basket_id: getBasketId(req) };
};

From that doc - it looks like basket_id is the custom property to be saved against the user "before they visit the Identity Provider to login". This sounds, to me, that basked_id will be saved somewhere against the users metadata once they've logged in. Is the documentation misleading, or am I misunderstanding?

How can I set the role during (or even slightly after) signup?


Solution

  • I managed to achieve what I wanted with the following Auth0 "rule":

    function (user, context, callback) {
    
        const count = context.stats && context.stats.loginsCount ? context.stats.loginsCount : 0;
        if (count > 1) {
            return callback(null, user, context);
        }
    
        const ManagementClient = require('[email protected]').ManagementClient;
        const management = new ManagementClient({
          token: auth0.accessToken,
          domain: auth0.domain
        });
        let roles = [context.request.query.role];
        const params =  { id : user.user_id};
        const data = { "roles" : roles};
    
        management.users.assignRoles(params, data, function (err, user) {
        if (err) {
            // Handle error.
            console.log(err);
         }
        callback(null, user, context);
        });
        
    }
    
    

    Notice that the role is being read in from context.request.query.role. This pulls the query param role key off the login URL which more-or-less works how I wanted it to.

    Then forward the role along from the auth in the backend:

    const getLoginState = (req, loginOptions) => {
        const  { role } = req.query;
        loginOptions.authorizationParams.role = role;
        return { role: role };
      };
    
    export default handleAuth({
        async login(req, res) {
            try {
              await handleLogin(req, res, { getLoginState });
            } catch (error) {
              res.status(error.status || 500).end(error.message);
            }
          }
    });
    

    Notice the loginOptions.authorizationParams.role = role;

    So the login link can be set to: /api/auth/login?role=somerole and the rule will pick up the role and set it in the metadata part of the users info.

    However: I wasn't able to get this to actually properly set the role on the user but it's enough for me, as it appears in the session.