UNPKG

@cipherstash/nextjs

Version:

Nextjs package for use with @cipherstash/protect

116 lines (95 loc) 3.12 kB
import { NextResponse } from 'next/server' import { logger } from '../../../utils/logger' import { CS_COOKIE_NAME, type CtsToken, type GetCtsTokenResponse, } from '../index' /** * Extracts the workspace ID from a CRN string. * CRN format: crn:region.aws:ID * * @param crn The CRN string to extract from * @returns The workspace ID portion of the CRN */ function extractWorkspaceIdFromCrn(crn: string): string { const match = crn.match(/crn:[^:]+:([^:]+)$/) if (!match) { throw new Error('Invalid CRN format') } return match[1] } export function loadWorkSpaceId(suppliedCrn?: string): string { if (suppliedCrn) { return extractWorkspaceIdFromCrn(suppliedCrn) } if (!process.env.CS_WORKSPACE_CRN) { throw new Error( 'You have not defined a workspace CRN in your config file, or the CS_WORKSPACE_CRN environment variable.', ) } return extractWorkspaceIdFromCrn(process.env.CS_WORKSPACE_CRN) } // Can be used independently of the Next.js middleware export const fetchCtsToken = async (oidcToken: string): GetCtsTokenResponse => { const workspaceId = loadWorkSpaceId() if (!workspaceId) { logger.error( 'The "CS_WORKSPACE_ID" environment variable is not set, and is required by protectClerkMiddleware. No CipherStash session will be set.', ) return { success: false, error: 'The "CS_WORKSPACE_ID" environment variable is not set.', } } const ctsEndoint = process.env.CS_CTS_ENDPOINT || 'https://ap-southeast-2.aws.auth.viturhosted.net' const ctsResponse = await fetch(`${ctsEndoint}/api/authorize`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ workspaceId, oidcToken, }), }) if (!ctsResponse.ok) { logger.debug(`Failed to fetch CTS token: ${ctsResponse.statusText}`) logger.error( 'There was an issue communicating with the CipherStash CTS API, the CipherStash session was not set. If the issue persists, please contact support.', ) return { success: false, error: `Failed to fetch CTS token: ${ctsResponse.statusText}`, } } const cts_token = (await ctsResponse.json()) as CtsToken return { success: true, ctsToken: cts_token, } } // Used in the Next.js middleware export const setCtsToken = async (oidcToken: string, res?: NextResponse) => { const ctsResponse = await fetchCtsToken(oidcToken) const cts_token = ctsResponse.ctsToken if (!cts_token) { logger.debug(`Failed to fetch CTS token: ${ctsResponse.error}`) logger.error( 'There was an issue fetching the CipherStash session, the CipherStash session was not set. If the issue persists, please contact support.', ) return res ?? NextResponse.next() } // Setting cookies on the request and response using the `ResponseCookies` API const response = res ?? NextResponse.next() response.cookies.set({ name: CS_COOKIE_NAME, value: JSON.stringify(cts_token), expires: new Date(cts_token.expiry * 1000), sameSite: 'lax', path: '/', }) return response }