Add PrismaORM
preparation for access_token refresh, since JWT cookies cannot be refreshed from the server side
This commit is contained in:
parent
c25bf01d53
commit
b4503db688
9 changed files with 267 additions and 6 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -41,3 +41,6 @@ next-env.d.ts
|
|||
/result-lib
|
||||
.direnv
|
||||
.env
|
||||
|
||||
# prisma
|
||||
schnabu-web.db
|
||||
|
|
25
auth.ts
25
auth.ts
|
@ -1,13 +1,18 @@
|
|||
import NextAuth,{ type DefaultSession } from "next-auth";
|
||||
import Authentik from "next-auth/providers/authentik";
|
||||
import { PrismaAdapter } from "@auth/prisma-adapter"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
declare module "next-auth" {
|
||||
interface Session {
|
||||
access_token: string;
|
||||
access_token: string | null;
|
||||
}
|
||||
}
|
||||
|
||||
export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
adapter: PrismaAdapter(prisma),
|
||||
providers: [Authentik({
|
||||
clientId: process.env.AUTH_OIDC_CLIENT_ID,
|
||||
clientSecret: process.env.AUTH_OIDC_CLIENT_SECRET,
|
||||
|
@ -21,12 +26,20 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
|||
}
|
||||
return token
|
||||
},
|
||||
async session({session, token}) {
|
||||
if(session) {
|
||||
session = Object.assign({}, session, {access_token: token.access_token})
|
||||
console.log(session);
|
||||
async session({session, user}) {
|
||||
const getToken = await prisma.account.findFirst({
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
let accessToken: string | null = null;
|
||||
if (getToken) {
|
||||
accessToken = getToken.access_token!;
|
||||
}
|
||||
return session
|
||||
|
||||
session.access_token = accessToken;
|
||||
return session;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
10
flake.nix
10
flake.nix
|
@ -17,6 +17,9 @@
|
|||
devShells = eachSystem (pkgs: {
|
||||
default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.openssl
|
||||
pkgs.prisma-engines
|
||||
|
||||
pkgs.nodejs
|
||||
|
||||
pkgs.nodePackages.pnpm
|
||||
|
@ -24,6 +27,13 @@
|
|||
pkgs.nodePackages.typescript
|
||||
pkgs.nodePackages.typescript-language-server
|
||||
];
|
||||
shellHook = ''
|
||||
export PRISMA_SCHEMA_ENGINE_BINARY="${pkgs.prisma-engines}/bin/schema-engine"
|
||||
export PRISMA_QUERY_ENGINE_BINARY="${pkgs.prisma-engines}/bin/query-engine"
|
||||
export PRISMA_QUERY_ENGINE_LIBRARY="${pkgs.prisma-engines}/lib/libquery_engine.node"
|
||||
export PRISMA_FMT_BINARY="${pkgs.prisma-engines}/bin/prisma-fmt"
|
||||
export PATH="$PWD/node_modules/.bin/:$PATH"
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/prisma-adapter": "^2.1.0",
|
||||
"@prisma/client": "^5.14.0",
|
||||
"next": "14.2.3",
|
||||
"next-auth": "5.0.0-beta.18",
|
||||
"react": "^18",
|
||||
|
@ -21,6 +23,7 @@
|
|||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.3",
|
||||
"postcss": "^8",
|
||||
"prisma": "^5.14.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,12 @@ settings:
|
|||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@auth/prisma-adapter':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(@prisma/client@5.14.0)
|
||||
'@prisma/client':
|
||||
specifier: ^5.14.0
|
||||
version: 5.14.0(prisma@5.14.0)
|
||||
next:
|
||||
specifier: 14.2.3
|
||||
version: 14.2.3(react-dom@18.3.1)(react@18.3.1)
|
||||
|
@ -37,6 +43,9 @@ devDependencies:
|
|||
postcss:
|
||||
specifier: ^8
|
||||
version: 8.4.38
|
||||
prisma:
|
||||
specifier: ^5.14.0
|
||||
version: 5.14.0
|
||||
tailwindcss:
|
||||
specifier: ^3.4.1
|
||||
version: 3.4.3
|
||||
|
@ -74,6 +83,19 @@ packages:
|
|||
preact-render-to-string: 5.2.3(preact@10.11.3)
|
||||
dev: false
|
||||
|
||||
/@auth/prisma-adapter@2.1.0(@prisma/client@5.14.0):
|
||||
resolution: {integrity: sha512-x1gYsi8xCFdxpEM6pxhh7OTV+VHB3PgID2L18y8F1kXu+PbcEWt4VZSQ8zk6dI/4YRStcuwQdHe7neCpczr0mg==}
|
||||
peerDependencies:
|
||||
'@prisma/client': '>=2.26.0 || >=3 || >=4 || >=5'
|
||||
dependencies:
|
||||
'@auth/core': 0.31.0
|
||||
'@prisma/client': 5.14.0(prisma@5.14.0)
|
||||
transitivePeerDependencies:
|
||||
- '@simplewebauthn/browser'
|
||||
- '@simplewebauthn/server'
|
||||
- nodemailer
|
||||
dev: false
|
||||
|
||||
/@babel/runtime@7.24.5:
|
||||
resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -303,6 +325,46 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/@prisma/client@5.14.0(prisma@5.14.0):
|
||||
resolution: {integrity: sha512-akMSuyvLKeoU4LeyBAUdThP/uhVP3GuLygFE3MlYzaCb3/J8SfsYBE5PkaFuLuVpLyA6sFoW+16z/aPhNAESqg==}
|
||||
engines: {node: '>=16.13'}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
prisma: '*'
|
||||
peerDependenciesMeta:
|
||||
prisma:
|
||||
optional: true
|
||||
dependencies:
|
||||
prisma: 5.14.0
|
||||
dev: false
|
||||
|
||||
/@prisma/debug@5.14.0:
|
||||
resolution: {integrity: sha512-iq56qBZuFfX3fCxoxT8gBX33lQzomBU0qIUaEj1RebsKVz1ob/BVH1XSBwwwvRVtZEV1b7Fxx2eVu34Ge/mg3w==}
|
||||
|
||||
/@prisma/engines-version@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48:
|
||||
resolution: {integrity: sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==}
|
||||
|
||||
/@prisma/engines@5.14.0:
|
||||
resolution: {integrity: sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@prisma/debug': 5.14.0
|
||||
'@prisma/engines-version': 5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48
|
||||
'@prisma/fetch-engine': 5.14.0
|
||||
'@prisma/get-platform': 5.14.0
|
||||
|
||||
/@prisma/fetch-engine@5.14.0:
|
||||
resolution: {integrity: sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==}
|
||||
dependencies:
|
||||
'@prisma/debug': 5.14.0
|
||||
'@prisma/engines-version': 5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48
|
||||
'@prisma/get-platform': 5.14.0
|
||||
|
||||
/@prisma/get-platform@5.14.0:
|
||||
resolution: {integrity: sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==}
|
||||
dependencies:
|
||||
'@prisma/debug': 5.14.0
|
||||
|
||||
/@rushstack/eslint-patch@1.10.3:
|
||||
resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==}
|
||||
dev: true
|
||||
|
@ -2294,6 +2356,14 @@ packages:
|
|||
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
|
||||
dev: false
|
||||
|
||||
/prisma@5.14.0:
|
||||
resolution: {integrity: sha512-gCNZco7y5XtjrnQYeDJTiVZmT/ncqCr5RY1/Cf8X2wgLRmyh9ayPAGBNziI4qEE4S6SxCH5omQLVo9lmURaJ/Q==}
|
||||
engines: {node: '>=16.13'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@prisma/engines': 5.14.0
|
||||
|
||||
/prop-types@15.8.1:
|
||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||
dependencies:
|
||||
|
|
77
prisma/migrations/20240519155316_init_authjs/migration.sql
Normal file
77
prisma/migrations/20240519155316_init_authjs/migration.sql
Normal file
|
@ -0,0 +1,77 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT,
|
||||
"email" TEXT,
|
||||
"emailVerified" DATETIME,
|
||||
"image" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Account" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"userId" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"provider" TEXT NOT NULL,
|
||||
"providerAccountId" TEXT NOT NULL,
|
||||
"refresh_token" TEXT,
|
||||
"access_token" TEXT,
|
||||
"expires_at" INTEGER,
|
||||
"token_type" TEXT,
|
||||
"scope" TEXT,
|
||||
"id_token" TEXT,
|
||||
"session_state" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Session" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"sessionToken" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"expires" DATETIME NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "VerificationToken" (
|
||||
"identifier" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"expires" DATETIME NOT NULL
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Authenticator" (
|
||||
"credentialID" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"providerAccountId" TEXT NOT NULL,
|
||||
"credentialPublicKey" TEXT NOT NULL,
|
||||
"counter" INTEGER NOT NULL,
|
||||
"credentialDeviceType" TEXT NOT NULL,
|
||||
"credentialBackedUp" BOOLEAN NOT NULL,
|
||||
"transports" TEXT,
|
||||
|
||||
PRIMARY KEY ("userId", "credentialID"),
|
||||
CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");
|
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "sqlite"
|
80
prisma/schema-sqlite.prisma
Normal file
80
prisma/schema-sqlite.prisma
Normal file
|
@ -0,0 +1,80 @@
|
|||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = "file:./schnabu-web.db"
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String? @unique
|
||||
emailVerified DateTime?
|
||||
image String?
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
// Optional for WebAuthn support
|
||||
Authenticator Authenticator[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
type String
|
||||
provider String
|
||||
providerAccountId String
|
||||
refresh_token String?
|
||||
access_token String?
|
||||
expires_at Int?
|
||||
token_type String?
|
||||
scope String?
|
||||
id_token String?
|
||||
session_state String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([provider, providerAccountId])
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
sessionToken String @unique
|
||||
userId String
|
||||
expires DateTime
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model VerificationToken {
|
||||
identifier String
|
||||
token String
|
||||
expires DateTime
|
||||
|
||||
@@unique([identifier, token])
|
||||
}
|
||||
|
||||
// Optional for WebAuthn support
|
||||
model Authenticator {
|
||||
credentialID String @unique
|
||||
userId String
|
||||
providerAccountId String
|
||||
credentialPublicKey String
|
||||
counter Int
|
||||
credentialDeviceType String
|
||||
credentialBackedUp Boolean
|
||||
transports String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([userId, credentialID])
|
||||
}
|
|
@ -2,6 +2,8 @@ import { signIn,signOut, auth } from "auth"
|
|||
|
||||
export default async function Home() {
|
||||
let session = await auth();
|
||||
|
||||
console.log(session?.access_token)
|
||||
return (
|
||||
<>
|
||||
<h1>Hello {session?.user?.name}!</h1>
|
||||
|
|
Loading…
Reference in a new issue