auth-astro
auth-astro copied to clipboard
Discord provider is missing user.id in the session object
If I log the session, I only get this JSON Object back and the user.id
is missing for some reason
Session Object :
{
user: {
name: 'staku',
email: '[email protected]',
image: 'https://cdn.discordapp.com/avatars/444560731300429844/28ef1f92c9bc92f919fa2ea5182ecb16.png'
},
expires: '2024-03-11T01:46:51.264Z'
}
auth.config.ts :
import Discord from '@auth/core/providers/discord';
import { defineConfig } from 'auth-astro';
export default defineConfig({
providers: [
Discord({
clientId: import.meta.env.DISCORD_CLIENT_ID,
clientSecret: import.meta.env.DISCORD_CLIENT_SECRET,
}),
],
});
I have the same error using github. Did you find a solution?
The soluzion is adding a callback inside the auth properties, thats add the userid
],
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
}
}
The soluzion is adding a callback inside the auth properties, thats add the userid
], callbacks: { session({ session, user }) { if (session.user) { session.user.id = user.id; } return session; } }
[auth][error] JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror
[auth][cause]: TypeError: Cannot read properties of undefined (reading 'id')
at Object.session (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:18:31)
at Module.session (file:///C:/.../auth/node_modules/@auth/core/lib/actions/session.js:35:52)
at async AuthInternal (file:///C:/.../auth/node_modules/@auth/core/lib/index.js:35:24)
at async Module.Auth (file:///C:/.../auth/node_modules/@auth/core/index.js:104:29)
at async Module.getSession (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:56:20)
at async eval (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:16:19)
at async AstroComponentInstance.render (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:44:7)
at async Object.render (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:356:7)
at async Module.renderChild (eval at instantiateModule (file:///C:/.../auth/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:36:5)
[auth][details]: {}
Doesn't work for me, I just get an error message when I try to log in, where should I add this?
Adding to auth.config.ts
did not work.
For me i added it like this to the auth config, but i only tested it for github, not for discord. t3-stack did the same, in order to add the user.id to every object
import GitHub from '@auth/core/providers/github';
import { DrizzleAdapter } from '@auth/drizzle-adapter';
import { db } from './src/utils/db';
import type { AuthConfig } from '@auth/core';
import { env } from '@/t3-env';
export default {
adapter: DrizzleAdapter(db),
providers: [
GitHub({
clientId: env.GITHUB_CLIENT_ID,
clientSecret: env.GITHUB_CLIENT_SECRET
})
],
callbacks: {
session({ session, user }) {
if (session.user)
session.user.id = user.id;
}
return session;
}
}
} satisfies AuthConfig;
Plss solve this
I use this to get user ID
export default defineConfig({
providers: [
Credentials({
...
}),
],
callbacks: {
session({ session, token }) {
if (session.user && token?.sub) {
session.user.id = token.sub;
}
return session;
}
}
})
But that does not retrieve the actual discord ID does it? it returns a unique identificatory number but not the actual discord ID right?
I think it is.
https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/discord.ts#L164-L168
After reading this repo code, I came to know that 'id' is forwarded as 'token.sub'
No for what I can see. ID is now smth that not looks like the discord ID
For those struggling - the solution I used was a small function to extract it from the image
URL.
The numbers after /avatars
has the User ID, its standard with Discord.
/**
* @summary Extracts the Discord User ID from the `image` field
* Custom utility function designed to enable us to get a User ID from a session (using auth-astro)
* @param {string} imageUrl
* @returns {string}
*/
export function extractUserIdFromImage(imageUrl: string): string {
const match = imageUrl.match(/avatars\/(\d+)\//);
return match ? match[1] : '';
}
And what if it has no avatar, then the image url is: 'https://cdn.discordapp.com/embed/avatars/0.png' @fearandesire
And what if it has no avatar, then the image url is: 'https://cdn.discordapp.com/embed/avatars/0.png' @fearandesire
Great point! I haven't come across this issue yet myself. That said, I just offered a solution that works for my needs. I'm not sure what to do in the event they don't have an avatar.
Following up, the solution provided by @willnode works! I explored this option for a site I recently launched, and the solution I provided prior was the cause of a silly bug as some users did not have avatars.
To clarify, for me -- this solution returns the User ID. I don't seem to get any UUID-like string as @Cocodrulo got here
I dont know why, sometimes token.sub gives the discord ID but other times it return thar strange UUID-like string. I was finally getting the discord ID and then suddenly token.sub was that kind of string again. I don't really understand.
Any update on a fix for this issue or alternative work arounds?
I get the same issues above when using the callbacks, either user.id
is not found or the token.sub
is the weird UUID like value
Would love to continue using the library but I need that ID, there's really no point without it
For those struggling - the solution I used was a small function to extract it from the
image
URL. The numbers after/avatars
has the User ID, its standard with Discord./** * @summary Extracts the Discord User ID from the `image` field * Custom utility function designed to enable us to get a User ID from a session (using auth-astro) * @param {string} imageUrl * @returns {string} */ export function extractUserIdFromImage(imageUrl: string): string { const match = imageUrl.match(/avatars\/(\d+)\//); return match ? match[1] : ''; }
I love this 😂 Very clever, I'm just concerned it will break if Discord randomly changes their avatar naming pattern.
Edit: And yes, as pointed out already, users with no avatar break this logic anyway
For those struggling - the solution I used was a small function to extract it from the
image
URL. The numbers after/avatars
has the User ID, its standard with Discord./** * @summary Extracts the Discord User ID from the `image` field * Custom utility function designed to enable us to get a User ID from a session (using auth-astro) * @param {string} imageUrl * @returns {string} */ export function extractUserIdFromImage(imageUrl: string): string { const match = imageUrl.match(/avatars\/(\d+)\//); return match ? match[1] : ''; }
problem here is that not everyone has a profile picture, so if you don't have one, it won't work because the avatar string is empty
All right here is my hacky solution because I don't need access to the users email
import Discord from '@auth/core/providers/discord';
import { defineConfig } from 'auth-astro';
export default defineConfig({
providers: [
Discord({
clientId: import.meta.env.DISCORD_CLIENT_ID,
clientSecret: import.meta.env.DISCORD_CLIENT_SECRET,
async profile(profile) {
return {
name: profile.username,
email: profile.id,
image: `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.png`,
};
},
}),
],
});
gives me this from the session
(verified that is my correct ID)
{
user: {
name: 'arknoodle',
email: '223864942615461888',
image: 'https://cdn.discordapp.com/avatars/223864942615461888/656ffa166759d7f24a73295a68ba023e.png'
},
expires: '2024-09-10T23:21:08.634Z'
}
If I want to add guild scope, to know which servers the user is on in Discord, how do I do it?
All right here is my hacky solution because I don't need access to the users email
import Discord from '@auth/core/providers/discord'; import { defineConfig } from 'auth-astro'; export default defineConfig({ providers: [ Discord({ clientId: import.meta.env.DISCORD_CLIENT_ID, clientSecret: import.meta.env.DISCORD_CLIENT_SECRET, async profile(profile) { return { name: profile.username, email: profile.id, image: `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.png`, }; }, }), ], });
gives me this from the
session
(verified that is my correct ID){ user: { name: 'arknoodle', email: '223864942615461888', image: 'https://cdn.discordapp.com/avatars/223864942615461888/656ffa166759d7f24a73295a68ba023e.png' }, expires: '2024-09-10T23:21:08.634Z' }
Which version are u using?
If I want to add guild scope, to know which servers the user is on in Discord, how do I do it?
using the discord API