Options
All
  • Public
  • Public/Protected
  • All
Menu

@thermopylae/core.cookie-session

@thermopylae/core.cookie-session

Version Node Version Documentation License: MIT

Cookie user session for HTTP interface.

Install

npm install @thermopylae/core.cookie-session

Description

This package contains Http Middleware for cookie user session management. It uses @thermopylae/lib.user-session for session management and contains implementation for repositories required by the library.

Usage

import { LoggerManagerInstance, OutputFormat } from '@thermopylae/core.logger';
import { ConnectionType, initLogger as initRedisClientLogger, RedisClientInstance, RedisConnectionOptions } from '@thermopylae/core.redis';
import { initLogger as initUserSessionCommonsLogger } from '@thermopylae/core.user-session.commons';
import { GeoIpLiteRepository, GeoIpLocator } from '@thermopylae/lib.geoip';
import { UserSessionManager } from '@thermopylae/lib.user-session';
import { AVRO_SERIALIZER } from '@thermopylae/core.user-session.commons/dist/storage/serializers/cookie/avro';
import { ExpressRequestAdapter, ExpressResponseAdapter, AdaptedExpressRequest, LOCATION_SYM } from '@thermopylae/core.adapter.express';
import { HttpStatusCode } from '@thermopylae/core.declarations';
import { CookieUserSessionMiddleware, initLogger as initCoreCookieSessionLogger, UserSessionRedisStorage } from '@thermopylae/core.cookie-session';
import { Response } from 'express';

(async function main() {
    /* Configure Logging */
    LoggerManagerInstance.formatting.setDefaultFormattingOrder(OutputFormat.PRINTF);
    LoggerManagerInstance.console.createTransport({ level: 'info' });

    /* Init Loggers */
    initRedisClientLogger();
    initCoreCookieSessionLogger();
    initUserSessionCommonsLogger();

    /* Connect to Redis Server */
    const redisClientOptions: RedisConnectionOptions = {
        host: '127.0.0.1',
        port: 6379,
        password: '09}KNng90/mng89;',
        connect_timeout: 10_000,
        max_attempts: 10,
        retry_max_delay: 5_000,
        attachDebugListeners: new Set(['end', 'reconnecting'])
    };

    await RedisClientInstance.connect({
        [ConnectionType.REGULAR]: {
            ...redisClientOptions,
            detect_buffers: true // very important, REQUIRED
        },
        [ConnectionType.SUBSCRIBER]: redisClientOptions
    });

    /* Enable Key Space Notification Events (REQUIRED) */
    await RedisClientInstance.client.config('SET', 'notify-keyspace-events', 'Kgxe');

    /* Configure Geoip (OPTIONAL) */
    const geoip = new GeoIpLocator([new GeoIpLiteRepository(1)]);

    /* Configure Middleware */
    const middleware = new CookieUserSessionMiddleware({
        sessionManager: {
            idLength: 24,
            sessionTtl: 86_400, // 24h
            timeouts: {
                idle: 3_600, // 1h
                renewal: 43_200, // 12h
                oldSessionAvailabilityAfterRenewal: 5
            },
            renewSessionHooks: {
                onRenewMadeAlreadyFromCurrentProcess(sessionId: string) {
                    console.warn(
                        `Can't renew session '${UserSessionManager.hash(
                            sessionId
                        )}', because it was renewed already. Renew has been made from this NodeJS process.`
                    );
                },
                onRenewMadeAlreadyFromAnotherProcess(sessionId: string) {
                    console.warn(
                        `Can't renew session '${UserSessionManager.hash(
                            sessionId
                        )}', because it was renewed already. Renew has been made from another NodeJS process.`
                    );
                },
                onOldSessionDeleteFailure(sessionId: string, e: Error) {
                    console.error(`Failed to delete renewed session '${UserSessionManager.hash(sessionId)}'.`, e);
                }
            },
            storage: new UserSessionRedisStorage({
                keyPrefix: {
                    sessions: 'sids',
                    sessionId: 'sid'
                },
                concurrentSessions: 2,
                serializer: AVRO_SERIALIZER
            })
        },
        session: {
            cookie: {
                name: 'sid',
                path: '/api',
                sameSite: 'strict',
                persistent: true
            },
            header: 'x-session-id',
            csrf: {
                name: 'x-requested-with',
                value: 'XmlHttpRequest'
            },
            'cache-control': true
        }
    });

    /* Define Route Handler */
    async function createSession(req: AdaptedExpressRequest, res: Response): Promise<void> {
        const request = new ExpressRequestAdapter(req);
        const response = new ExpressResponseAdapter(res);

        req[LOCATION_SYM] = await geoip.locate(request.ip);

        try {
            await middleware.create(request, response, 'uid1');
            response.status(HttpStatusCode.Created).send();
        } catch (e) {
            response.status(HttpStatusCode.BadRequest).send({ message: e.message });
        }
    }
})();

API Reference

API documentation is available here.

It can also be generated by issuing the following commands:

git clone git@github.com:marinrusu1997/thermopylae.git
cd thermopylae
yarn install
yarn workspace @thermopylae/core.cookie-session run doc

Author

👤 Rusu Marin

📝 License

Copyright © 2021 Rusu Marin.
This project is MIT licensed.