Next-auth: Twitter login not working

Created on 18 May 2020  路  14Comments  路  Source: nextauthjs/next-auth

image

/Users/sunilbagde/code/tweety/node_modules/next-auth/dist/server/lib/oauth/callback.js:126
profile: { name: f.name, email: f.email.toLowerCase(), image: f.image },
^

TypeError: Cannot read property 'toLowerCase' of undefined
at _getProfile (/Users/sunilbagde/code/tweety/node_modules/next-auth/dist/server/lib/oauth/callback.js:126:45)
at g.get (/Users/sunilbagde/code/tweety/node_modules/next-auth/dist/server/lib/oauth/callback.js:103:22)
at passBackControl (/Users/sunilbagde/code/tweety/node_modules/oauth/lib/oauth.js:390:11)
at IncomingMessage. (/Users/sunilbagde/code/tweety/node_modules/oauth/lib/oauth.js:409:9)
at IncomingMessage.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1129:12)
at process._tickCallback (internal/process/next_tick.js:63:19)

bug

Most helpful comment

@iaincollins and @LoriKarikari Thanks for great support and i have figure it out how to get Account, User session info (as @iaincollins you comment)

1-
import { getConnection } from "typeorm";

import Adapters from "next-auth/adapters";

import NextAuth from "next-auth/client";

2-

let session = await NextAuth.session({ req });

let Account = Adapters.TypeORM.Models.Account.model;

let Session = Adapters.TypeORM.Models.Session.model;

let accessToken = session.accessToken;

let { userId } = await connection.getRepository(Session).findOne({ accessToken: accessToken, });

let account = await connection
  .getRepository(Account)
  .findOne({ userId: userId });

All 14 comments

Thanks for reporting this issue @im-sunil. I'll check this out.

My guess is that this is happening because you need to enable the option "Request email address from users" permission in Twitter.

Twitter is a little different to most other oAuth providers in that it doesn't return the email address unless you explicitly enable the option.

Screenshot 2020-05-18 at 08 58 12

Context

v1 actually use to cope with oAuth providers that didn't return an email address, by creating a dummy email address that looked something like {profileId}:{providerName}@localhost.localdomain.

It would then look for email addresses like this and replace them with the users real email address if they linked their account with with another service that did have an email address, or if they provided one by updating their profile information manually.

Note: Account linking is technically possible in v2 (you just sign in, then sign in again with a different service) but it's not clear yet, and you can't unlink accounts.

Solutions

The easiest solution for @im-sunil is to enable the option to return the email address in Twitter.

However, this raises the question of what we should do about it.

  • We could improve the error messaging - eg return a specific error page that explains what is wrong (this might be the easiest thing; and we could even do this first, and change it later).
  • We could try to do the same behaviour as v1 and support creating accounts without an email address. This is a great user experience but requires some hackery like the above to implement.

Yes added permission, its fixed I guess

image

Can you give ref to how add sqlite?

You might want to take a look at http://next-auth-example.now.sh and also #116

tl;dr you probably your config to look like this:

 adapter: Adapters.Default({
  type: 'sqlite',
  database: ':memory:',
  synchronize: true 
})

Error handling for this to better explain what is wrong will be better later.

Able login next question how i get twitter access token and oath token for requesting twitter api

{ user:
{ name: 'Sunil Bagde', email: '[email protected]' },
accessToken:
'a590d5b27588f2fc804f14080ed7c6221b43451206bf00cc97f6d63e872ccb43'
}

accessToken. is for nextjs app ?

Able login next question how i get twitter access token and oath token for requesting twitter api

{ user:
{ name: 'Sunil Bagde', email: '[email protected]' },
accessToken:
'a590d5b27588f2fc804f14080ed7c6221b43451206bf00cc97f6d63e872ccb43'
}

accessToken. is for nextjs app ?

The token is stored in the database in the Account table so you should be able to get it from there.

@im-sunil Yes that's correct, the accessToken in the session object is for your app only (e.g. you want to build your own endpoint that looks up users based on that token) and not the Twitter one.

AccessTokens and RefreshTokens for oAuth services are stored in the Accounts table (as @LoriKarikari says).

These are not currently exposed via the API.

You could do something like create an endpoint that AccessToken above to query the User ID from the Sessions table, then look up their Twitter AccessToken from the Account table.

Ok can you give sample Pls.

You'd probably want to create a new endpoint in /api/ that either takes the accessToken from the session object or looks in req.cookies for the Session ID and gets the User ID from there.

I can't offer more general help with Next.js / SQLite, but will keep it in mind and might add something like it to an example / documentation in future.

Closing this off as have resolved original query and moved the underlying issue to #131

@iaincollins and @LoriKarikari Thanks for great support and i have figure it out how to get Account, User session info (as @iaincollins you comment)

1-
import { getConnection } from "typeorm";

import Adapters from "next-auth/adapters";

import NextAuth from "next-auth/client";

2-

let session = await NextAuth.session({ req });

let Account = Adapters.TypeORM.Models.Account.model;

let Session = Adapters.TypeORM.Models.Session.model;

let accessToken = session.accessToken;

let { userId } = await connection.getRepository(Session).findOne({ accessToken: accessToken, });

let account = await connection
  .getRepository(Account)
  .findOne({ userId: userId });

That should do it! :-)

As a tip, with Twitter you get both AccessToken and RefreshToken on every sign in.

With other providers (e.g. Google) some only send RefreshToken the very first time you sign in to a new site, and you need to do some other stuff to get the RefreshToken if you didn't save it in a database on first login, like forcing Google to give you it or deleting the association in Google and signing in again.

(This is mostly just an issue that developers run into when testing.)

@iaincollins Thanks i keep in mind.

hello @iaincollins and @LoriKarikari how to access accessToken accessTokenSecret in account table only access token is stored, ow to get access token secret (oauth token and oauth secret)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iaincollins picture iaincollins  路  3Comments

eatrocks picture eatrocks  路  3Comments

simonbbyrne picture simonbbyrne  路  3Comments

jimmiejackson414 picture jimmiejackson414  路  3Comments

MelMacaluso picture MelMacaluso  路  3Comments