I have a side project currently using this library. I set-up auth through the Github provider π ( _so far so good_ ).
Not so long ago I raised an issue on how to retrieve the _access token_ provided by Github to be able to call its API.
@LoriKarikari pointed me on this other issue: https://github.com/iaincollins/next-auth/issues/128, which explained a way to do this, here is my code for it:
// pages/api/github/get-token.ts
import { getConnection } from 'typeorm'
import Adapters from 'next-auth/adapters'
import * as NextAuth from 'next-auth/client'
import { NextApiRequest, NextApiResponse } from 'next'
interface SessionConnection {
userId: string
}
export default async function getToken(
req: NextApiRequest,
res: NextApiResponse
) {
let account = null,
error = null
try {
const connection = getConnection()
const session = await NextAuth.getSession({ req })
const { model: accountModel } = Adapters.TypeORM.Models.Account
const { model: sessionModel } = Adapters.TypeORM.Models.Session
const sessionConnection = await connection
.getRepository(sessionModel)
.findOne({ accessToken: session?.accessToken })
account = await connection
.getRepository(accountModel)
.findOne({ userId: (sessionConnection as SessionConnection).userId })
} catch (e) {
error = e.message
}
res.status(200).send({ account, error })
}
It's called client-side when the application loads, so calls to the Github API can be formed.
So far it was working so good until recently where this line:
const connection = getConnection()
blows up π₯ π’ , having the following set-up for NextAuth:
{
site: process.env.NEXTAUTH_SITE,
providers: [
Providers.GitHub({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
scope:
'user public_repo repo repo_deployment repo:status read:repo_hook read:org read:public_key read:gpg_key',
}),
],
database: process.env.DATABASE_URL,
}
When calling getConnection() server-side I noticed ( through the _debugger_ ) that there's no active connections on TypeORM's connection pool:

and hence and error is thrown preventing to initialise the app ( "Connection 'default' was not found" ).
Any help with this highly appreciated β€οΈ
Have retagged this as it's not a bug in NextAuth.js but rather a question about TypeORM.
That approach looks good to me (RE: how the models are handled). Reliable connection handling with TypeORM can be tricky, especially with serverless and/or the behaviour of clients in development mode (like Hot Module Reloading).
I was just mentioning the complexity of this in #385 as it happens, I think a lot of folks underestimate it.
This is really a question for the TypeORM forum, but as an example, the logic that the TypeORM adapter in NextAuth.js uses to check a connection is valid is something like this:
async function _connect () {
// Get current connection by name
connection = getConnection(config.name)
// If connection is no longer established, reconnect
if (!connection.isConnected) { connection = await connection.connect() }
}
if (!connection) {
// If no connection, create new connection
try {
connection = await createConnection(config)
} catch (error) {
if (error.name === 'AlreadyHasActiveConnectionError') {
// If creating connection fails because it's already
// been re-established, check it's really up
await _connect()
} else {
logger.error('ADAPTER_CONNECTION_ERROR', error)
}
}
} else {
// If the connection object already exists, ensure it's valid
await _connect()
}
We do this before making any call, because we don't know how long a process has been idle and if the connection has dropped on if the function has been suspended or restarted recently.
Thanks @iaincollins for the explanation β€οΈ π
I have enhanced the getConnection() logic as you suggested to check if one is present and if not create one.
I think though the issue is deeper in my app:
const sessionConnection = await connection
.getRepository(sessionModel)
.findOne({ accessToken: session?.accessToken })
as it now doesn't seem to relate the existing session to the new connection:

