Skip to content

Commit

Permalink
feat(passport): custom domain
Browse files Browse the repository at this point in the history
  • Loading branch information
szkl committed May 29, 2023
1 parent e161906 commit c58de35
Show file tree
Hide file tree
Showing 20 changed files with 184 additions and 61 deletions.
10 changes: 7 additions & 3 deletions apps/passport/app/auth.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import {
import { TwitterStrategy } from 'remix-auth-twitter'

import { AppleStrategy } from '~/utils/applestrategy.server'
import { getCookieDomain } from './utils/cookie'

// OAuth state

export const createAuthenticatorSessionStorage = (env: Env) => {
export const createAuthenticatorSessionStorage = (
request: Request,
env: Env
) => {
return createCookieSessionStorage({
cookie: {
domain: env.COOKIE_DOMAIN,
domain: getCookieDomain(request, env),
httpOnly: true,
name: 'external_oauth_login',
path: '/',
Expand All @@ -40,7 +44,7 @@ export const injectAuthnParamsIntoSession = async (
request: Request,
env: Env
) => {
const authenticatorStorage = createAuthenticatorSessionStorage(env)
const authenticatorStorage = createAuthenticatorSessionStorage(request, env)
const session = await authenticatorStorage.getSession(
request.headers.get('Cookie')
)
Expand Down
6 changes: 5 additions & 1 deletion apps/passport/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
},
{
headers: {
'Set-Cookie': await commitFlashSession(context.env, flashSession),
'Set-Cookie': await commitFlashSession(
request,
context.env,
flashSession
),
},
}
)
Expand Down
2 changes: 2 additions & 0 deletions apps/passport/app/routes/authorize.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
}

await createAuthzParamsCookieAndAuthenticate(
request,
context.authzQueryParams,
context.env
)
Expand All @@ -136,6 +137,7 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
if (lastCP) {
if (!authzParamsMatch(lastCP, context.authzQueryParams)) {
await createAuthzParamsCookieAndAuthenticate(
request,
context.authzQueryParams,
context.env
)
Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/apple/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorStorage = createAuthenticatorSessionStorage(context.env)
const authenticatorStorage = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorStorage)
authenticator.use(getAppleStrategy(context.env))

Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/discord/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorStorage = createAuthenticatorSessionStorage(context.env)
const authenticatorStorage = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorStorage)
authenticator.use(getDiscordStrategy(context.env))

Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/github/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorSession = createAuthenticatorSessionStorage(context.env)
const authenticatorSession = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorSession)
authenticator.use(getGithubAuthenticator(context.env))

Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/google/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorStorage = createAuthenticatorSessionStorage(context.env)
const authenticatorStorage = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorStorage)
authenticator.use(getGoogleAuthenticator(context.env))

Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/microsoft/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorStorage = createAuthenticatorSessionStorage(context.env)
const authenticatorStorage = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorStorage)
authenticator.use(getMicrosoftStrategy(context.env))

Expand Down
5 changes: 4 additions & 1 deletion apps/passport/app/routes/connect/twitter/callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(

const appData = await getAuthzCookieParams(request, context.env)

const authenticatorStorage = createAuthenticatorSessionStorage(context.env)
const authenticatorStorage = createAuthenticatorSessionStorage(
request,
context.env
)
const authenticator = new Authenticator(authenticatorStorage)
authenticator.use(getTwitterStrategy(context.env))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(

return redirect('/settings/applications', {
headers: {
'Set-Cookie': await commitFlashSession(context.env, session),
'Set-Cookie': await commitFlashSession(request, context.env, session),
},
})
}
Expand Down
2 changes: 1 addition & 1 deletion apps/passport/app/routes/settings/applications/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
},
{
headers: {
'Set-Cookie': await commitFlashSession(context.env, session),
'Set-Cookie': await commitFlashSession(request, context.env, session),
},
}
)
Expand Down
55 changes: 38 additions & 17 deletions apps/passport/app/session.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ import { AccountURNSpace } from '@proofzero/urns/account'
import type { AccountURN } from '@proofzero/urns/account'

