From c9de1140fadde3f864cd05dce372beebde0f9440 Mon Sep 17 00:00:00 2001 From: Soxasora Date: Fri, 21 Feb 2025 12:32:56 +0100 Subject: [PATCH] Invalidate all sessions by keeping track of session revision --- api/resolvers/user.js | 8 ++++++ api/typeDefs/user.js | 2 ++ fragments/users.js | 2 ++ pages/api/auth/[...nextauth].js | 6 +++++ pages/settings/index.js | 27 +++++++++++++++++++ .../migration.sql | 2 ++ prisma/schema.prisma | 1 + 7 files changed, 48 insertions(+) create mode 100644 prisma/migrations/20250221103652_invalidate_sessions/migration.sql diff --git a/api/resolvers/user.js b/api/resolvers/user.js index 782380756..e6d8e6d19 100644 --- a/api/resolvers/user.js +++ b/api/resolvers/user.js @@ -898,6 +898,14 @@ export default { await models.user.update({ where: { id: me.id }, data: { hideWelcomeBanner: true } }) return true + }, + invalidateSessions: async (parent, args, { me, models }) => { + if (!me) { + throw new GqlAuthenticationError() + } + + await models.user.update({ where: { id: me.id }, data: { sessionRev: { increment: 1 } } }) + return true } }, diff --git a/api/typeDefs/user.js b/api/typeDefs/user.js index fd26838ce..0453f808f 100644 --- a/api/typeDefs/user.js +++ b/api/typeDefs/user.js @@ -44,6 +44,7 @@ export default gql` generateApiKey(id: ID!): String deleteApiKey(id: ID!): User disableFreebies: Boolean + invalidateSessions: Boolean } type User { @@ -197,6 +198,7 @@ export default gql` walletsUpdatedAt: Date proxyReceive: Boolean directReceive: Boolean + sessionRev: Int receiveCreditsBelowSats: Int! sendCreditsBelowSats: Int! } diff --git a/fragments/users.js b/fragments/users.js index 94e1a7a67..b56f62100 100644 --- a/fragments/users.js +++ b/fragments/users.js @@ -54,6 +54,7 @@ ${STREAK_FIELDS} walletsUpdatedAt proxyReceive directReceive + sessionRev } optional { isContributor @@ -117,6 +118,7 @@ export const SETTINGS_FIELDS = gql` apiKeyEnabled proxyReceive directReceive + sessionRev receiveCreditsBelowSats sendCreditsBelowSats } diff --git a/pages/api/auth/[...nextauth].js b/pages/api/auth/[...nextauth].js index 8f2d7ffa4..431ded963 100644 --- a/pages/api/auth/[...nextauth].js +++ b/pages/api/auth/[...nextauth].js @@ -98,6 +98,7 @@ function getCallbacks (req, res) { // token won't have an id on it for new logins, we add it // note: token is what's kept in the jwt token.id = Number(user.id) + token.sessionRev = user.sessionRev || 0 // if referrer exists, set on user // isNewUser doesn't work for nostr/lightning auth because we create the user before nextauth can @@ -143,6 +144,11 @@ function getCallbacks (req, res) { // and returns a new object session that's returned whenever get|use[Server]Session is called session.user.id = token.id + // invalidate this session if session revision mismatch + session.user.sessionRev = token.sessionRev || 0 // if no sessionRev, set to 0, the user will have one after login + const sessionRev = await prisma.user.findUnique({ where: { id: session.user.id }, select: { sessionRev: true } }) + if (session.user.sessionRev !== sessionRev?.sessionRev) return {} + return session } } diff --git a/pages/settings/index.js b/pages/settings/index.js index 5ad2f813c..c6cc48c9e 100644 --- a/pages/settings/index.js +++ b/pages/settings/index.js @@ -886,6 +886,7 @@ function AuthMethods ({ methods, apiKeyEnabled }) { ) } })} + ) @@ -1188,3 +1189,29 @@ const TipRandomField = () => { ) } + +const InvalidateSessions = () => { + const showModal = useShowModal() + const router = useRouter() + + const [invalidateSessions] = useMutation(gql` + mutation invalidateSessions { + invalidateSessions + }` + ) + + return ( + + ) +} diff --git a/prisma/migrations/20250221103652_invalidate_sessions/migration.sql b/prisma/migrations/20250221103652_invalidate_sessions/migration.sql new file mode 100644 index 000000000..eea333e55 --- /dev/null +++ b/prisma/migrations/20250221103652_invalidate_sessions/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "sessionRev" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a3f986b62..4af1d5980 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -123,6 +123,7 @@ model User { mcredits BigInt @default(0) receiveCreditsBelowSats Int @default(10) sendCreditsBelowSats Int @default(10) + sessionRev Int @default(0) muters Mute[] @relation("muter") muteds Mute[] @relation("muted") ArcOut Arc[] @relation("fromUser")