Skip to content

Commit

Permalink
mostly typescript tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Kabo committed Dec 11, 2023
1 parent 83c815f commit 0ac75f9
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 39 deletions.
19 changes: 6 additions & 13 deletions server/IdentityLocalState.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import type { Response } from 'express';

//could this be unified with IdentityDetails in globalstate.ts ?
interface IdentityLocalState {
userId?: string;
email?: string;
name?: string;
signInStatus?: string;
}
import type { IdentityDetails } from '@/shared/globals';

export const setIdentityLocalState = (
res: Response,
identityLocalState: IdentityLocalState,
): void => {
identityLocalState: IdentityDetails,
) => {
res.locals.identity = identityLocalState;
};
export const getIdentityLocalState = (
res: Response,
): IdentityLocalState | undefined => {
return res.locals.identity;
): IdentityDetails | undefined => {
return res.locals?.identity;
};
export const clearIdentityLocalState = (res: Response): void => {
export const clearIdentityLocalState = (res: Response) => {
delete res.locals.identity;
};
18 changes: 10 additions & 8 deletions server/middleware/OktaServerSideAuthMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { joinUrl } from '@guardian/libs';
import type { NextFunction, Request, Response } from 'express';
import fetch from 'node-fetch';
import {
clearIdentityLocalState,
getIdentityLocalState,
Expand Down Expand Up @@ -33,12 +32,12 @@ export const withOktaSeverSideValidation = async (
}

console.log('Validating token server side ...');
const signinRequired = () => requiresSignin(req.originalUrl);
const signinRequired = requiresSignin(req.originalUrl);

const locallyValidatedIdentityData = getIdentityLocalState(res);
const accessToken = req.signedCookies[OAuthAccessTokenCookieName];
if (!accessToken || !locallyValidatedIdentityData?.userId) {
if (signinRequired()) {
if (signinRequired) {
console.error(
'error: no access token or user in request for a sign-in required endpoint! this should have failed local validation',
);
Expand All @@ -65,18 +64,21 @@ export const withOktaSeverSideValidation = async (
console.log(`okta response status: ${oktaResponse.status}`);
if (oktaResponse.status == 200) {
//valid token
const oktaUserInfo = await oktaResponse.json<OktaUserInfo>();
const oktaUserInfo = (await oktaResponse.json()) as OktaUserInfo;
// Refresh the local state from the Okta response.
setIdentityLocalState(res, {
signInStatus: 'signedInRecently', // TODO can I hardcode this here or do I need to check something else ?
// This is always 'signedInRecently' because we've just checked
// the token is valid with Okta, and it's only valid for 30 minutes.
signInStatus: 'signedInRecently',
userId: oktaUserInfo.legacy_identity_id,
name: oktaUserInfo.name,
displayName: oktaUserInfo.name,
email: oktaUserInfo.email,
});
return next();
} else if ([403, 401].includes(oktaResponse.status)) {
} else if ([401, 403].includes(oktaResponse.status)) {
//invalid token
clearIdentityLocalState(res);
if (signinRequired()) {
if (signinRequired) {
return res.sendStatus(401);
}
return next();
Expand Down
32 changes: 15 additions & 17 deletions server/oauth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import crypto from 'crypto';
import { joinUrl } from '@guardian/libs';
import type { JwtClaims } from '@okta/jwt-verifier';
import OktaJwtVerifier from '@okta/jwt-verifier';
import type { CookieOptions, Request, Response } from 'express';
import ms from 'ms';
Expand All @@ -25,6 +26,12 @@ export const oauthCookieOptions: CookieOptions = {
httpOnly: true,
};

interface IdTokenClaims extends JwtClaims {
legacy_identity_id: string;
name: string;
email: string;
}

/**
* @function getOktaOrgUrl
*
Expand Down Expand Up @@ -348,25 +355,16 @@ export const setLocalStateFromIdTokenOrUserCookie = (
// signed in menu, but not show the user's name or email.
const hasIdTokenOrUserCookie = idToken || req.cookies['GU_U'];

let identityIdClaim: string | undefined;
let nameClaim: string | undefined;
let emailClaim: string | undefined;

if (typeof idToken?.claims.legacy_identity_id === 'string') {
identityIdClaim = idToken?.claims.legacy_identity_id;
}
if (typeof idToken?.claims.name === 'string') {
nameClaim = idToken?.claims.name;
}
if (typeof idToken?.claims.email === 'string') {
emailClaim = idToken?.claims.email;
}

const {
legacy_identity_id: userId,
name: displayName,
email,
} = idToken?.claims as IdTokenClaims;
setIdentityLocalState(res, {
signInStatus: hasIdTokenOrUserCookie ? 'signedInRecently' : undefined,
userId: identityIdClaim,
name: nameClaim,
email: emailClaim,
userId,
displayName,
email,
});
};

Expand Down
2 changes: 1 addition & 1 deletion shared/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface CommonGlobals {
dsn: string | null;
}

interface IdentityDetails {
export interface IdentityDetails {
userId?: string;
email?: string;
displayName?: string;
Expand Down

0 comments on commit 0ac75f9

Please sign in to comment.