Edit nginx configuration and add redirection during login and logout
parent
e13315eb92
commit
7aacae842d
|
@ -2,6 +2,10 @@ FROM node
|
||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
COPY app /usr/src
|
COPY package.json /usr/src/package.json
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
CMD ["node", "app.js"]
|
COPY src /usr/src
|
||||||
|
|
||||||
|
|
||||||
|
CMD ["node", "index.js"]
|
||||||
|
|
|
@ -5,10 +5,11 @@ services:
|
||||||
build: .
|
build: .
|
||||||
environment:
|
environment:
|
||||||
- LDAP_URL=ldap://ldap
|
- LDAP_URL=ldap://ldap
|
||||||
- SECRET=NBD2ZV64R9UV1O7K
|
- LDAP_USERS_DN=dc=example,dc=com
|
||||||
- USERS_DN=dc=example,dc=com
|
- TOTP_SECRET=NBD2ZV64R7UV1O7K
|
||||||
|
- JWT_SECRET=unsecure_secret
|
||||||
|
- JWT_EXPIRATION_TIME=1h
|
||||||
- PORT=80
|
- PORT=80
|
||||||
- EXPIRATION_TIME=2m
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- ldap
|
- ldap
|
||||||
expose:
|
expose:
|
||||||
|
@ -26,14 +27,10 @@ services:
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
volumes:
|
volumes:
|
||||||
- ./proxy/nginx.conf:/etc/nginx/nginx.conf
|
- ./nginx_conf/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
- ./nginx_conf/index.html:/usr/share/nginx/html/index.html
|
||||||
|
- ./nginx_conf/secret.html:/usr/share/nginx/html/secret.html
|
||||||
depends_on:
|
depends_on:
|
||||||
- auth-server
|
- auth-server
|
||||||
ports:
|
ports:
|
||||||
- "8085:80"
|
- "8085:80"
|
||||||
|
|
||||||
secret:
|
|
||||||
image: nginx:alpine
|
|
||||||
volumes:
|
|
||||||
- ./secret/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
- ./secret/index.html:/usr/share/nginx/html/index.html
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Home page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
You need to <a href="/auth/login?redirect=http://localhost:8085/">log in</a> to access the <a href="/secret.html">secret</a>!<br/><br/>
|
||||||
|
You can also log off by visiting the following <a href="/auth/logout?redirect=http://localhost:8085/">link</a>.
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,73 @@
|
||||||
|
# nginx-sso - example nginx config
|
||||||
|
#
|
||||||
|
# (c) 2015 by Johannes Gilger <heipei@hackvalue.de>
|
||||||
|
#
|
||||||
|
# This is an example config for using nginx with the nginx-sso cookie system.
|
||||||
|
# For simplicity, this config sets up two fictional vhosts that you can use to
|
||||||
|
# test against both components of the nginx-sso system: ssoauth & ssologin.
|
||||||
|
# In a real deployment, these vhosts would be separate hosts.
|
||||||
|
|
||||||
|
#user nobody;
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
#error_log logs/error.log;
|
||||||
|
#error_log logs/error.log notice;
|
||||||
|
#error_log logs/error.log info;
|
||||||
|
|
||||||
|
#pid logs/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
error_page 401 = @error401;
|
||||||
|
location @error401 {
|
||||||
|
return 302 http://localhost:8085/auth/login?redirect=$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /check-auth {
|
||||||
|
internal;
|
||||||
|
# proxy_pass_request_body off;
|
||||||
|
proxy_set_header X-Original-URI $request_uri;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|
||||||
|
proxy_pass http://auth-server/_auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /auth/ {
|
||||||
|
proxy_set_header X-Original-URI $request_uri;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|
||||||
|
proxy_pass http://auth-server/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /secret.html {
|
||||||
|
auth_request /check-auth;
|
||||||
|
|
||||||
|
auth_request_set $user $upstream_http_x_remote_user;
|
||||||
|
proxy_set_header X-Forwarded-User $user;
|
||||||
|
auth_request_set $groups $upstream_http_remote_groups;
|
||||||
|
proxy_set_header Remote-Groups $groups;
|
||||||
|
auth_request_set $expiry $upstream_http_remote_expiry;
|
||||||
|
proxy_set_header Remote-Expiry $expiry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Block everything but POST on _auth
|
||||||
|
location = /_auth {
|
||||||
|
if ($request_method != POST) {
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
proxy_pass http://auth-server/_auth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Secret</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
This is a very important secret!
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
Coucou
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,76 +0,0 @@
|
||||||
# nginx-sso - example nginx config
|
|
||||||
#
|
|
||||||
# (c) 2015 by Johannes Gilger <heipei@hackvalue.de>
|
|
||||||
#
|
|
||||||
# This is an example config for using nginx with the nginx-sso cookie system.
|
|
||||||
# For simplicity, this config sets up two fictional vhosts that you can use to
|
|
||||||
# test against both components of the nginx-sso system: ssoauth & ssologin.
|
|
||||||
# In a real deployment, these vhosts would be separate hosts.
|
|
||||||
|
|
||||||
#user nobody;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
#error_log logs/error.log;
|
|
||||||
#error_log logs/error.log notice;
|
|
||||||
#error_log logs/error.log info;
|
|
||||||
|
|
||||||
#pid logs/nginx.pid;
|
|
||||||
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
http {
|
|
||||||
# This is the vserver for the service that you want to protect.
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
error_page 401 = @error401;
|
|
||||||
location @error401 {
|
|
||||||
return 302 http://127.0.0.1:8085/login;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /_auth {
|
|
||||||
internal;
|
|
||||||
|
|
||||||
proxy_pass http://auth-server/_auth;
|
|
||||||
|
|
||||||
proxy_pass_request_body off;
|
|
||||||
|
|
||||||
proxy_set_header Content-Length "";
|
|
||||||
proxy_set_header X-Original-URI $request_uri;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /secret/ {
|
|
||||||
auth_request /_auth;
|
|
||||||
|
|
||||||
auth_request_set $user $upstream_http_x_remote_user;
|
|
||||||
proxy_set_header X-Forwarded-User $user;
|
|
||||||
# auth_request_set $groups $upstream_http_remote_groups;
|
|
||||||
# proxy_set_header Remote-Groups $groups;
|
|
||||||
# auth_request_set $expiry $upstream_http_remote_expiry;
|
|
||||||
# proxy_set_header Remote-Expiry $expiry;
|
|
||||||
|
|
||||||
rewrite ^/secret/(.*)$ /$1 break;
|
|
||||||
proxy_pass http://secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /login {
|
|
||||||
proxy_set_header X-Original-URI $request_uri;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_pass http://auth-server/login;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /logout {
|
|
||||||
proxy_set_header X-Original-URI $request_uri;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_pass http://auth-server/logout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
Coucou
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,32 +0,0 @@
|
||||||
# nginx-sso - example nginx config
|
|
||||||
#
|
|
||||||
# (c) 2015 by Johannes Gilger <heipei@hackvalue.de>
|
|
||||||
#
|
|
||||||
# This is an example config for using nginx with the nginx-sso cookie system.
|
|
||||||
# For simplicity, this config sets up two fictional vhosts that you can use to
|
|
||||||
# test against both components of the nginx-sso system: ssoauth & ssologin.
|
|
||||||
# In a real deployment, these vhosts would be separate hosts.
|
|
||||||
|
|
||||||
#user nobody;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
#error_log logs/error.log;
|
|
||||||
#error_log logs/error.log notice;
|
|
||||||
#error_log logs/error.log info;
|
|
||||||
|
|
||||||
#pid logs/nginx.pid;
|
|
||||||
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
http {
|
|
||||||
# This is the vserver for the service that you want to protect.
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ var server = require('./lib/server');
|
||||||
var ldap = require('ldapjs');
|
var ldap = require('ldapjs');
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
port: process.env.PORT || 8080
|
port: process.env.PORT || 8080,
|
||||||
totp_secret: process.env.TOTP_SECRET,
|
totp_secret: process.env.TOTP_SECRET,
|
||||||
ldap_url: process.env.LDAP_URL || 'ldap://127.0.0.1:389',
|
ldap_url: process.env.LDAP_URL || 'ldap://127.0.0.1:389',
|
||||||
ldap_users_dn: process.env.LDAP_USERS_DN,
|
ldap_users_dn: process.env.LDAP_USERS_DN,
|
||||||
|
|
|
@ -49,6 +49,7 @@ function authenticate(req, res) {
|
||||||
|
|
||||||
function verify_authentication(req, res) {
|
function verify_authentication(req, res) {
|
||||||
console.log('Verify authentication');
|
console.log('Verify authentication');
|
||||||
|
console.log(req.cookies);
|
||||||
|
|
||||||
if(!objectPath.has(req, 'cookies.access_token')) {
|
if(!objectPath.has(req, 'cookies.access_token')) {
|
||||||
return utils.reject('No access token provided');
|
return utils.reject('No access token provided');
|
||||||
|
|
|
@ -33,10 +33,14 @@ function serveAuthPost(req, res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function serveLogin(req, res) {
|
function serveLogin(req, res) {
|
||||||
|
console.log(req.headers);
|
||||||
res.render('login');
|
res.render('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
function serveLogout(req, res) {
|
function serveLogout(req, res) {
|
||||||
|
var redirect_param = req.query.redirect;
|
||||||
|
var redirect_url = redirect_param || '/';
|
||||||
res.clearCookie('access_token');
|
res.clearCookie('access_token');
|
||||||
res.redirect('/');
|
res.redirect(redirect_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,18 @@ var express = require('express');
|
||||||
var bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
var cookieParser = require('cookie-parser');
|
var cookieParser = require('cookie-parser');
|
||||||
var speakeasy = require('speakeasy');
|
var speakeasy = require('speakeasy');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
function run(config, ldap_client) {
|
function run(config, ldap_client) {
|
||||||
|
var view_directory = path.resolve(__dirname, '../views');
|
||||||
|
var public_html_directory = path.resolve(__dirname, '../public_html');
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
app.set('views', './src/views');
|
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.static(__dirname + '/public_html'));
|
app.use(express.static(public_html_directory));
|
||||||
app.use(bodyParser.urlencoded({ extended: false }));
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
|
|
||||||
|
app.set('views', view_directory);
|
||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
app.set('jwt engine', new Jwt(config.jwt_secret));
|
app.set('jwt engine', new Jwt(config.jwt_secret));
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,2 @@
|
||||||
|
/*! js-cookie v2.1.3 | MIT */
|
||||||
|
!function(a){var b=!1;if("function"==typeof define&&define.amd&&(define(a),b=!0),"object"==typeof exports&&(module.exports=a(),b=!0),!b){var c=window.Cookies,d=window.Cookies=a();d.noConflict=function(){return window.Cookies=c,d}}}(function(){function a(){for(var a=0,b={};a<arguments.length;a++){var c=arguments[a];for(var d in c)b[d]=c[d]}return b}function b(c){function d(b,e,f){var g;if("undefined"!=typeof document){if(arguments.length>1){if(f=a({path:"/"},d.defaults,f),"number"==typeof f.expires){var h=new Date;h.setMilliseconds(h.getMilliseconds()+864e5*f.expires),f.expires=h}try{g=JSON.stringify(e),/^[\{\[]/.test(g)&&(e=g)}catch(i){}return e=c.write?c.write(e,b):encodeURIComponent(e+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),b=encodeURIComponent(b+""),b=b.replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent),b=b.replace(/[\(\)]/g,escape),document.cookie=b+"="+e+(f.expires?"; expires="+f.expires.toUTCString():"")+(f.path?"; path="+f.path:"")+(f.domain?"; domain="+f.domain:"")+(f.secure?"; secure":"")}b||(g={});for(var j=document.cookie?document.cookie.split("; "):[],k=/(%[0-9A-Z]{2})+/g,l=0;l<j.length;l++){var m=j[l].split("="),n=m.slice(1).join("=");'"'===n.charAt(0)&&(n=n.slice(1,-1));try{var o=m[0].replace(k,decodeURIComponent);if(n=c.read?c.read(n,o):c(n,o)||n.replace(k,decodeURIComponent),this.json)try{n=JSON.parse(n)}catch(i){}if(b===o){g=n;break}b||(g[o]=n)}catch(i){}}return g}}return d.set=d,d.get=function(a){return d.call(d,a)},d.getJSON=function(){return d.apply({json:!0},[].slice.call(arguments))},d.defaults={},d.remove=function(b,c){d(b,"",a(c,{expires:-1}))},d.withConverter=b,d}return b(function(){})});
|
|
@ -56,3 +56,18 @@ input {
|
||||||
}
|
}
|
||||||
input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); }
|
input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); }
|
||||||
|
|
||||||
|
#information {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin-top: 25px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#information.failure {
|
||||||
|
background-color: rgb(255, 124, 124);
|
||||||
|
}
|
||||||
|
|
||||||
|
#information.success {
|
||||||
|
background-color: rgb(43, 188, 99);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
params={};
|
||||||
|
location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(s,k,v){params[k]=v});
|
||||||
|
console.log(params);
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#login-button').on('click', onLoginButtonClicked);
|
||||||
|
setupEnterKeypressListener();
|
||||||
|
$('#information').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupEnterKeypressListener() {
|
||||||
|
$('#login-form').on('keydown', 'input', function (e) {
|
||||||
|
var key = e.which;
|
||||||
|
switch (key) {
|
||||||
|
case 13: // enter key code
|
||||||
|
onLoginButtonClicked();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoginButtonClicked() {
|
||||||
|
var username = $('#username').val();
|
||||||
|
var password = $('#password').val();
|
||||||
|
var token = $('#token').val();
|
||||||
|
|
||||||
|
authenticate(username, password, token, function(err, access_token) {
|
||||||
|
if(err) {
|
||||||
|
onAuthenticationFailure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onAuthenticationSuccess(access_token);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function authenticate(username, password, token, fn) {
|
||||||
|
$.post('/_auth', {
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
token: token
|
||||||
|
})
|
||||||
|
.done(function(access_token) {
|
||||||
|
fn(undefined, access_token);
|
||||||
|
})
|
||||||
|
.fail(function(err) {
|
||||||
|
fn(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayInformationMessage(msg, type, time, fn) {
|
||||||
|
if(type == 'success') {
|
||||||
|
$('#information').addClass("success");
|
||||||
|
}
|
||||||
|
else if(type == 'failure') {
|
||||||
|
$('#information').addClass("failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#information').text(msg);
|
||||||
|
$('#information').show("fast");
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
$('#information').hide("fast");
|
||||||
|
$('#information').removeClass("success");
|
||||||
|
$('#information').removeClass("failure");
|
||||||
|
|
||||||
|
if(fn) fn();
|
||||||
|
},time);
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirect() {
|
||||||
|
var redirect_uri = '/';
|
||||||
|
if('redirect' in params) {
|
||||||
|
redirect_uri = params['redirect'];
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.replace(redirect_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAuthenticationSuccess(access_token) {
|
||||||
|
Cookies.set('access_token', access_token, { path: '/' });
|
||||||
|
|
||||||
|
$('#username').val('');
|
||||||
|
$('#password').val('');
|
||||||
|
$('#token').val('');
|
||||||
|
|
||||||
|
redirect();
|
||||||
|
// displayInformationMessage('Authentication success, You will be redirected' +
|
||||||
|
// 'in few seconds.', 'success', 3000, function() {
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAuthenticationFailure() {
|
||||||
|
$('#password').val('');
|
||||||
|
$('#token').val('');
|
||||||
|
|
||||||
|
displayInformationMessage('Authentication failed, please try again.', 'failure', 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
|
@ -1,17 +1,21 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
|
<title>Login Portal</title>
|
||||||
<link rel="stylesheet" type="text/css" href="login.css">
|
<link rel="stylesheet" type="text/css" href="login.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="login">
|
<div class="login">
|
||||||
<h1>Login</h1>
|
<h1>Login Portal</h1>
|
||||||
<form method="POST">
|
<div id="login-form">
|
||||||
<input type="text" name="username" placeholder="Username" required="required" />
|
<input type="text" name="username" id="username" placeholder="Username" required="required" />
|
||||||
<input type="password" name="password" placeholder="Password" required="required" />
|
<input type="password" name="password" id="password" placeholder="Password" required="required" />
|
||||||
<input type="text" name="token" placeholder="Verification token" required="required" />
|
<input type="text" name="token" id="token" placeholder="Verification token" required="required" />
|
||||||
<button type="submit" class="btn btn-primary btn-block btn-large">Enter</button>
|
<button type="button" id="login-button" class="btn btn-primary btn-block btn-large">Enter</button>
|
||||||
</form>
|
</div>
|
||||||
<br>
|
<div id="information" style="display: none;"></div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
<script src="jquery.min.js"></script>
|
||||||
|
<script src="js.cookie.min.js"></script>
|
||||||
|
<script src="login.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -9,7 +9,7 @@ var sinon = require('sinon');
|
||||||
describe('test the server', function() {
|
describe('test the server', function() {
|
||||||
var jwt = new Jwt('jwt_secret');
|
var jwt = new Jwt('jwt_secret');
|
||||||
var ldap_client = {
|
var ldap_client = {
|
||||||
bind: sinon.mock()
|
bind: sinon.stub()
|
||||||
};
|
};
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
|
@ -25,11 +25,30 @@ describe('test the server', function() {
|
||||||
// ldap_client.bind.yields(undefined);
|
// ldap_client.bind.yields(undefined);
|
||||||
ldap_client.bind.withArgs('cn=test_ok,ou=users,dc=example,dc=com',
|
ldap_client.bind.withArgs('cn=test_ok,ou=users,dc=example,dc=com',
|
||||||
'password').yields(undefined);
|
'password').yields(undefined);
|
||||||
// ldap_client.bind.withArgs('cn=test_nok,ou=users,dc=example,dc=com',
|
ldap_client.bind.withArgs('cn=test_nok,ou=users,dc=example,dc=com',
|
||||||
// 'password').yields(undefined, 'error');
|
'password').yields('error');
|
||||||
server.run(config, ldap_client);
|
server.run(config, ldap_client);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('test GET /login', function() {
|
||||||
|
test_login()
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test GET /logout', function() {
|
||||||
|
test_logout()
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test GET /_auth', function() {
|
||||||
|
test_get_auth(jwt);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test POST /_auth', function() {
|
||||||
|
test_post_auth(jwt);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function test_login() {
|
||||||
it('should serve the login page', function(done) {
|
it('should serve the login page', function(done) {
|
||||||
request.get('http://localhost:8080/login')
|
request.get('http://localhost:8080/login')
|
||||||
.on('response', function(response) {
|
.on('response', function(response) {
|
||||||
|
@ -37,7 +56,19 @@ describe('test the server', function() {
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_logout() {
|
||||||
|
it('should logout and redirect to /', function(done) {
|
||||||
|
request.get('http://localhost:8080/logout')
|
||||||
|
.on('response', function(response) {
|
||||||
|
assert.equal(response.req.path, '/');
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_get_auth(jwt) {
|
||||||
it('should return status code 401 when user is not authenticated', function(done) {
|
it('should return status code 401 when user is not authenticated', function(done) {
|
||||||
request.get('http://localhost:8080/_auth')
|
request.get('http://localhost:8080/_auth')
|
||||||
.on('response', function(response) {
|
.on('response', function(response) {
|
||||||
|
@ -59,7 +90,9 @@ describe('test the server', function() {
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_post_auth() {
|
||||||
it('should return the JWT token when authentication is successful', function(done) {
|
it('should return the JWT token when authentication is successful', function(done) {
|
||||||
var clock = sinon.useFakeTimers();
|
var clock = sinon.useFakeTimers();
|
||||||
var real_token = speakeasy.totp({
|
var real_token = speakeasy.totp({
|
||||||
|
@ -83,4 +116,26 @@ describe('test the server', function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('should return invalid authentication status code', function(done) {
|
||||||
|
var clock = sinon.useFakeTimers();
|
||||||
|
var real_token = speakeasy.totp({
|
||||||
|
secret: 'totp_secret',
|
||||||
|
encoding: 'base32'
|
||||||
|
});
|
||||||
|
var data = {
|
||||||
|
form: {
|
||||||
|
username: 'test_nok',
|
||||||
|
password: 'password',
|
||||||
|
token: real_token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.post('http://localhost:8080/_auth', data, function (error, response, body) {
|
||||||
|
if(response.statusCode == 401) {
|
||||||
|
clock.restore();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue