@thermopylae/core.cookie-session
Version:
Cookie user session for HTTP interface.
170 lines (169 loc) • 9.16 kB
TypeScript
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 };