mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
563e2da323
This URL is used when user access the authentication domain without providing the 'redirect' query parameter. In that case, Authelia does not know where to redirect the user. If the parameter is defined, Authelia can redirect the user to a default page when no redirect parameter is provided. When user is already authenticated and tries to access the authentication domain, the "already logged in" page is rendered and it now tells the user he is to be redirected in few seconds and uses this URL to redirect. This parameter is optional. If it is not provided, there is only a notification message at the end of the authentication process, as before, and the user is not redirected when visiting the authentication domain while already authenticated.
136 lines
5.3 KiB
TypeScript
136 lines
5.3 KiB
TypeScript
|
|
import objectPath = require("object-path");
|
|
import randomstring = require("randomstring");
|
|
import BluebirdPromise = require("bluebird");
|
|
import util = require("util");
|
|
import Exceptions = require("./Exceptions");
|
|
import fs = require("fs");
|
|
import ejs = require("ejs");
|
|
import { IUserDataStore } from "./storage/IUserDataStore";
|
|
import { Winston } from "../../types/Dependencies";
|
|
import express = require("express");
|
|
import ErrorReplies = require("./ErrorReplies");
|
|
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
|
import { AuthenticationSession } from "../../types/AuthenticationSession";
|
|
import { ServerVariables } from "./ServerVariables";
|
|
|
|
import Identity = require("../../types/Identity");
|
|
import { IdentityValidationDocument } from "./storage/IdentityValidationDocument";
|
|
|
|
const filePath = __dirname + "/../resources/email-template.ejs";
|
|
const email_template = fs.readFileSync(filePath, "utf8");
|
|
|
|
// IdentityValidator allows user to go through a identity validation process in two steps:
|
|
// - Request an operation to be performed (password reset, registration).
|
|
// - Confirm operation with email.
|
|
|
|
export interface IdentityValidable {
|
|
challenge(): string;
|
|
preValidationInit(req: express.Request): BluebirdPromise<Identity.Identity>;
|
|
postValidationInit(req: express.Request): BluebirdPromise<void>;
|
|
|
|
// Serves a page after identity check request
|
|
preValidationResponse(req: express.Request, res: express.Response): void;
|
|
// Serves the page if identity validated
|
|
postValidationResponse(req: express.Request, res: express.Response): void;
|
|
mailSubject(): string;
|
|
}
|
|
|
|
function createAndSaveToken(userid: string, challenge: string, userDataStore: IUserDataStore)
|
|
: BluebirdPromise<string> {
|
|
const five_minutes = 4 * 60 * 1000;
|
|
const token = randomstring.generate({ length: 64 });
|
|
const that = this;
|
|
|
|
return userDataStore.produceIdentityValidationToken(userid, token, challenge, five_minutes)
|
|
.then(function () {
|
|
return BluebirdPromise.resolve(token);
|
|
});
|
|
}
|
|
|
|
function consumeToken(token: string, challenge: string, userDataStore: IUserDataStore)
|
|
: BluebirdPromise<IdentityValidationDocument> {
|
|
return userDataStore.consumeIdentityValidationToken(token, challenge);
|
|
}
|
|
|
|
export function register(app: express.Application, pre_validation_endpoint: string,
|
|
post_validation_endpoint: string, handler: IdentityValidable, vars: ServerVariables) {
|
|
app.get(pre_validation_endpoint, get_start_validation(handler, post_validation_endpoint, vars));
|
|
app.get(post_validation_endpoint, get_finish_validation(handler, vars));
|
|
}
|
|
|
|
function checkIdentityToken(req: express.Request, identityToken: string): BluebirdPromise<void> {
|
|
if (!identityToken)
|
|
return BluebirdPromise.reject(new Exceptions.AccessDeniedError("No identity token provided"));
|
|
return BluebirdPromise.resolve();
|
|
}
|
|
|
|
export function get_finish_validation(handler: IdentityValidable,
|
|
vars: ServerVariables)
|
|
: express.RequestHandler {
|
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
|
let authSession: AuthenticationSession;
|
|
const identityToken = objectPath.get<express.Request, string>(req, "query.identity_token");
|
|
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
|
|
|
return checkIdentityToken(req, identityToken)
|
|
.then(function () {
|
|
return handler.postValidationInit(req);
|
|
})
|
|
.then(function () {
|
|
return AuthenticationSessionHandler.get(req, vars.logger);
|
|
})
|
|
.then(function (_authSession) {
|
|
authSession = _authSession;
|
|
})
|
|
.then(function () {
|
|
return consumeToken(identityToken, handler.challenge(), vars.userDataStore);
|
|
})
|
|
.then(function (doc: IdentityValidationDocument) {
|
|
authSession.identity_check = {
|
|
challenge: handler.challenge(),
|
|
userid: doc.userId
|
|
};
|
|
handler.postValidationResponse(req, res);
|
|
return BluebirdPromise.resolve();
|
|
})
|
|
.catch(ErrorReplies.replyWithError401(req, res, vars.logger));
|
|
};
|
|
}
|
|
|
|
|
|
export function get_start_validation(handler: IdentityValidable,
|
|
postValidationEndpoint: string,
|
|
vars: ServerVariables)
|
|
: express.RequestHandler {
|
|
return function (req: express.Request, res: express.Response): BluebirdPromise<void> {
|
|
let identity: Identity.Identity;
|
|
|
|
return handler.preValidationInit(req)
|
|
.then(function (id: Identity.Identity) {
|
|
identity = id;
|
|
const email = identity.email;
|
|
const userid = identity.userid;
|
|
vars.logger.info(req, "Start identity validation of user \"%s\"", userid);
|
|
|
|
if (!(email && userid))
|
|
return BluebirdPromise.reject(new Exceptions.IdentityError(
|
|
"Missing user id or email address"));
|
|
|
|
return createAndSaveToken(userid, handler.challenge(), vars.userDataStore);
|
|
})
|
|
.then(function (token: string) {
|
|
const host = req.get("Host");
|
|
const link_url = util.format("https://%s%s?identity_token=%s", host,
|
|
postValidationEndpoint, token);
|
|
vars.logger.info(req, "Notification sent to user \"%s\"", identity.userid);
|
|
return vars.notifier.notify(identity.email, handler.mailSubject(), link_url);
|
|
})
|
|
.then(function () {
|
|
handler.preValidationResponse(req, res);
|
|
return BluebirdPromise.resolve();
|
|
})
|
|
.catch(ErrorReplies.replyWithError401(req, res, vars.logger));
|
|
};
|
|
}
|