import { FLASH_MESSAGE, FLASH_MESSAGE_KEY } from './utils/flashMessage.server'
import { getCookieDomain } from './utils/cookie'

export const InvalidSessionAccountError = new UnauthorizedError({
message: 'Session account is not valid',
})

// FLASH SESSION

const getFlashSessionStorage = (env: Env) => {
const getFlashSessionStorage = (request: Request, env: Env) => {
return createCookieSessionStorage({
cookie: {
domain: env.COOKIE_DOMAIN,
domain: getCookieDomain(request, env),
name: '_rollup_flash',
path: '/',
sameSite: 'lax',
Expand All @@ -46,18 +47,23 @@ const getFlashSessionStorage = (env: Env) => {
}

export function getFlashSession(request: Request, env: Env) {
const storage = getFlashSessionStorage(env)
const storage = getFlashSessionStorage(request, env)
return storage.getSession(request.headers.get('Cookie'))
}

export function commitFlashSession(env: Env, session: Session) {
const storage = getFlashSessionStorage(env)
export function commitFlashSession(
request: Request,
env: Env,
session: Session
) {
const storage = getFlashSessionStorage(request, env)
return storage.commitSession(session)
}

// USER PARAMS

const getUserSessionStorage = (
request: Request,
env: Env,
clientId?: string,
MAX_AGE = 7776000 /*60 * 60 * 24 * 90*/
Expand All @@ -68,7 +74,7 @@ const getUserSessionStorage = (
}

return createCookie(cookieName, {
domain: env.COOKIE_DOMAIN,
domain: getCookieDomain(request, env),
path: '/',
sameSite: 'lax',
secure: process.env.NODE_ENV == 'production',
Expand All @@ -78,12 +84,13 @@ const getUserSessionStorage = (
}

export async function createUserSession(
request: Request,
jwt: string,
redirectTo: string,
env: Env,
clientId?: string
) {
const cookie = getUserSessionStorage(env, clientId)
const cookie = getUserSessionStorage(request, env, clientId)
return redirect(redirectTo, {
headers: {
'Set-Cookie': await cookie.serialize(
Expand All @@ -98,7 +105,7 @@ export async function getUserSession(
env: Env,
clientId?: string
) {
const cookie = getUserSessionStorage(env, clientId)
const cookie = getUserSessionStorage(request, env, clientId)
const data = await cookie.parse(request.headers.get('Cookie'))
if (!data) return ''

Expand All @@ -122,13 +129,13 @@ export async function destroyUserSession(
) {
const headers = new Headers()

const cookie = await getUserSessionStorage(env, clientId)
const cookie = await getUserSessionStorage(request, env, clientId)
headers.append(
'Set-Cookie',
await cookie.serialize('', { expires: new Date(0) })
)

const flashStorage = getFlashSessionStorage(env)
const flashStorage = getFlashSessionStorage(request, env)
const flashSession = await flashStorage.getSession()
flashSession.flash(FLASH_MESSAGE_KEY, flashMessage)
headers.append('Set-Cookie', await flashStorage.commitSession(flashSession))
Expand All @@ -137,6 +144,7 @@ export async function destroyUserSession(
}

const getAuthzCookieParamsSessionStorage = (
request: Request,
env: Env,
clientId: string = 'last',
// https://developer.chrome.com/blog/cookie-max-age-expires/
Expand All @@ -146,7 +154,7 @@ const getAuthzCookieParamsSessionStorage = (
) => {
return createCookieSessionStorage({
cookie: {
domain: env.COOKIE_DOMAIN,
domain: getCookieDomain(request, env),
name: `_rollup_authz_params_${clientId}`,
path: '/',
sameSite: 'lax',
Expand All @@ -162,6 +170,7 @@ const getAuthzCookieParamsSessionStorage = (
* and redirects to the authentication route
*/
export async function createAuthzParamsCookieAndAuthenticate(
request: Request,
authzQueryParams: AuthzParams,
env: Env,
qp: URLSearchParams = new URLSearchParams()
Expand All @@ -185,13 +194,15 @@ export async function createAuthzParamsCookieAndAuthenticate(

throw redirect(redirectURL, {
headers: await createAuthorizationParamsCookieHeaders(
request,
authzQueryParams,
env
),
})
}

export async function createAuthorizationParamsCookieHeaders(
request: Request,
authzParams: AuthzParams,
env: Env
) {
Expand All @@ -204,22 +215,28 @@ export async function createAuthorizationParamsCookieHeaders(
const headers = new Headers()
headers.append(
'Set-Cookie',
await setAuthzCookieParamsSession(authzParams, env, authzParams.clientId)
await setAuthzCookieParamsSession(
request,
authzParams,
env,
authzParams.clientId
)
)
headers.append(
'Set-Cookie',
await setAuthzCookieParamsSession(authzParams, env)
await setAuthzCookieParamsSession(request, authzParams, env)
)

return headers
}

export async function setAuthzCookieParamsSession(
request: Request,
authzParams: AuthzParams,
env: Env,
clientId?: string
) {
const storage = getAuthzCookieParamsSessionStorage(env, clientId)
const storage = getAuthzCookieParamsSessionStorage(request, env, clientId)
const session = await storage.getSession()

//Convert string array scope to space-delimited scope before setting cookie value
Expand All @@ -235,7 +252,7 @@ export async function getAuthzCookieParamsSession(
env: Env,
clientId?: string
) {
const storage = getAuthzCookieParamsSessionStorage(env, clientId)
const storage = getAuthzCookieParamsSessionStorage(request, env, clientId)
return storage.getSession(request.headers.get('Cookie'))
}

Expand All @@ -245,7 +262,7 @@ export async function destroyAuthzCookieParamsSession(
clientId?: string
) {
const gps = await getAuthzCookieParamsSession(request, env, clientId)
const storage = getAuthzCookieParamsSessionStorage(env, clientId)
const storage = getAuthzCookieParamsSessionStorage(request, env, clientId)
return storage.destroySession(gps)
}

Expand Down Expand Up @@ -318,7 +335,11 @@ export async function getValidatedSessionContext(
const redirectTo = `/authenticate/${authzParams?.clientId}`
if (error === InvalidTokenError)
if (authzParams.clientId)
throw await createAuthzParamsCookieAndAuthenticate(authzParams, env)
throw await createAuthzParamsCookieAndAuthenticate(
request,
authzParams,
env
)
else throw redirect(redirectTo)
else if (
error === ExpiredTokenError ||
Expand Down
6 changes: 5 additions & 1 deletion apps/passport/app/utils/authenticate.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const authenticateAddress = async (
await provisionProfile(accessToken, env, traceSpan, address)

return createUserSession(
request,
accessToken,
getAuthzRedirectURL(appData),
env,
Expand Down Expand Up @@ -189,7 +190,10 @@ export const checkOAuthError = async (request: Request, env: Env) => {
console.error({ error, uri, description })

const authzParams = await getAuthzCookieParamsSession(request, env)
const authenticatorStorage = await createAuthenticatorSessionStorage(env)
const authenticatorStorage = await createAuthenticatorSessionStorage(
request,
env
)
const session = await authenticatorStorage.getSession(
request.headers.get('Cookie')
)
Expand Down
6 changes: 5 additions & 1 deletion apps/passport/app/utils/authorize.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export async function createAuthzParamCookieAndCreate(
throw new BadRequestError({ message: 'Invalid create_type' })
}
throw redirect(redirectURL, {
headers: await createAuthorizationParamsCookieHeaders(authzParams, env),
headers: await createAuthorizationParamsCookieHeaders(
request,
authzParams,
env
),
})
}
14 changes: 14 additions & 0 deletions apps/passport/app/utils/cookie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Request as CfRequest } from '@cloudflare/workers-types'

type CfHostMetadata = {
clientId: string
}

export const getCookieDomain = (request: Request, env: Env): string => {
const host = request.headers.get('host') as string
if (host == env.DEFAULT_HOST) return env.COOKIE_DOMAIN
const cfRequest = request as unknown as CfRequest<CfHostMetadata>
const clientId = cfRequest.cf?.hostMetadata.clientId
if (clientId) return host
return env.COOKIE_DOMAIN
}
Loading

0 comments on commit c58de35

Please sign in to comment.