Search code examples
amazon-web-servicesnext.jsoauth-2.0amazon-cognitonext-auth

Add role based authentication using next-auth in NextJS


I was implementing a role based authentication using next-auth v4 using CognitoProvider which I modified to add a role but the role attribute is not passed in the final session json

import NextAuth from "next-auth/next";

function CognitoProvider(options) {
  return {
    id: "cognito",
    name: "Cognito",
    type: "oauth",
    wellKnown: `${options.issuer}/.well-known/openid-configuration`,
    idToken: true,
    profile(profile) {
      console.log(profile);
      return {
        id: profile.sub,
        name: profile.name,
        email: profile.email,
        image: profile.picture,
        role: profile["cognito:groups"],
      };
    },
    options,
  };
}

export default NextAuth({
  providers: [
    CognitoProvider({
      clientId: process.env.COGNITO_CLIENT_ID,
      clientSecret: process.env.COGNITO_CLIENT_SECRET,
      issuer: process.env.COGNITO_DOAMIN,
    }),
  ],
  callbacks: {
    session: (props) => {
      console.log(props);
      return props.session;
    },
  },
});

Below is the console log of profile object

enter image description here

role: profile["cognito:groups"]

Actual Object

enter image description here

I have added a user to admin group and wanted him to access a specific route in my NextJS app.

Any help would be appreciated.


Solution

  • You need to configure the jwt and session callbacks to include more data in the session.

    From Next-Auth docs:

    If you want to make something available you added to the token [...] via the jwt() callback, you have to explicitly forward it here [the session() callback] to make it available to the client.

    To add the user's role:

    export default NextAuth({
      // ...
      callbacks: {
        jwt({ token, account, profile }) {
            if (account) {
                // modify token
                token.role = profile.role;
            }
    
            return token;
        },
    
        session({ session, token }) {
          // Send properties to the client
    
          if (session.user) {
            // modify session
            session.user.roles = token.role;
          }
    
          return session;
        },
      },
    });
    

    Then in your route, you would get the user's role from the session session.user.role