I wonder if we could expose a declarative API in next-auth to retrieve access_token from the providers easily:
import { getProviderAccessToken } from 'next-auth'
I would be more than happy to contribute to this π€π» π
I advanced a bit more on this πͺπ»
Basically I had to call in my API route:
NextAuth.setOptions({ site: process.env.NEXT_AUTH_SITE })
as documented here for NextAuthClient.getSession() to work.
The last step for me is to learn and how to create a new TypeORM connection properly, as I'm doing:
async function connectToDb() {
// ...
if (!connection) createConnection(
// I need to pass the correct options here...
)
}
@lluia Yeah sorry needing to call NextAuth.setOptions() here is annoying - this is fixed in v3 as it uses an environment variable to configure it everywhere in the app once, instead of needing to set the site option in multiple places!
The example site at https://next-auth-example.now.sh is actually doing this running v3 beta if you'd like an example :-)
RE: TypeORM connection - We should have a tutorial for how to do things like this for sure!
I was really surprised how much custom connection handling code was required with NextAuth.js and would be interested to hear from TypeORM folks on their opinion on the approach we have taken, and if they can suggest ways it could be simplified, without triggering some of the issues we saw that lead to us taking the approach we currently have.
Reliable connection handling with TypeORM can be tricky, especially with serverless and/or the behaviour of clients in development mode (like Hot Module Reloading).
I opened an issue in TypeORM repo some time ago: https://github.com/typeorm/typeorm/issues/6241
There is a working example of how to handle HMR (it should work for serverless also) with TypeORM: https://github.com/typeorm/typeorm/issues/6241#issuecomment-643690383
@iaincollins
Regarding this code: https://github.com/iaincollins/next-auth/blob/d38cd54deeb225774c016407e80444ff206a4273/src/adapters/typeorm/index.js#L52-L68
You cannot rely on _your_ connection var here since in serverless mode this var can become completely different (on some particular function (I mean FAAS) execution). But you can try to retrieve existing connection by using TypeORM getConnection() function or connectionManager.get() method:
if (connectionManager.has(name)) {
return connectionManager.get(name);
}
return connectionManager.create().connect();
Also try...catch method you use didn't work well for me for some reason (at least in HMR mode, I didn't check it in real serverless), but if has() then get() else create() works well.
Ah I'm sorry I'm so inattentive. You first try to create connection and then, if there is an error, you try to get an existing.
That code could probably use more comments to explain why some of that logic exists. Some of the handling was issues I only saw on some scenarios (I think at least some of it was specific to handling an issue I only encountered with SQLite).
You cannot rely on your connection var here since in serverless mode this var can become completely different (on some particular function (I mean FAAS) execution).
The connection is scoped to the encapsulating function (Adapter) there isn't a problem with the approach here.
But you can try to retrieve existing connection by using TypeORM getConnection() function or connectionManager.get() method:
I would love to remove some of this logic and just do this, but unfortunately using the connection manager alone that comes with TypeORM doesn't seem to be reliable enough.
Using the built in connection manager to handle this was the very first thing I tried, and it had to be refactored out because it didn't work well enough in practice (e.g. connections would go stale, because they existed but didn't work because it seemed like they timed out and that wasn't being checked for by the connection manager).
The approach we have ended up with comes from real-world cross database testing, with some insights from Stack Overflow from folks who had run into similar problems with TypeORM and had to write their own connection handlers. If you'd like to raise a PR to suggest any specific improvements for folks to test out and to feedback on, that is always welcome.
Also try...catch method you use didn't work well for me for some reason (at least in HMR mode, I didn't check it in real serverless), but if has() then get() else create() works well.
Can you elaborate on what you mean by "didn't work well" for you?
Do have a replicable problem or get an error message?
After several hours of running locally with Postgres, MySQL, MongoDB and SQLite databases I haven't run into any issues (touch wood), but if you are getting an error or encountering a recurring problem we can replicate that's something we might be able to help with.
For me, now I'm getting this error on any API route π€―
(node:8400) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:63:28
at Generator.next (<anonymous>)
at asyncGeneratorStep (/Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:44:103)
at _next (/Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:194)
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:364
at new Promise (<anonymous>)
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:97
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:312:22
at new Promise (<anonymous>)
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:53:12
at Generator.next (<anonymous>)
at asyncGeneratorStep (/Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:44:103)
at _next (/Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:194)
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:364
at new Promise (<anonymous>)
at /Users/lluis.agusti/Code/hip-hub/node_modules/next-auth/dist/server/index.js:46:97
(node:8400) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:8400) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 15)
[next-auth][error][CLIENT_FETCH_ERROR] [
'http://localhost:3000/api/auth/session',
FetchError: request to http://localhost:3000/api/auth/session failed, reason: socket hang up
at ClientRequest.<anonymous> (/Users/lluis.agusti/Code/hip-hub/node_modules/next/dist/compiled/node-fetch/index.js:1:147710)
at ClientRequest.emit (events.js:311:20)
at Socket.socketOnEnd (_http_client.js:460:9)
at Socket.emit (events.js:323:22)
which refers to this line, and happens in both 3.0.0-beta, 2.2.0 and 2.2.1-beta.
My project is running on TS; I guess JS is fine ππ»ββοΈ
I simplified my route to the simplest ( and moved to JWT to discard issues with TypeORM )
// pages/api/github/get-token
import { setOptions, getSession } from 'next-auth/client'
import { NextApiRequest, NextApiResponse } from 'next'
setOptions({ site: process.env.NEXTAUTH_URL })
export default async function getToken(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getSession({ req })
console.log('>>>>>>>>> session', session)
res.end()
}
with this config:
{
site: process.env.NEXTAUTH_URL!,
providers: [
Providers.GitHub({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
scope:
'user public_repo repo repo_deployment repo:status read:repo_hook read:org read:public_key read:gpg_key',
}),
],
secret: process.env.JWT_SECRET,
session: {
jwt: true,
},
callbacks: {
jwt: async (token, oAuthProfile) => {
console.log('>>>>>>', token)
console.log('>>>>>>', oAuthProfile)
},
},
}
but the server blows-up π₯ with the strange error above.
I noticed @arnodel was pointing a similar issue here.
@lluia Yup, getting the same issue now that I've updated to 2.2.0
So ive run into the same problem (https://github.com/iaincollins/next-auth/issues/467) in regards to https://github.com/iaincollins/next-auth/issues/390#issuecomment-654160452 around HMR and TypeORM. This effectively makes dev unusable since changing any file basically causes a connection issue. Has anyone managed to find a workaround to this problem? I am using typescript with next and not js.
Here is an example https://github.com/deep-c/next-auth-typeorm . Basically any sort of reload happens I get an EntityMetadataNotFound error.
Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!
Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!
Most helpful comment
@lluia Yeah sorry needing to call
NextAuth.setOptions()here is annoying - this is fixed in v3 as it uses an environment variable to configure it everywhere in the app once, instead of needing to set thesiteoption in multiple places!The example site at https://next-auth-example.now.sh is actually doing this running v3 beta if you'd like an example :-)
RE: TypeORM connection - We should have a tutorial for how to do things like this for sure!
I was really surprised how much custom connection handling code was required with NextAuth.js and would be interested to hear from TypeORM folks on their opinion on the approach we have taken, and if they can suggest ways it could be simplified, without triggering some of the issues we saw that lead to us taking the approach we currently have.