diff --git a/.travis.yml b/.travis.yml
index 0b8fecdb..27105ca4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,6 +23,7 @@ addons:
     - mx1.mail.example.com
     - mx2.mail.example.com
     - public.example.com
+    - authelia.example.com
 
 before_install: 
   - npm install -g npm@'>=2.13.5'
diff --git a/README.md b/README.md
index 682b5ce3..b70d69a7 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,9 @@
   [![Build](https://travis-ci.org/clems4ever/authelia.svg?branch=master)](https://travis-ci.org/clems4ever/authelia)
   [![Gitter](https://img.shields.io/gitter/room/badges/shields.svg)](https://gitter.im/authelia/general?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
 
-**Authelia** is a complete HTTP 2-factor authentication server for proxies like 
-nginx. It has been made to work with nginx [auth_request] module and is currently 
-used in production to secure internal services in a small docker swarm cluster.
+**Authelia** is a complete HTTP 2-factor authentication server for proxies like
+Nginx or Traefik. It has been designed to be proxy agnostic so that you can 
+use whichever proxy supporting authentication forwarding.
 
 # Table of Contents
 1. [Features summary](#features-summary)
diff --git a/doc/api_data.js b/doc/api_data.js
index 2eacc2aa..7aba8ada 100644
--- a/doc/api_data.js
+++ b/doc/api_data.js
@@ -20,7 +20,7 @@ define({ "api": [
       }
     },
     "description": "<p>Serves the login page and create a create a cookie for the client.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -56,7 +56,7 @@ define({ "api": [
       }
     },
     "description": "<p>Log out the user and redirect to the URL.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -80,7 +80,7 @@ define({ "api": [
       }
     },
     "description": "<p>Serves the second factor page</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -145,7 +145,7 @@ define({ "api": [
       }
     },
     "description": "<p>Verify credentials against the LDAP.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication",
     "header": {
       "fields": {
@@ -169,7 +169,7 @@ define({ "api": [
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Start password reset request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -240,7 +240,7 @@ define({ "api": [
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Serve a page that requires the username.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -277,7 +277,7 @@ define({ "api": [
       }
     },
     "description": "<p>Set a new password for the user.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -301,7 +301,7 @@ define({ "api": [
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Start password reset request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -366,7 +366,7 @@ define({ "api": [
     "group": "TOTP",
     "version": "1.0.0",
     "description": "<p>Serves the TOTP registration page that displays the secret. The secret is a QRCode and a base32 secret.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -437,7 +437,7 @@ define({ "api": [
     "group": "TOTP",
     "version": "1.0.0",
     "description": "<p>Initiates the identity validation</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -521,7 +521,7 @@ define({ "api": [
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
@@ -549,7 +549,7 @@ define({ "api": [
       }
     },
     "description": "<p>Verify TOTP token. The user is authenticated upon success.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -579,7 +579,7 @@ define({ "api": [
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
@@ -607,7 +607,7 @@ define({ "api": [
       }
     },
     "description": "<p>Complete authentication request of the U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -637,13 +637,13 @@ define({ "api": [
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
     },
     "description": "<p>Complete U2F registration request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -679,7 +679,7 @@ define({ "api": [
     "name": "RequestU2FRegistration",
     "group": "U2F",
     "version": "1.0.0",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -745,7 +745,7 @@ define({ "api": [
     "group": "U2F",
     "version": "1.0.0",
     "description": "<p>Serves the U2F registration page that asks the user to touch the token of the U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -850,7 +850,7 @@ define({ "api": [
       }
     },
     "description": "<p>Initiate an authentication request using a U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -908,7 +908,7 @@ define({ "api": [
       }
     },
     "description": "<p>Initiate a U2F device registration request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -926,11 +926,24 @@ define({ "api": [
   },
   {
     "type": "get",
-    "url": "/verify",
+    "url": "/api/verify",
     "title": "Verify user authentication",
     "name": "VerifyAuthentication",
     "group": "Verification",
     "version": "1.0.0",
+    "parameter": {
+      "fields": {
+        "Parameter": [
+          {
+            "group": "Parameter",
+            "type": "String",
+            "optional": false,
+            "field": "redirect",
+            "description": "<p>Optional parameter set to the url where the user is redirected if access is refused. It is mainly used by Traefik that does not control the redirection itself.</p>"
+          }
+        ]
+      }
+    },
     "success": {
       "fields": {
         "Success 204": [
@@ -945,18 +958,26 @@ define({ "api": [
     },
     "error": {
       "fields": {
+        "Error 302": [
+          {
+            "group": "Error 302",
+            "optional": false,
+            "field": "redirect",
+            "description": "<p>The user is redirected if redirect parameter is provided.</p>"
+          }
+        ],
         "Error 401": [
           {
             "group": "Error 401",
             "optional": false,
             "field": "status",
-            "description": "<p>The user is not authenticated.</p>"
+            "description": "<p>The user get an error if access failed</p>"
           }
         ]
       }
     },
-    "description": "<p>Verify that the user is authenticated, i.e., the two factors have been validated</p>",
-    "filename": "src/server/endpoints.ts",
+    "description": "<p>Verify that the user is authenticated, i.e., the two factors have been validated. If the user is authenticated the response headers Remote-User and Remote-Groups are set. Remote-User contains the user id of the currently logged in user and Remote-Groups a comma separated list of assigned groups.</p>",
+    "filename": "shared/api.ts",
     "groupTitle": "Verification",
     "header": {
       "fields": {
diff --git a/doc/api_data.json b/doc/api_data.json
index 527b6750..c6935ffe 100644
--- a/doc/api_data.json
+++ b/doc/api_data.json
@@ -20,7 +20,7 @@
       }
     },
     "description": "<p>Serves the login page and create a create a cookie for the client.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -56,7 +56,7 @@
       }
     },
     "description": "<p>Log out the user and redirect to the URL.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -80,7 +80,7 @@
       }
     },
     "description": "<p>Serves the second factor page</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication"
   },
   {
@@ -145,7 +145,7 @@
       }
     },
     "description": "<p>Verify credentials against the LDAP.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "Authentication",
     "header": {
       "fields": {
@@ -169,7 +169,7 @@
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Start password reset request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -240,7 +240,7 @@
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Serve a page that requires the username.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -277,7 +277,7 @@
       }
     },
     "description": "<p>Set a new password for the user.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -301,7 +301,7 @@
     "group": "PasswordReset",
     "version": "1.0.0",
     "description": "<p>Start password reset request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "PasswordReset",
     "header": {
       "fields": {
@@ -366,7 +366,7 @@
     "group": "TOTP",
     "version": "1.0.0",
     "description": "<p>Serves the TOTP registration page that displays the secret. The secret is a QRCode and a base32 secret.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -437,7 +437,7 @@
     "group": "TOTP",
     "version": "1.0.0",
     "description": "<p>Initiates the identity validation</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -521,7 +521,7 @@
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
@@ -549,7 +549,7 @@
       }
     },
     "description": "<p>Verify TOTP token. The user is authenticated upon success.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "TOTP",
     "header": {
       "fields": {
@@ -579,7 +579,7 @@
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
@@ -607,7 +607,7 @@
       }
     },
     "description": "<p>Complete authentication request of the U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -637,13 +637,13 @@
             "group": "Success 302",
             "optional": false,
             "field": "Redirect",
-            "description": "<p>to the URL that has been stored during last call to /verify.</p>"
+            "description": "<p>to the URL that has been stored during last call to /api/verify.</p>"
           }
         ]
       }
     },
     "description": "<p>Complete U2F registration request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -679,7 +679,7 @@
     "name": "RequestU2FRegistration",
     "group": "U2F",
     "version": "1.0.0",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -745,7 +745,7 @@
     "group": "U2F",
     "version": "1.0.0",
     "description": "<p>Serves the U2F registration page that asks the user to touch the token of the U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -850,7 +850,7 @@
       }
     },
     "description": "<p>Initiate an authentication request using a U2F device.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -908,7 +908,7 @@
       }
     },
     "description": "<p>Initiate a U2F device registration request.</p>",
-    "filename": "src/server/endpoints.ts",
+    "filename": "shared/api.ts",
     "groupTitle": "U2F",
     "header": {
       "fields": {
@@ -926,11 +926,24 @@
   },
   {
     "type": "get",
-    "url": "/verify",
+    "url": "/api/verify",
     "title": "Verify user authentication",
     "name": "VerifyAuthentication",
     "group": "Verification",
     "version": "1.0.0",
+    "parameter": {
+      "fields": {
+        "Parameter": [
+          {
+            "group": "Parameter",
+            "type": "String",
+            "optional": false,
+            "field": "redirect",
+            "description": "<p>Optional parameter set to the url where the user is redirected if access is refused. It is mainly used by Traefik that does not control the redirection itself.</p>"
+          }
+        ]
+      }
+    },
     "success": {
       "fields": {
         "Success 204": [
@@ -945,18 +958,26 @@
     },
     "error": {
       "fields": {
+        "Error 302": [
+          {
+            "group": "Error 302",
+            "optional": false,
+            "field": "redirect",
+            "description": "<p>The user is redirected if redirect parameter is provided.</p>"
+          }
+        ],
         "Error 401": [
           {
             "group": "Error 401",
             "optional": false,
             "field": "status",
-            "description": "<p>The user is not authenticated.</p>"
+            "description": "<p>The user get an error if access failed</p>"
           }
         ]
       }
     },
-    "description": "<p>Verify that the user is authenticated, i.e., the two factors have been validated</p>",
-    "filename": "src/server/endpoints.ts",
+    "description": "<p>Verify that the user is authenticated, i.e., the two factors have been validated. If the user is authenticated the response headers Remote-User and Remote-Groups are set. Remote-User contains the user id of the currently logged in user and Remote-Groups a comma separated list of assigned groups.</p>",
+    "filename": "shared/api.ts",
     "groupTitle": "Verification",
     "header": {
       "fields": {
diff --git a/doc/api_project.js b/doc/api_project.js
index 9b4ecf09..727258a0 100644
--- a/doc/api_project.js
+++ b/doc/api_project.js
@@ -1,14 +1,14 @@
 define({
   "title": "Authelia API documentation",
   "name": "authelia",
-  "version": "2.1.3",
+  "version": "3.7.0",
   "description": "2FA Single Sign-On server for nginx using LDAP, TOTP and U2F",
   "sampleUrl": false,
   "defaultVersion": "0.0.0",
   "apidoc": "0.3.0",
   "generator": {
     "name": "apidoc",
-    "time": "2017-06-11T20:41:36.025Z",
+    "time": "2017-12-04T21:38:44.927Z",
     "url": "http://apidocjs.com",
     "version": "0.17.6"
   }
diff --git a/doc/api_project.json b/doc/api_project.json
index b27e7e63..a3017b24 100644
--- a/doc/api_project.json
+++ b/doc/api_project.json
@@ -1,14 +1,14 @@
 {
   "title": "Authelia API documentation",
   "name": "authelia",
-  "version": "2.1.3",
+  "version": "3.7.0",
   "description": "2FA Single Sign-On server for nginx using LDAP, TOTP and U2F",
   "sampleUrl": false,
   "defaultVersion": "0.0.0",
   "apidoc": "0.3.0",
   "generator": {
     "name": "apidoc",
-    "time": "2017-06-11T20:41:36.025Z",
+    "time": "2017-12-04T21:38:44.927Z",
     "url": "http://apidocjs.com",
     "version": "0.17.6"
   }
diff --git a/example/nginx/portal/nginx.conf b/example/nginx/portal/nginx.conf
index c7d4016b..1ce5fcfc 100644
--- a/example/nginx/portal/nginx.conf
+++ b/example/nginx/portal/nginx.conf
@@ -322,5 +322,25 @@ http {
             proxy_pass        $upstream_headers;
         }
     }
+
+    server {
+        listen 443 ssl;
+        server_name     authelia.example.com;
+
+        resolver 127.0.0.11 ipv6=off;
+        set $upstream_endpoint http://authelia;
+
+        ssl on;
+        ssl_certificate     /etc/ssl/server.crt;
+        ssl_certificate_key /etc/ssl/server.key;
+
+        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+        add_header X-Frame-Options "SAMEORIGIN";
+
+        location / {
+            proxy_set_header  Host $http_host;
+            proxy_pass        $upstream_endpoint;
+        }
+    }
 }
 
diff --git a/server/src/lib/ErrorReplies.ts b/server/src/lib/ErrorReplies.ts
index dc74abbe..f1c5f4fd 100644
--- a/server/src/lib/ErrorReplies.ts
+++ b/server/src/lib/ErrorReplies.ts
@@ -19,6 +19,15 @@ function replyWithError(req: express.Request, res: express.Response,
   };
 }
 
+export function redirectTo(redirectUrl: string, req: express.Request,
+  res: express.Response, logger: IRequestLogger) {
+  return function(err: Error) {
+    logger.error(req, "Error: %s", err.message);
+    logger.debug(req, "Redirecting to %s", redirectUrl);
+    res.redirect(redirectUrl);
+  };
+}
+
 export function replyWithError400(req: express.Request,
   res: express.Response, logger: IRequestLogger) {
   return replyWithError(req, res, 400, logger);
diff --git a/server/src/lib/routes/verify/get.ts b/server/src/lib/routes/verify/get.ts
index 54f0c2ec..79fda877 100644
--- a/server/src/lib/routes/verify/get.ts
+++ b/server/src/lib/routes/verify/get.ts
@@ -5,6 +5,7 @@ import ErrorReplies = require("../../ErrorReplies");
 import { ServerVariables } from "../../ServerVariables";
 import GetWithSessionCookieMethod from "./get_session_cookie";
 import GetWithBasicAuthMethod from "./get_basic_auth";
+import Constants = require("../../../../../shared/constants");
 
 import { AuthenticationSessionHandler }
   from "../../AuthenticationSessionHandler";
@@ -50,6 +51,12 @@ function replyWith200(res: Express.Response) {
   };
 }
 
+function getRedirectParam(req: Express.Request) {
+  return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined"
+    ? req.query[Constants.REDIRECT_QUERY_PARAM]
+    : undefined;
+}
+
 export default function (vars: ServerVariables) {
   return function (req: Express.Request, res: Express.Response)
     : BluebirdPromise<void> {
@@ -66,7 +73,15 @@ export default function (vars: ServerVariables) {
       .catch(Exceptions.DomainAccessDenied, ErrorReplies
         .replyWithError403(req, res, vars.logger))
       // The user is not yet authenticated -> 401
-      .catch(ErrorReplies.replyWithError401(req, res, vars.logger));
+      .catch(function (err) {
+        const redirectUrl = getRedirectParam(req);
+        if (redirectUrl) {
+          ErrorReplies.redirectTo(redirectUrl, req, res, vars.logger)(err);
+        }
+        else {
+          ErrorReplies.replyWithError401(req, res, vars.logger)(err);
+        }
+      });
   };
 }
 
diff --git a/server/test/routes/verify/get.test.ts b/server/test/routes/verify/get.test.ts
index 099e763b..d46a0af6 100644
--- a/server/test/routes/verify/get.test.ts
+++ b/server/test/routes/verify/get.test.ts
@@ -24,11 +24,11 @@ describe("test /api/verify endpoint", function () {
     res = ExpressMock.ResponseMock();
     req.originalUrl = "/api/xxxx";
     req.query = {
-      redirect: "http://redirect.url"
+      redirect: "undefined"
     };
     AuthenticationSessionHandler.reset(req as any);
     req.headers.host = "secret.example.com";
-    const s = ServerVariablesMockBuilder.build(true);
+    const s = ServerVariablesMockBuilder.build(false);
     mocks = s.mocks;
     vars = s.variables;
     authSession = AuthenticationSessionHandler.get(req as any, vars.logger);
@@ -147,9 +147,6 @@ describe("test /api/verify endpoint", function () {
 
     describe("given user tries to access a single factor endpoint", function () {
       beforeEach(function () {
-        req.query = {
-          redirect: "http://redirect.url"
-        };
         req.headers["host"] = "redirect.url";
         mocks.config.authentication_methods.per_subdomain_methods = {
           "redirect.url": "single_factor"
@@ -220,6 +217,36 @@ describe("test /api/verify endpoint", function () {
     });
   });
 
+  describe("response type 401 | 302", function() {
+    it("should return error code 401", function() {
+      mocks.accessController.isAccessAllowedMock.returns(true);
+      mocks.config.authentication_methods.default_method = "single_factor";
+      mocks.ldapAuthenticator.authenticateStub.rejects(new Error(
+        "Invalid credentials"));
+      req.headers["proxy-authorization"] = "Basic am9objpwYXNzd29yZA==";
+
+      return VerifyGet.default(vars)(req as express.Request, res as any)
+        .then(function () {
+          Assert(res.status.calledWithExactly(401));
+        });
+    });
+
+    it("should redirect to provided redirection url", function() {
+      const REDIRECT_URL = "http://redirection_url.com";
+      mocks.accessController.isAccessAllowedMock.returns(true);
+      mocks.config.authentication_methods.default_method = "single_factor";
+      mocks.ldapAuthenticator.authenticateStub.rejects(new Error(
+        "Invalid credentials"));
+      req.headers["proxy-authorization"] = "Basic am9objpwYXNzd29yZA==";
+      req.query["redirect"] = REDIRECT_URL;
+
+      return VerifyGet.default(vars)(req as express.Request, res as any)
+        .then(function () {
+          Assert(res.redirect.calledWithExactly(REDIRECT_URL));
+        });
+    });
+  });
+
   describe("with basic auth", function () {
     it("should authenticate correctly", function () {
       mocks.accessController.isAccessAllowedMock.returns(true);
diff --git a/shared/api.ts b/shared/api.ts
index ef257f2c..2ebe5d3d 100644
--- a/shared/api.ts
+++ b/shared/api.ts
@@ -39,7 +39,7 @@
  * @apiUse UserSession
  * @apiUse InternalError
  *
- * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /verify.
+ * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /api/verify.
  *
  * @apiDescription Complete U2F registration request.
  */
@@ -68,7 +68,7 @@ export const SECOND_FACTOR_U2F_REGISTER_REQUEST_GET = "/api/u2f/register_request
  * @apiUse UserSession
  * @apiUse InternalError
  *
- * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /verify.
+ * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /api/verify.
  * @apiError (Error 403) {none} error No authentication request has been provided.
  *
  * @apiDescription Complete authentication request of the U2F device.
@@ -100,7 +100,7 @@ export const SECOND_FACTOR_U2F_SIGN_REQUEST_GET = "/api/u2f/sign_request";
  *
  * @apiParam {String} token TOTP token.
  *
- * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /verify.
+ * @apiSuccess (Success 302) Redirect to the URL that has been stored during last call to /api/verify.
  * @apiError (Error 401) {none} error TOTP token is invalid.
  *
  * @apiDescription Verify TOTP token. The user is authenticated upon success.
@@ -270,8 +270,13 @@ export const SECOND_FACTOR_GET = "/secondfactor";
  * @apiVersion 1.0.0
  * @apiUse UserSession
  *
+ * @apiParam {String} redirect Optional parameter set to the url where the user
+ * is redirected if access is refused. It is mainly used by Traefik that does
+ * not control the redirection itself.
+ *
  * @apiSuccess (Success 204) status The user is authenticated.
- * @apiError (Error 401) status The user is not authenticated.
+ * @apiError (Error 302) redirect The user is redirected if redirect parameter is provided.
+ * @apiError (Error 401) status The user get an error if access failed
  *
  * @apiDescription Verify that the user is authenticated, i.e., the two
  * factors have been validated.
diff --git a/test/features/authelia.feature b/test/features/authelia.feature
new file mode 100644
index 00000000..7c7f472d
--- /dev/null
+++ b/test/features/authelia.feature
@@ -0,0 +1,9 @@
+Feature: Generic tests on Authelia endpoints
+
+  Scenario: /api/verify replies with error when redirect parameter is not provided
+    When I query "https://authelia.example.com:8080/api/verify"
+    Then I get error code 401
+
+  Scenario: /api/verify redirects when redirect parameter is provided
+    When I query "https://authelia.example.com:8080/api/verify?redirect=http://login.example.com:8080"
+    Then I get redirected to "http://login.example.com:8080"
\ No newline at end of file
diff --git a/test/features/step_definitions/authelia.ts b/test/features/step_definitions/authelia.ts
new file mode 100644
index 00000000..da3f9676
--- /dev/null
+++ b/test/features/step_definitions/authelia.ts
@@ -0,0 +1,51 @@
+import Cucumber = require("cucumber");
+import seleniumWebdriver = require("selenium-webdriver");
+import Assert = require("assert");
+import Request = require("request-promise");
+import Bluebird = require("bluebird");
+
+Cucumber.defineSupportCode(function ({ Given, When, Then, Before, After }) {
+  Before(function () {
+    this.jar = Request.jar();
+  })
+
+  When("I query {stringInDoubleQuotes}", function (url: string) {
+    const that = this;
+    return Request(url, { followRedirect: false })
+      .then(function(response) {
+        console.log(response);
+        that.response = response;
+      })
+      .catch(function(err: Error) {
+        that.error = err;
+      })
+  });
+
+  Then("I get error code 401", function() {
+    const that = this;
+    return new Bluebird(function(resolve, reject) {
+      if(that.error && that.error.statusCode == 401) {
+        resolve();
+      }
+      else {
+        if(that.response) 
+          reject(new Error("No error thrown"));
+        else if(that.error.statusCode != 401)
+          reject(new Error("Error code != 401"));
+      }
+    });
+  });
+
+  Then("I get redirected to {stringInDoubleQuotes}", function(url: string) {
+    const that = this;
+    return new Bluebird(function(resolve, reject) {
+      if(that.error && that.error.statusCode == 302 
+        && that.error.message.indexOf(url) > -1) {
+        resolve();
+      }
+      else {
+        reject(new Error("Not redirected"));
+      }
+    });
+  })
+});
\ No newline at end of file