Yes, you can update user metadata with Next.js + Auth0
It’s just not documented that well.
Here’s how I got it to work:
Install both both @auth0/nextjs-auth0 and auth0 (aka node-auth0). @auth0/nextjs-auth0
works beautifully out of the box for authentication, but you’ll want to configure it to actually work with current_user
scopes.
yarn add @auth0/nextjs-auth0 auth0
Follow the README guide to set up @auth0/nextjs-auth0. You'll want to customize just the [...auth0].js
file:
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
export default handleAuth({
async login(req, res) {
try {
await handleLogin(req, res, {
authorizationParams: {
audience: `${process.env.AUTH0_ISSUER_BASE_URL}/api/v2/`,
scope: 'openid read:current_user update:current_user_metadata',
},
});
} catch (error) {
res.status(error.status || 400).end(error.message);
}
},
});
The key here is specifying the audience
and scope
when logging in. For whatever reason, the nextjs package won't read AUTH0_SCOPE
from your .env.local
file. You can verify this out by inspecting session
in your API routes without setting the scope in handleAuth
:
import { getSession } from '@auth0/nextjs-auth0';
const handler = async (req, res) => {
const session = await getSession(req, res);
console.log(session.accessTokenScope) // doesn't have 'current_user'
}
After you explicitly set it, session.accessTokenScope
should return the correct scope. (Another caveat, not including openid
in the scope with throw an error.)
The final step is to use the access token from your session to init your management client and specify the scope again.
// at the top:
import { ManagementClient } from 'auth0';
// in your handler
const session = await getSession(req, res);
const id = session.user.sub;
const accessToken = session.accessToken;
const currentUserManagementClient = new ManagementClient({
token: accessToken,
domain: process.env.AUTH0_ISSUER_BASE_URL.replace('https://', ''),
scope: 'openid read:current_user update:current_user_metadata'
});
const user = await currentUserManagementClient.updateUserMetadata(
{ id },
params
);
Try it out—if you're already logged in, you'll need to log out and back in to see the scope change applied.
Here's a full example. I'm pretty sure the scope thing is a bug (does someone want to investigate to confirm and report it?), but drop in any suggestions in the gist comments.