6bae1f1a89
* Always switch to user we just logged in as If we're logged in and switch to anon and then use login to get into our previous account instead of using 'switch accounts', we only updated the JWT but we didn't switch to the user. * Fix getToken unaware of multi-auth middleware If we use login with new credentials while switched to anon (multi_auth.user-id === 'anonymous'), we updated the pubkey because getToken wasn't aware of the switch and thus believed we're logged in as a user. This is fixed by applying the middleware before calling getToken.
124 lines
3.9 KiB
JavaScript
124 lines
3.9 KiB
JavaScript
import { ApolloServer } from '@apollo/server'
|
|
import { startServerAndCreateNextHandler } from '@as-integrations/next'
|
|
import resolvers from '@/api/resolvers'
|
|
import models from '@/api/models'
|
|
import lnd from '@/api/lnd'
|
|
import typeDefs from '@/api/typeDefs'
|
|
import { getServerSession } from 'next-auth/next'
|
|
import { getAuthOptions } from './auth/[...nextauth]'
|
|
import search from '@/api/search'
|
|
import {
|
|
ApolloServerPluginLandingPageLocalDefault,
|
|
ApolloServerPluginLandingPageProductionDefault
|
|
} from '@apollo/server/plugin/landingPage/default'
|
|
|
|
const apolloServer = new ApolloServer({
|
|
typeDefs,
|
|
resolvers,
|
|
introspection: true,
|
|
allowBatchedHttpRequests: true,
|
|
plugins: [{
|
|
requestDidStart (initialRequestContext) {
|
|
return {
|
|
executionDidStart () {
|
|
return {
|
|
willResolveField ({ source, args, context, info }) {
|
|
const start = process.hrtime.bigint()
|
|
return (error, result) => {
|
|
const end = process.hrtime.bigint()
|
|
const ms = (end - start) / 1000000n
|
|
if (process.env.GRAPHQL_SLOW_LOGS_MS && ms > process.env.GRAPHQL_SLOW_LOGS_MS) {
|
|
console.log(`Field ${info.parentType.name}.${info.fieldName} took ${ms}ms`)
|
|
}
|
|
if (error) {
|
|
console.log(`Field ${info.parentType.name}.${info.fieldName} failed with ${error}`)
|
|
}
|
|
}
|
|
},
|
|
async executionDidEnd (err) {
|
|
if (err) {
|
|
console.error('hey bud', err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
process.env.NODE_ENV === 'production'
|
|
? ApolloServerPluginLandingPageProductionDefault(
|
|
{ embed: { endpointIsEditable: false, persistExplorerState: true, displayOptions: { theme: 'dark' } }, footer: false })
|
|
: ApolloServerPluginLandingPageLocalDefault(
|
|
{ embed: { endpointIsEditable: false, persistExplorerState: true, displayOptions: { theme: 'dark' } }, footer: false })]
|
|
})
|
|
|
|
export default startServerAndCreateNextHandler(apolloServer, {
|
|
context: async (req, res) => {
|
|
const apiKey = req.headers['x-api-key']
|
|
let session
|
|
if (apiKey) {
|
|
const [user] = await models.$queryRaw`
|
|
SELECT id, name, "apiKeyEnabled"
|
|
FROM users
|
|
WHERE "apiKeyHash" = encode(digest(${apiKey}, 'sha256'), 'hex')
|
|
LIMIT 1`
|
|
if (user?.apiKeyEnabled) {
|
|
const { apiKeyEnabled, ...sessionFields } = user
|
|
session = { user: { ...sessionFields, apiKey: true } }
|
|
}
|
|
} else {
|
|
req = multiAuthMiddleware(req)
|
|
session = await getServerSession(req, res, getAuthOptions(req))
|
|
}
|
|
return {
|
|
models,
|
|
headers: req.headers,
|
|
lnd,
|
|
me: session
|
|
? session.user
|
|
: null,
|
|
search
|
|
}
|
|
}
|
|
})
|
|
|
|
export function multiAuthMiddleware (request) {
|
|
// switch next-auth session cookie with multi_auth cookie if cookie pointer present
|
|
|
|
// is there a cookie pointer?
|
|
const cookiePointerName = 'multi_auth.user-id'
|
|
const hasCookiePointer = !!request.cookies[cookiePointerName]
|
|
|
|
const secure = process.env.NODE_ENV === 'production'
|
|
|
|
// is there a session?
|
|
const sessionCookieName = secure ? '__Secure-next-auth.session-token' : 'next-auth.session-token'
|
|
const hasSession = !!request.cookies[sessionCookieName]
|
|
|
|
if (!hasCookiePointer || !hasSession) {
|
|
// no session or no cookie pointer. do nothing.
|
|
return request
|
|
}
|
|
|
|
const userId = request.cookies[cookiePointerName]
|
|
if (userId === 'anonymous') {
|
|
// user switched to anon. only delete session cookie.
|
|
delete request.cookies[sessionCookieName]
|
|
return request
|
|
}
|
|
|
|
const userJWT = request.cookies[`multi_auth.${userId}`]
|
|
if (!userJWT) {
|
|
// no JWT for account switching found
|
|
return request
|
|
}
|
|
|
|
if (userJWT) {
|
|
// use JWT found in cookie pointed to by cookie pointer
|
|
request.cookies[sessionCookieName] = userJWT
|
|
return request
|
|
}
|
|
|
|
return request
|
|
}
|