Skip to content

Commit

Permalink
Allow undefined redirect uri (#97)
Browse files Browse the repository at this point in the history
* Make redirect URI available evia either env variables or via middleware config

* Add version bump
  • Loading branch information
PaulAsjes authored Oct 2, 2024
1 parent cca4e06 commit 7d71910
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 27 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workos-inc/authkit-nextjs",
"version": "0.11.1",
"version": "0.11.2",
"description": "Authentication and session helpers for using WorkOS & AuthKit with Next.js",
"sideEffects": false,
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions src/authkit-callback-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cookies } from 'next/headers';
import { workos } from './workos.js';
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_NAME } from './env-variables.js';
import { encryptSession } from './session.js';
import { cookieOptions } from './cookie.js';
import { getCookieOptions } from './cookie.js';
import { HandleAuthOptions } from './interfaces.js';

export function handleAuth(options: HandleAuthOptions = {}) {
Expand Down Expand Up @@ -52,7 +52,7 @@ export function handleAuth(options: HandleAuthOptions = {}) {
const session = await encryptSession({ accessToken, refreshToken, user, impersonator });
const cookieName = WORKOS_COOKIE_NAME || 'wos-session';

cookies().set(cookieName, session, cookieOptions);
cookies().set(cookieName, session, getCookieOptions(request.url));

return response;
} catch (error) {
Expand Down
30 changes: 15 additions & 15 deletions src/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { WORKOS_REDIRECT_URI, WORKOS_COOKIE_MAX_AGE, WORKOS_COOKIE_DOMAIN } from './env-variables.js';
import { CookieOptions } from './interfaces.js';

const redirectUrl = new URL(WORKOS_REDIRECT_URI);
const isSecureProtocol = redirectUrl.protocol === 'https:';
export function getCookieOptions(redirectUri?: string | null): CookieOptions {
const url = new URL(redirectUri || WORKOS_REDIRECT_URI);

const cookieOptions = {
path: '/',
httpOnly: true,
secure: isSecureProtocol,
sameSite: 'lax' as const,
// Defaults to 400 days, the maximum allowed by Chrome
// It's fine to have a long cookie expiry date as the access/refresh tokens
// act as the actual time-limited aspects of the session.
maxAge: WORKOS_COOKIE_MAX_AGE ? parseInt(WORKOS_COOKIE_MAX_AGE, 10) : 60 * 60 * 24 * 400,
domain: WORKOS_COOKIE_DOMAIN,
};

export { cookieOptions };
return {
path: '/',
httpOnly: true,
secure: url.protocol === 'https:',
sameSite: 'lax' as const,
// Defaults to 400 days, the maximum allowed by Chrome
// It's fine to have a long cookie expiry date as the access/refresh tokens
// act as the actual time-limited aspects of the session.
maxAge: WORKOS_COOKIE_MAX_AGE ? parseInt(WORKOS_COOKIE_MAX_AGE, 10) : 60 * 60 * 24 * 400,
domain: WORKOS_COOKIE_DOMAIN,
};
}
9 changes: 9 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,12 @@ export interface AuthkitMiddlewareOptions {
middlewareAuth?: AuthkitMiddlewareAuth;
redirectUri?: string;
}

export interface CookieOptions {
path: '/';
httpOnly: true;
secure: boolean;
sameSite: 'lax';
maxAge: number;
domain: string | undefined;
}
24 changes: 16 additions & 8 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { cookies, headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify, createRemoteJWKSet, decodeJwt } from 'jose';
import { sealData, unsealData } from 'iron-session';
import { cookieOptions } from './cookie.js';
import { getCookieOptions } from './cookie.js';
import { workos } from './workos.js';
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_PASSWORD, WORKOS_COOKIE_NAME, WORKOS_REDIRECT_URI } from './env-variables.js';
import { getAuthorizationUrl } from './get-authorization-url.js';
Expand All @@ -29,6 +29,10 @@ async function updateSession(
middlewareAuth: AuthkitMiddlewareAuth,
redirectUri: string,
) {
if (!redirectUri && !WORKOS_REDIRECT_URI) {
throw new Error('You must provide a redirect URI in the AuthKit middleware or in the environment variables.');
}

const session = await getSessionFromCookie();
const newRequestHeaders = new Headers(request.headers);

Expand All @@ -40,15 +44,18 @@ async function updateSession(
// Record that the request was routed through the middleware so we can check later for DX purposes
newRequestHeaders.set(middlewareHeaderName, 'true');

let url;

// If the redirect URI is set, store it in the headers so we can use it later
if (redirectUri) {
newRequestHeaders.set(redirectUriHeaderName, redirectUri);
url = new URL(redirectUri);
} else {
url = new URL(WORKOS_REDIRECT_URI);
}

newRequestHeaders.delete(sessionHeaderName);

const url = new URL(WORKOS_REDIRECT_URI);

if (
middlewareAuth.enabled &&
url.pathname === request.nextUrl.pathname &&
Expand Down Expand Up @@ -124,7 +131,7 @@ async function updateSession(
request: { headers: newRequestHeaders },
});
// update the cookie
response.cookies.set(cookieName, encryptedSession, cookieOptions);
response.cookies.set(cookieName, encryptedSession, getCookieOptions(redirectUri));
return response;
} catch (e) {
if (debug) console.log('Failed to refresh. Deleting cookie and redirecting.', e);
Expand Down Expand Up @@ -173,7 +180,9 @@ async function refreshSession({
});

const cookieName = WORKOS_COOKIE_NAME || 'wos-session';
cookies().set(cookieName, encryptedSession, cookieOptions);
const url = headers().get('x-url');

cookies().set(cookieName, encryptedSession, getCookieOptions(url));

const { sid: sessionId, org_id: organizationId, role, permissions } = decodeJwt<AccessToken>(accessToken);

Expand All @@ -192,8 +201,7 @@ function getMiddlewareAuthPathRegex(pathGlob: string) {
let regex: string;

try {
// Redirect URI is only used to construct the URL
const url = new URL(pathGlob, WORKOS_REDIRECT_URI);
const url = new URL(pathGlob, 'https://example.com');
const path = `${url.pathname!}${url.hash || ''}`;

const tokens = parse(path);
Expand Down Expand Up @@ -297,7 +305,7 @@ async function getSessionFromHeader(): Promise<Session | undefined> {

if (!hasMiddleware) {
throw new Error(
"You are calling 'withAuth' on a path that isn’t covered by the AuthKit middleware. Make sure it is running on all paths you are calling `${caller}` from by updating your middleware config in `middleware.(js|ts)`.",
"You are calling 'withAuth' on a path that isn’t covered by the AuthKit middleware. Make sure it is running on all paths you are calling withAuth from by updating your middleware config in `middleware.(js|ts)`.",
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/workos.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { WorkOS } from '@workos-inc/node';
import { WORKOS_API_HOSTNAME, WORKOS_API_KEY, WORKOS_API_HTTPS, WORKOS_API_PORT } from './env-variables.js';

export const VERSION = '0.11.1';
export const VERSION = '0.11.2';

const options = {
apiHostname: WORKOS_API_HOSTNAME,
Expand Down

0 comments on commit 7d71910

Please sign in to comment.