Add redis option to the express-session middleware

pull/47/head
Clement Michaud 2017-06-29 19:41:05 +02:00
parent 888bdd2bf9
commit 925b58fabc
11 changed files with 75 additions and 24 deletions

View File

@ -73,7 +73,9 @@ session:
secret: unsecure_secret
expiration: 3600000
domain: test.local
redis:
host: redis
port: 6379
# The directory where the DB files will be saved
store_directory: /var/lib/authelia/store

View File

@ -9,3 +9,7 @@ services:
networks:
- example-network
redis:
image: redis
networks:
- example-network

View File

@ -27,6 +27,7 @@
"@types/cors": "^2.8.1",
"bluebird": "^3.4.7",
"body-parser": "^1.15.2",
"connect-redis": "^3.3.0",
"dovehash": "0.0.5",
"ejs": "^2.5.5",
"express": "^4.14.0",
@ -45,6 +46,7 @@
"devDependencies": {
"@types/bluebird": "^3.5.4",
"@types/body-parser": "^1.16.3",
"@types/connect-redis": "0.0.6",
"@types/ejs": "^2.3.33",
"@types/express": "^4.0.35",
"@types/express-session": "0.0.32",

View File

@ -3,27 +3,29 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import Server from "./lib/Server";
import { GlobalDependencies } from "../types/Dependencies";
const YAML = require("yamljs");
const config_path = process.argv[2];
if (!config_path) {
const configurationFilepath = process.argv[2];
if (!configurationFilepath) {
console.log("No config file has been provided.");
console.log("Usage: authelia <config>");
process.exit(0);
}
console.log("Parse configuration file: %s", config_path);
console.log("Parse configuration file: %s", configurationFilepath);
const yaml_config = YAML.load(config_path);
const yaml_config = YAML.load(configurationFilepath);
const deps = {
const deps: GlobalDependencies = {
u2f: require("u2f"),
nodemailer: require("nodemailer"),
ldapjs: require("ldapjs"),
session: require("express-session"),
winston: require("winston"),
speakeasy: require("speakeasy"),
nedb: require("nedb")
nedb: require("nedb"),
ConnectRedis: require("connect-redis")
};
const server = new Server();

View File

@ -11,6 +11,7 @@ import RestApi from "./RestApi";
import { LdapClient } from "./LdapClient";
import BluebirdPromise = require("bluebird");
import ServerVariables = require("./ServerVariables");
import SessionConfigurationBuilder from "./SessionConfigurationBuilder";
import * as Express from "express";
import * as BodyParser from "body-parser";
@ -33,16 +34,8 @@ export default class Server {
app.set("trust proxy", 1); // trust first proxy
app.use(deps.session({
secret: config.session.secret,
resave: false,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: config.session.expiration,
domain: config.session.domain
},
}));
const sessionOptions = SessionConfigurationBuilder.build(config, deps);
app.use(deps.session(sessionOptions));
app.set("views", view_directory);
app.set("view engine", "pug");

View File

@ -0,0 +1,37 @@
import ExpressSession = require("express-session");
import { AppConfiguration } from "../../types/Configuration";
import { GlobalDependencies } from "../../types/Dependencies";
export default class SessionConfigurationBuilder {
static build(configuration: AppConfiguration, deps: GlobalDependencies): ExpressSession.SessionOptions {
const sessionOptions: ExpressSession.SessionOptions = {
secret: configuration.session.secret,
resave: false,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: configuration.session.expiration,
domain: configuration.session.domain
},
};
if (configuration.session.redis) {
let redisOptions;
if (configuration.session.redis.host && configuration.session.redis.port) {
redisOptions = {
host: configuration.session.redis.host,
port: configuration.session.redis.port
};
}
if (redisOptions) {
const RedisStore = deps.ConnectRedis(deps.session);
sessionOptions.store = new RedisStore(redisOptions);
}
}
return sessionOptions;
}
}

View File

@ -28,6 +28,10 @@ interface SessionCookieConfiguration {
secret: string;
expiration?: number;
domain?: string;
redis?: {
host: string;
port: number;
};
}
export interface GmailNotifierConfiguration {

View File

@ -5,6 +5,7 @@ import session = require("express-session");
import nedb = require("nedb");
import ldapjs = require("ldapjs");
import u2f = require("u2f");
import RedisSession = require("connect-redis");
export type Nodemailer = typeof nodemailer;
export type Speakeasy = typeof speakeasy;
@ -13,12 +14,14 @@ export type Session = typeof session;
export type Nedb = typeof nedb;
export type Ldapjs = typeof ldapjs;
export type U2f = typeof u2f;
export type ConnectRedis = typeof RedisSession;
export interface GlobalDependencies {
u2f: U2f;
nodemailer: Nodemailer;
ldapjs: Ldapjs;
session: Session;
ConnectRedis: ConnectRedis;
winston: Winston;
speakeasy: Speakeasy;
nedb: Nedb;

View File

@ -100,15 +100,16 @@ describe("test data persistence", function () {
sendMail: sinon.stub().yields()
};
const deps = {
const deps: GlobalDependencies = {
u2f: u2f,
nedb: nedb,
nodemailer: nodemailer,
session: session,
winston: winston,
ldapjs: ldap,
speakeasy: speakeasy
} as GlobalDependencies;
speakeasy: speakeasy,
ConnectRedis: sinon.spy()
};
const j1 = request.jar();
const j2 = request.jar();

View File

@ -7,6 +7,7 @@ import BluebirdPromise = require("bluebird");
import speakeasy = require("speakeasy");
import request = require("request");
import nedb = require("nedb");
import { GlobalDependencies } from "../../src/types/Dependencies";
import { TOTPSecret } from "../../src/types/TOTPSecret";
import U2FMock = require("./mocks/u2f");
import Endpoints = require("../../src/server/endpoints");
@ -96,14 +97,15 @@ describe("test the server", function () {
ldapClient.modify.yields();
ldapClient.search.yields(undefined, search_res);
const deps = {
const deps: GlobalDependencies = {
u2f: u2f,
nedb: nedb,
nodemailer: nodemailer,
ldapjs: ldap,
session: session,
winston: winston,
speakeasy: speakeasy
speakeasy: speakeasy,
ConnectRedis: sinon.spy()
};
server = new Server();

View File

@ -38,11 +38,12 @@ describe("test server configuration", function () {
createClient: sinon.spy(function () {
return {
on: sinon.spy(),
bind: sinon.spy()
bind: sinon.spy(),
};
})
},
session: sessionMock as any
session: sessionMock as any,
ConnectRedis: sinon.spy()
};
});