UNPKG

@thermopylae/core.cookie-session

Version:
170 lines (169 loc) 9.16 kB
import type { HttpResponseHeader, HttpRequestHeader, HttpHeaderValue, HTTPRequestLocation, HttpRequest, HttpResponse, Seconds } from '@thermopylae/core.declarations'; import type { Subject } from '@thermopylae/lib.user-session.commons'; import type { UserSessionManagerOptions, UserSessionMetaData } from '@thermopylae/lib.user-session'; import type { UserSessionDevice, AuthorizationTokenExtractor } from '@thermopylae/core.user-session.commons'; import { UserSessionManager } from '@thermopylae/lib.user-session'; interface UserSessionCookiesOptions { /** * Lowercase name of the cookie where session id will be stored. <br/> * Notice that this name should be unpredictable one (e.g. not 'sid', 'id' etc). <br/> * Also, cookie name should not begin with *__Host-* or *__Secure-* prefixes, as they will be added automatically. */ name: string; /** * [Domain](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent) attribute. <br/> * **Recommended** value is to be left *undefined*. */ readonly domain?: string; /** * [Path](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent) attribute. <br/> */ readonly path?: string; /** * [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) attribute. <br/> * Set value to *false* if you don't want to set this attribute. * **Recommended** value is *strict*. */ readonly sameSite: 'lax' | 'strict' | 'none' | boolean; /** * Whether session id cookie need to be [persisted in browser](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_the_lifetime_of_a_cookie). <br/> * When set to: <br/> * - *true* - sets *Max-Age* attribute which makes the browser to persist that cookie for specified amount of time <br/> * - *false* - doesn't set *Max-Age*, nor *Expires* attribute which makes the browser to not persist that cookie */ readonly persistent: boolean; } interface UserSessionOptions { /** * Session id cookie options. */ readonly cookie: UserSessionCookiesOptions; /** * Lowercase name of header in the HTTP response which will contain session id. <br/> * This option is related to non-browser devices, which will receive session id via header, instead of cookies. <br/> * Decision whether is a browser on non-browser device is taked based on `device` property from the HTTP request object. * * **Notice** that on further subsequent requests, session id will need to be included in the *Authorization* header. * * @example <br/> *x-session-id* */ readonly header: HttpResponseHeader | string; /** * CSRF header options applied only when requests are made from browser devices. <br/> * After session creation, all subsequent requests will need to include {@link UserSessionOptions.csrf.name} header with value * {@link UserSessionOptions.csrf.value}. <br/> * This is needed for [CSRF mitigation](https://markitzeroday.com/x-requested-with/cors/2017/06/29/csrf-mitigation-for-ajax-requests.html). */ readonly csrf: { /** * Lowercase name of the CSRF header. * * @example <br/> *x-requested-with* */ readonly name: HttpRequestHeader | string; /** * Value of the the CSRF header. <br/> * This value will be used for comparison with the one from HTTP request. * In case they not match, an error is thrown and request will be aborted. * * @example <br/> *XmlHttpRequest* */ readonly value: HttpHeaderValue | string; }; /** * Whether to set *Cache-Control: no-cache="Set-Cookie, Set-Cookie2"* response header for the * requests that deliver access and refresh tokens to client * (i.e. {@link CookieUserSessionMiddleware.create} and {@link CookieUserSessionMiddleware.renew} operations). */ readonly 'cache-control': boolean; } interface CookieUserSessionMiddlewareOptions { /** * Options for {@link UserSessionManager}. */ readonly sessionManager: UserSessionManagerOptions<UserSessionDevice, HTTPRequestLocation>; /** * User session options. */ readonly session: UserSessionOptions; /** * Function which extracts session id from *Authorization* header. <br/> * If the token could not be extracted, the extractor should throw an exception. <br/> * **Defaults** to extractor which expects *Authorization* header with value in the format: `Bearer ${token}`. */ readonly sessionIdExtractor?: AuthorizationTokenExtractor; } /** * Cookie User Session middleware which uses *lib.user-session* for session management and HTTP protocol as transport of session id. <br/> * Notice that all function members that operate on HTTP response, will set/unset only it's headers, * while other parts, like status code, payload etc are left untouched. * Also it doesn't send response back to clients, this is the caller job to call `send` on response. <br/> * Caller should also handle all of the exceptions (own and of other libraries) thrown by the methods of this class. */ declare class CookieUserSessionMiddleware { private readonly options; private readonly sessionManager; private readonly cookieSerializeOptions; private readonly invalidateSessionCookieHeaderValue; constructor(options: CookieUserSessionMiddlewareOptions); /** * Get {@link UserSessionManager} instance. */ get userSessionManager(): UserSessionManager<UserSessionDevice, HTTPRequestLocation>; /** * Create user session. <br/> * After session creation, sets session id in the response * cookies and/or headers, depending on the device from where request was sent. * * @param req Incoming HTTP request. * @param res Outgoing HTTP response. * @param subject Subject. * @param sessionTtl Explicit session ttl, has priority over default one. */ create(req: HttpRequest, res: HttpResponse, subject: Subject, sessionTtl?: Seconds): Promise<void>; /** * Verify user session. <br/> * Session id will be extracted from request according to {@link UserSessionOptions}. <br/> * Depending on the {@link UserSessionManager} config, user session might be renewed, and the new user session id * will be set in the headers of response object. Therefore, it's very important that response is sent to client * with renewed session id at least. * * @param req Incoming HTTP request. * @param res Outgoing HTTP response. * @param subject Subject. * @param unsetSessionCookie Whether to unset session cookie in the `res` in case it is not found/expired. <br/> * This is valid only for requests made from browser devices. <br/> * More information about cookie invalidation can be found [here](https://stackoverflow.com/questions/5285940/correct-way-to-delete-cookies-server-side). */ verify(req: HttpRequest, res: HttpResponse, subject: Subject, unsetSessionCookie?: boolean): Promise<UserSessionMetaData<UserSessionDevice, HTTPRequestLocation>>; /** * Renew user session, by deleting the old one and creating a new one. * * @param req Incoming HTTP request. * @param res Outgoing HTTP response. * @param subject Subject. * @param metaData User session metadata. */ renew(req: HttpRequest, res: HttpResponse, subject: Subject, metaData: UserSessionMetaData<UserSessionDevice, HTTPRequestLocation>): Promise<void>; /** * Delete user session. <br/> * Refresh Token will be extracted from request according to {@link UserSessionOptions}. * * @param req Incoming HTTP request. * @param res Outgoing HTTP response. * @param subject Subject which has the session that needs to be deleted. * @param sessionId Id of the session to be deleted. <br/> * This parameter is optional, and should be mainly by admins to forcefully end user session. <br/> * **CAUTION!** When this param is set, you will most probably want to set `unsetSessionCookie` * to *false* in order to not invalidate session id cookie of the admin. * @param unsetSessionCookie Whether to unset session cookie in the `res` after session deletion. <br/> * This is valid only for requests made from browser devices. <br/> * More information about cookie invalidation can be found [here](https://stackoverflow.com/questions/5285940/correct-way-to-delete-cookies-server-side). */ delete(req: HttpRequest, res: HttpResponse, subject: string, sessionId?: string | null | undefined, unsetSessionCookie?: boolean): Promise<void>; private extractSessionId; private setSessionIdInResponseHeader; private static fillWithDefaults; } export { CookieUserSessionMiddleware }; export type { UserSessionCookiesOptions, UserSessionOptions, CookieUserSessionMiddlewareOptions };