Hi! Thanks for this amazing library, saved me a ton of work!
I am having some issues figuring out how to get the profile details from a session and was wondering if I could get some help. My app only provides Twitter as a login provider, and it uses JWT.
When I have a custom callback for signin, I am able to get the profile metadata on the API route. However, on the client-side, when I call getSession(), it only returns the Twitter display name and profile picture. It does not return the access token, the Twitter uid, or any of the other details that are part of the metadata.
So my question is, how can I make it so that I can access some of the metadata from the client-side (mainly the Twitter UID and possibly the access token)?
Thanks!
If you have jwt: true in your config, then the callback for session will include a token. That token includes a lot more information, which you can make available on the session. For example, I'm using the following to return a database ID for my user.
callbacks: {
session: async (session, token) => {
if (!session || !session.user || !token || !token.user) {
return Promise.resolve(session);
}
session.user.id = token.user.id;
return Promise.resolve(session);
}
}
That's perfect, thank you @bplowry!
If anyone comes across this in the future, here's how to get the accessToken and Twitter user ID on the session callback:
callbacks: {
session: async (session, token) => {
if (!session || !session.user || !token || !token.account) {
return Promise.resolve(session);
}
session.user.id = token.account.id;
session.accessToken = token.account.accessToken;
return Promise.resolve(session);
}
},
@bplowry @MehediH Thanks! Those are 100% the intended approaches!
I hope we will have a "Tutorials" section for stuff like this in the documentation as I know it's quite terse and not obvious.
We don't expose more info in the session for security reasons, as we want to be as secure as possible by default, so this trips a lot of folks up. For security reasons, probably isn't default behaviour we want to change but is something we should document better. There may also be API endpoints for getting access tokens for providers in future.
@MehediH I think you can further simplify it to something like this:
callbacks: {
async session(session, token) {
if (!session?.user || !token?.account) {
return session
}
session.user.id = token.account.id
session.accessToken = token.account.accessToken
return session
},
},
(Note: Since you define the function as async, you do not need to use Promise.resolve in the return statement. My second tip is to use optional chaining to simplify the logic, although this one is optional (馃槢), depending on your JS environment it may not be supported (yet?), but it is most likely that it is)
Anyways, thanks for letting me come across this from the future 馃敭, now I have access (馃槢) to the accessToken in useSession and getSession!
why do I get this shape instead of the object you guys mention above
session {
user: { name: 'Administrator', email: 'pro@...', image: null },
expires: '2020-08-29T02:49:39.839Z'
}
token {
name: 'Administrator',
email: 'pro@...',
iat: 1596077378,
exp: 1598669378
}
For someone who might needs, in jwt callback, you can pass over the profile and account props to session like so:
session: async (session: any, token: any) => {
if (session.user) {
session.user.firstName = token.profile.given_name;
session.user.lastName = token.profile.family_name;
session.user.id = token.account.id;
session.accessToken = token.account.accessToken;
}
return Promise.resolve(session);
},
jwt: async (token: any, user: any, account: any, profile: any, isNewUser: boolean) => {
if (account) {
token.account = account;
}
if (profile) {
token.profile = profile;
}
return Promise.resolve(token);
}
Note that the account and profile props are only available at signin.
Most helpful comment
That's perfect, thank you @bplowry!
If anyone comes across this in the future, here's how to get the accessToken and Twitter user ID on the session callback: