Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: moving cookie related logic to cookieAdapter.ts #42

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
801 changes: 0 additions & 801 deletions .yarn/releases/yarn-3.2.4.cjs

This file was deleted.

2 changes: 0 additions & 2 deletions .yarnrc

This file was deleted.

5 changes: 0 additions & 5 deletions .yarnrc.yml

This file was deleted.

6,255 changes: 2,787 additions & 3,468 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

59 changes: 0 additions & 59 deletions src/session-adapters/cookieAdapter.ts

This file was deleted.

81 changes: 81 additions & 0 deletions src/session-adapters/createCookieAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { expireCookie, getCookie, setCookie, verifyData } from '../utils'
import jwt from 'jsonwebtoken'
import { Adapter } from './publicAdapter'
import { isAppSession } from '../session'

const clientSecret = process.env['CLIENT_SECRET'] || ''
const defaultSessionKey = 'sb.auth'

type CreateCookieAdapter = (params?: {
sessionKey?: string | undefined
}) => Adapter

export const createCookieAdapter: CreateCookieAdapter = (params) => {
const key = params?.sessionKey ?? defaultSessionKey

const adapter: Adapter = {
getSession: ({ req, spaceId, userId }) => {
const cookie = getCookie(req, createScopedKey({ spaceId, userId, key }))

if (!cookie) {
return undefined
}

const verifiedData = verifyData(clientSecret, cookie)

if (!isAppSession(verifiedData)) {
return undefined
}

return verifiedData
},

setSession: ({ res, spaceId, userId, session }) => {
const expires = createExpirationDate(7)

const signedData = jwt.sign({ data: session }, clientSecret)

setCookie(
res,
createScopedKey({ spaceId, userId, key }),
signedData,
expires,
)
return true
},

hasSession: (params) => {
const session = adapter.getSession(params)
return session !== undefined
},

removeSession: ({ res, spaceId, userId }) => {
expireCookie(res, createScopedKey({ spaceId, userId, key }))
return true
},
}

return adapter
}

// We do not use `clientId` in cookie adapter,
// because different plugins will have different domain names,
// and it's enough to differentiate these cookie values.
const createScopedKey = ({
spaceId,
userId,
key,
}: {
spaceId: string
userId: string
key: string
}) => {
return `${spaceId}:${userId}:${key}`
}

//TODO: extract to util
const createExpirationDate = (days: number): Date => {
const expires = new Date()
expires.setDate(expires.getDate() + days)
return expires
}
2 changes: 1 addition & 1 deletion src/session-adapters/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './cookieAdapter'
export * from './createCookieAdapter'
export * from './publicAdapter'
export * from './internalAdapter'
80 changes: 45 additions & 35 deletions src/session-adapters/internalAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../utils'
import { AppSession } from '../session/types'
import { AuthHandlerParams } from '../storyblok-auth-api'
import { sessionIdentifier } from '../session/sessionIdentifier'

export type InternalAdapter = {
// session
Expand Down Expand Up @@ -52,7 +51,7 @@ type CreateInternalAdapter = ({
res,
adapter,
}: {
params: Pick<AuthHandlerParams, 'clientId' | 'clientSecret' | 'sessionKey'>
params: Pick<AuthHandlerParams, 'clientId' | 'clientSecret'>
req: http.IncomingMessage
res: http.ServerResponse
adapter: Adapter
Expand All @@ -64,65 +63,76 @@ export const createInternalAdapter: CreateInternalAdapter = ({
res,
adapter,
}) => {
const sessionKey = sessionIdentifier(params.sessionKey)

return {
getSession: async ({ spaceId, userId }) => {
const session = await adapter.getItem({
req,
res,
clientId: params.clientId,
spaceId,
userId,
key: sessionKey,
})
if (!session) {
return undefined
}
try {
return JSON.parse(session) as AppSession
} catch (err) {
const session = await adapter.getSession({
req,
res,
clientId: params.clientId,
spaceId,
userId,
})

if (!session) {
return undefined
}

return session
} catch (e) {
console.log('Retrieving the session failed: ', e)
return undefined
}
},

setSession: async ({ spaceId, userId, session }) => {
try {
return await adapter.setItem({
const isSessionSet = await adapter.setSession({
req,
res,
clientId: params.clientId,
spaceId,
userId,
key: sessionKey,
value: JSON.stringify(session),
session,
})
} catch (err) {

return isSessionSet
} catch (e) {
console.log('Setting the session failed: ', e)
return false
}
},

hasSession: ({ spaceId, userId }) =>
adapter.hasItem({
req,
res,
clientId: params.clientId,
spaceId,
userId,
key: sessionKey,
}),
hasSession: async ({ spaceId, userId }) => {
try {
const hasSession = await adapter.hasSession({
req,
res,
clientId: params.clientId,
spaceId,
userId,
})

return hasSession
} catch (e) {
console.log('Session could not be found: ', e)
return false
}
},

removeSession: async ({ spaceId, userId }) => {
try {
return await adapter.removeItem({
const sessionRemoved = await adapter.removeSession({
req,
res,
clientId: params.clientId,
spaceId,
userId,
key: sessionKey,
})
} catch (err) {

return sessionRemoved
} catch (e) {
console.log('Removing the session failed: ', e)
return false
}
},
Expand All @@ -133,15 +143,15 @@ export const createInternalAdapter: CreateInternalAdapter = ({
return true
},

getCallbackData() {
getCallbackData: () => {
const cookie = getCookie(req, callbackCookieName)
const data = verifyData(params.clientSecret, cookie || '') as
| CallbackCookieData
| undefined
return data
},

removeCallbackData() {
removeCallbackData: () => {
expireCookie(res, callbackCookieName)
return true
},
Expand Down
59 changes: 25 additions & 34 deletions src/session-adapters/publicAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,33 @@
import { IncomingMessage, ServerResponse } from 'node:http'
import { AppSession } from '../session'

export type MaybePromise<T> = T | Promise<T>

export type Adapter = {
getItem: (params: {
req: IncomingMessage
res: ServerResponse
clientId: string
spaceId: string
userId: string
key: string
}) => MaybePromise<string | undefined>
getSession: GetSession
setSession: SetSession
removeSession: RemoveSession
hasSession: HasSession
}

setItem: (params: {
req: IncomingMessage
res: ServerResponse
clientId: string
spaceId: string
userId: string
key: string
value: string
}) => MaybePromise<boolean>
type BaseSessionParams = {
req: IncomingMessage
res: ServerResponse
clientId: string
spaceId: string
userId: string
}

removeItem: (params: {
req: IncomingMessage
res: ServerResponse
clientId: string
spaceId: string
userId: string
key: string
}) => MaybePromise<boolean>
type GetSession = (
params: BaseSessionParams,
) => MaybePromise<AppSession | undefined>

hasItem: (params: {
req: IncomingMessage
res: ServerResponse
clientId: string
spaceId: string
userId: string
key: string
}) => MaybePromise<boolean>
}
type SetSession = (
params: BaseSessionParams & {
session: AppSession
},
) => MaybePromise<boolean>

type RemoveSession = (params: BaseSessionParams) => MaybePromise<boolean>

type HasSession = (params: BaseSessionParams) => MaybePromise<boolean>
Loading