@guardian/pan-domain-node
Version:
NodeJs implementation of Guardian pan-domain auth verification
84 lines (75 loc) • 2.85 kB
text/typescript
export { PanDomainAuthentication } from './panda';
// We continue to consider the request authenticated for
// a period of time after the cookie expiry. This is to allow
// API requests which cannot directly send the user for re-auth to
// indicate to the user that they must take some action to refresh their
// credentials (usually, refreshing the page).
// Panda cookie: issued expires
// | |
// |--1 hour--|
// Grace period: [------------- 24 hours ------]
// `success`: --false-][-true-----------------------------------][-false-------->
// `shouldRefreshCredentials` [-false---][-true------------------------]
export const gracePeriodInMillis = 24 * 60 * 60 * 1000;
// These are used to enforce the structure of the
// `AuthenticationResult` union types,
// but are not exported because they are too general.
interface Result {
success: boolean
}
interface Success extends Result {
// `success` is true when both these are true:
// 1. we've verified that the cookie is signed by the correct private key
// and decoded a `User` from it
// 2. we've validated the `User` using `ValidateUserFn`
success: true,
shouldRefreshCredentials: boolean,
user: User
}
interface Failure extends Result {
success: false,
reason: string
}
// These are members of the `AuthenticationResult` union,
// so they are exported for use by library consumers.
export interface FreshSuccess extends Success {
// Cookie has not expired yet, so no need to refresh credentials.
shouldRefreshCredentials: false
}
export interface StaleSuccess extends Success {
// Cookie has expired: we're in the grace period.
// Endpoints that can refresh credentials should do so,
// and those that cannot should tell the user to do so.
shouldRefreshCredentials: true,
mustRefreshByEpochTimeMillis: number
}
export interface UserValidationFailure extends Failure {
reason: 'invalid-user',
user: User
}
export interface CookieFailure extends Failure {
reason: 'no-cookie' | 'invalid-cookie' | 'expired-cookie'
}
export interface UnknownFailure extends Failure {
reason: 'unknown'
}
export type AuthenticationResult = FreshSuccess
| StaleSuccess
| CookieFailure
| UserValidationFailure
| UnknownFailure
export interface User {
firstName: string,
lastName: string,
email: string,
avatarUrl?: string,
authenticatingSystem: string,
authenticatedIn: string[],
expires: number,
multifactor: boolean
}
export type ValidateUserFn = (user: User) => boolean;
export function guardianValidation(user: User): boolean {
const isGuardianUser = user.email.indexOf('guardian.co.uk') !== -1;
return isGuardianUser && user.multifactor;
}