Last active
April 22, 2024 17:13
-
-
Save gue-ni/39751d1122822ee6cf21f756b34c2c5a to your computer and use it in GitHub Desktop.
NextAuth.js postgres adapter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import NextAuth from "next-auth"; | |
import GoogleProvider from "next-auth/providers/google"; | |
import PostgresAdapter from "../../../lib/adapter"; | |
const pool = new Pool({ | |
user: "postgres", | |
host: "localhost", | |
database: "postgres", | |
password: "postgres", | |
port: 5432, | |
}); | |
export default NextAuth({ | |
providers: [ | |
GoogleProvider({ | |
clientId: process.env.GOOGLE_ID, | |
clientSecret: process.env.GOOGLE_SECRET, | |
}), | |
], | |
adapter: PostgresAdapter(pool), | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default function PostgresAdapter(client, options = {}) { | |
return { | |
async createUser(user) { | |
try { | |
const sql = ` | |
INSERT INTO users (name, email, email_verified, image) | |
VALUES ($1, $2, $3, $4) | |
RETURNING id, name, email, email_verified, image`; | |
let result = await client.query(sql, [user.name, user.email, user.emailVerified, user.image]); | |
return result.rows[0]; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async getUser(id) { | |
try { | |
const sql = `select * from users where id = $1`; | |
let result = await client.query(sql, [id]); | |
return result.rows[0]; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async getUserByEmail(email) { | |
try { | |
const sql = `select * from users where email = $1`; | |
let result = await client.query(sql, [email]); | |
return result.rows[0]; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async getUserByAccount({ providerAccountId, provider }) { | |
try { | |
const sql = ` | |
select u.* from users u join accounts a on u.id = a.user_id | |
where | |
a.provider_id = $1 | |
and | |
a.provider_account_id = $2`; | |
const result = await client.query(sql, [provider, providerAccountId]); | |
return result.rows[0]; | |
} catch (err) { | |
console.log(err); | |
} | |
}, | |
async updateUser(user) { | |
try { | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async linkAccount(account) { | |
try { | |
const sql = ` | |
insert into accounts | |
( | |
user_id, | |
provider_id, | |
provider_type, | |
provider_account_id, | |
access_token, | |
access_token_expires | |
) | |
values ($1, $2, $3, $4, $5, to_timestamp($6))`; | |
const params = [ | |
account.userId, | |
account.provider, | |
account.type, | |
account.providerAccountId, | |
account.access_token, | |
account.expires_at, | |
]; | |
await client.query(sql, params); | |
return account; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async createSession({ sessionToken, userId, expires }) { | |
try { | |
const sql = `insert into sessions (user_id, expires, session_token) values ($1, $2, $3)`; | |
await client.query(sql, [userId, expires, sessionToken]); | |
return { sessionToken, userId, expires }; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async getSessionAndUser(sessionToken) { | |
try { | |
let result; | |
result = await client.query("select * from sessions where session_token = $1", [sessionToken]); | |
let session = result.rows[0]; | |
result = await client.query("select * from users where id = $1", [session.user_id]); | |
let user = result.rows[0]; | |
return { | |
session, | |
user, | |
}; | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
async updateSession({ sessionToken }) { | |
console.log("updateSession", sessionToken); | |
return; | |
}, | |
async deleteSession(sessionToken) { | |
try { | |
const sql = `delete from sessions where session_token = $1`; | |
await client.query(sql, [sessionToken]); | |
} catch (err) { | |
console.log(err); | |
return; | |
} | |
}, | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE TABLE accounts | |
( | |
id SERIAL, | |
compound_id VARCHAR(255), -- removed not null | |
user_id INTEGER NOT NULL, | |
provider_type VARCHAR(255) NOT NULL, | |
provider_id VARCHAR(255) NOT NULL, | |
provider_account_id VARCHAR(255) NOT NULL, | |
refresh_token TEXT, | |
access_token TEXT, | |
access_token_expires TIMESTAMPTZ, | |
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
PRIMARY KEY (id) | |
); | |
CREATE TABLE sessions | |
( | |
id SERIAL, | |
user_id INTEGER NOT NULL, | |
expires TIMESTAMPTZ NOT NULL, | |
session_token VARCHAR(255) NOT NULL, | |
access_token VARCHAR(255), -- removed not null | |
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
PRIMARY KEY (id) | |
); | |
CREATE TABLE users | |
( | |
id SERIAL, | |
name VARCHAR(255), | |
email VARCHAR(255), | |
email_verified TIMESTAMPTZ, | |
image TEXT, | |
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
PRIMARY KEY (id) | |
); | |
CREATE UNIQUE INDEX compound_id ON accounts(compound_id); | |
CREATE INDEX provider_account_id ON accounts(provider_account_id); | |
CREATE INDEX provider_id ON accounts(provider_id); | |
CREATE INDEX user_id ON accounts(user_id); | |
CREATE UNIQUE INDEX session_token ON sessions(session_token); | |
CREATE UNIQUE INDEX access_token ON sessions(access_token); | |
CREATE UNIQUE INDEX email ON users(email); |
Is this next-auth 4 compatible?
Thanks for this, however as I used this on next auth v4, I always getting error about getSessionAndUser method, is this still working?
what error are you getting?
what error are you getting?
on getSessionAndUser, as I check the DB it will not save in the session table.
I'm using Credentials Provider btw
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this,
however as I used this on next auth v4, I always getting error about getSessionAndUser method, is this still working?