diff --git a/client/src/css/01-main.css b/client/src/css/01-main.css index 443430d39..662d72e74 100644 --- a/client/src/css/01-main.css +++ b/client/src/css/01-main.css @@ -1,61 +1,66 @@ - body { - background-image: url("/img/background.svg"); + background-image: url("/img/background.svg"); } - .authelia-brand { - font-weight: bold; - font-style: italic; - color: #648caf + font-weight: bold; + font-style: italic; + color: #648caf } - .poweredby-block { - margin: 0px 30px; - margin-top: 10px; - padding-top: 15px; - border-top: 1px solid rgba(0, 0, 0, 0.15); + margin: 0px 30px; + margin-top: 10px; + padding-top: 15px; + border-top: 1px solid rgba(0, 0, 0, 0.15); } - .poweredby { - font-size: 0.7em; - color: #6b6b6b; + font-size: 0.7em; + color: #6b6b6b; } - /* notifications */ - .notification { - padding: 10px; - border-radius: 6px; - display: none; + padding: 10px; + margin: 10px 0px; + border-radius: 6px; + display: none; } - .notification img { - width: 24px; - margin-right: 10px; + width: 24px; + margin-right: 10px; } - .notification i, .notification span { - display:table-cell; - vertical-align:middle; + display:table-cell; + vertical-align:middle; } - .info { - border: 1px solid #9cb1ff; - background-color: rgb(192, 220, 255); + border: 1px solid #9cb1ff; + background-color: rgb(192, 220, 255); } - .success { - border: 1px solid #65ec7c; - background-color: rgb(163, 255, 157); + border: 1px solid #65ec7c; + background-color: rgb(163, 255, 157); } - .error { - border: 1px solid #ffa3a3; - background-color: rgb(255, 175, 175); + border: 1px solid #ffa3a3; + background-color: rgb(255, 175, 175); } - .warning { - border: 1px solid #ffd743; - background-color: rgb(255, 230, 143); + border: 1px solid #ffd743; + background-color: rgb(255, 230, 143); +} +.bottom-right-links { + text-align: right; + margin-top: 10px; + font-size: 0.8em; +} +.header { + background-color: #778dab; + color: white; + margin: 0px; +} +.body { + padding: 10px; +} +h1 { + font-size: 30px; } \ No newline at end of file diff --git a/client/src/css/02-login.css b/client/src/css/02-login.css index 9f17de7b6..a28d6fd05 100644 --- a/client/src/css/02-login.css +++ b/client/src/css/02-login.css @@ -1,6 +1,5 @@ .form-signin { - padding: 15px; margin: 0 auto; } @@ -44,8 +43,7 @@ { border: 1px solid #DDD; margin-top: 20px; - padding: 20px; - padding-bottom: 15px; + padding-bottom: 20px; background-color: #f7f7f7; -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); @@ -53,18 +51,20 @@ } .account-wall h1 { - color: #555; - margin-bottom: 30px; - font-weight: 400; + margin-bottom: 20px; + font-weight: 800; + display: block; + text-align: center; +} +.account-wall h3 +{ display: block; text-align: center; } .account-wall p { text-align: center; - margin: 10px 10px; - margin-top: 20px; - font-size: 1.3em; + margin: 10px; } .account-wall .form-inputs { @@ -98,4 +98,12 @@ .btn-primary.u2f { background-color: rgb(83, 149, 204); +} + +.u2f-token { + text-align: center; +} + +.u2f-token img { + width: 70px; } \ No newline at end of file diff --git a/client/src/css/03-totp-register.css b/client/src/css/03-totp-register.css index ebd243a77..cb76720ad 100644 --- a/client/src/css/03-totp-register.css +++ b/client/src/css/03-totp-register.css @@ -6,20 +6,16 @@ border: 1px solid #c7c7c7; word-wrap: break-word; } - .totp-register #qrcode img { - margin: 20px auto; + margin: 10px auto; } - .totp-register .need-google-authenticator { text-align: center; - margin: 20px; + margin-top: 20px; } - .totp-register .store-badges { margin-top: 5px; } - .totp-register .store-badge { width: 110px; height: 30px; diff --git a/client/src/lib/secondfactor/constants.ts b/client/src/lib/secondfactor/constants.ts index eb8b154b3..50bba7571 100644 --- a/client/src/lib/secondfactor/constants.ts +++ b/client/src/lib/secondfactor/constants.ts @@ -1,5 +1,3 @@ export const TOTP_FORM_SELECTOR = ".form-signin.totp"; export const TOTP_TOKEN_SELECTOR = ".form-signin #token"; - -export const U2F_FORM_SELECTOR = ".form-signin.u2f"; \ No newline at end of file diff --git a/client/src/lib/secondfactor/index.ts b/client/src/lib/secondfactor/index.ts index bd3f9e13a..db58cfff2 100644 --- a/client/src/lib/secondfactor/index.ts +++ b/client/src/lib/secondfactor/index.ts @@ -49,14 +49,9 @@ export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) return false; } - function onU2FFormSubmitted(): boolean { - U2FValidator.validate($, notifierU2f, U2fApi) - .then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure); - return false; - } - $(window.document).ready(function () { $(ClientConstants.TOTP_FORM_SELECTOR).on("submit", onTOTPFormSubmitted); - $(ClientConstants.U2F_FORM_SELECTOR).on("submit", onU2FFormSubmitted); + U2FValidator.validate($, notifierU2f, U2fApi) + .then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure); }); } \ No newline at end of file diff --git a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts index fa37c1540..c262efc01 100644 --- a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts +++ b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts @@ -41,7 +41,7 @@ export default class RegistrationHandler implements IdentityValidable { const email = authSession.email; if (!(userid && email)) { - return BluebirdPromise.reject(new Error("User ID or email is missing")); + return BluebirdPromise.reject(new Error("User ID or email is missing.")); } const identity = { @@ -79,7 +79,7 @@ export default class RegistrationHandler implements IdentityValidable { return BluebirdPromise.reject(new Error("Bad challenge.")); } const secret = that.totp.generate(); - that.logger.debug(req, "Save the TOTP secret in DB"); + that.logger.debug(req, "Save the TOTP secret in DB."); return that.userDataStore.saveTOTPSecret(userid, secret) .then(function () { AuthenticationSession.reset(req); @@ -95,6 +95,6 @@ export default class RegistrationHandler implements IdentityValidable { } mailSubject(): string { - return "Register your TOTP secret key"; + return "Set up Authelia's one-time password"; } } \ No newline at end of file diff --git a/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts index bd41ecae2..7c99ec265 100644 --- a/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts +++ b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts @@ -11,7 +11,7 @@ import AuthenticationSession = require("../../../../AuthenticationSession"); import { IRequestLogger } from "../../../../logging/IRequestLogger"; const CHALLENGE = "u2f-register"; -const MAIL_SUBJECT = "Register your U2F device"; +const MAIL_SUBJECT = "Register your security key with Authelia"; const POST_VALIDATION_TEMPLATE_NAME = "u2f-register"; diff --git a/server/src/views/already-logged-in.pug b/server/src/views/already-logged-in.pug index 765e03447..541717d91 100644 --- a/server/src/views/already-logged-in.pug +++ b/server/src/views/already-logged-in.pug @@ -1,10 +1,10 @@ extends layout/layout.pug block form-header -

Sign in

- + h1 Sign in block content -

You are already logged in as #{ username }.

+ img(class="header-img" src="/img/success.png" alt="success") + p You are already logged in as #{ username }.

| If you are not redirected in few seconds, click here.

- | Otherwise, click here to log off.

+ | Otherwise, click here to log off. diff --git a/server/src/views/errors/401.pug b/server/src/views/errors/401.pug index b0dfae0e9..052b4dc57 100644 --- a/server/src/views/errors/401.pug +++ b/server/src/views/errors/401.pug @@ -4,8 +4,8 @@ block variables - page_classname = "error-401"; block form-header -

Error 401

- + h1 Error 401 block content -

Please log in to access this resource.

+ img(class="header-img" src="/img/warning.png" alt="warning") + p Please log in to access this resource. diff --git a/server/src/views/errors/403.pug b/server/src/views/errors/403.pug index 605f6f389..b0b77b606 100644 --- a/server/src/views/errors/403.pug +++ b/server/src/views/errors/403.pug @@ -4,8 +4,8 @@ block variables - page_classname = "error-403"; block form-header -

Error 403

- + h1 Error 403 block content -

You are not authorized to access this resource.

+ img(class="header-img" src="/img/warning.png" alt="warning") + p You are not authorized to access this resource. diff --git a/server/src/views/errors/404.pug b/server/src/views/errors/404.pug index 3228f71a3..06d6375fc 100644 --- a/server/src/views/errors/404.pug +++ b/server/src/views/errors/404.pug @@ -5,7 +5,7 @@ block variables block form-header

Error 404

- block content -

Page not found.

+ img(class="header-img" src="/img/warning.png" alt="warning") + p Page not found. diff --git a/server/src/views/firstfactor.pug b/server/src/views/firstfactor.pug index c7571fb86..373d2f454 100644 --- a/server/src/views/firstfactor.pug +++ b/server/src/views/firstfactor.pug @@ -1,17 +1,20 @@ extends layout/layout.pug +block variables + - page_classname = "firstfactor"; + block form-header -

Sign in

- + h1 Sign in block content -
-
-
- - -
- - a(href=reset_password_request_endpoint, class="pull-right link forgot-password") Forgot password? - -
\ No newline at end of file + img(class="header-img" src="/img/user.png" alt="user profile") + p Enter your credentials to sign in + div(class="notification") + form(class="form-signin") + div(class="form-inputs") + input(type="text" class="form-control" id="username" placeholder="Username" required autofocus) + input(type="password" class="form-control" id="password" placeholder="Password" required) + button(class="btn btn-lg btn-primary btn-block" type="submit") Sign in + div(class="bottom-right-links pull-right") + a(href=reset_password_request_endpoint, class="link forgot-password") Forgot password? + span(class="clearfix") diff --git a/server/src/views/layout/layout.pug b/server/src/views/layout/layout.pug index 613f6f052..eaf315aee 100644 --- a/server/src/views/layout/layout.pug +++ b/server/src/views/layout/layout.pug @@ -9,24 +9,19 @@ html link(rel="icon", href="/img/icon.png" type="image/png" sizes="32x32")/ link(rel="stylesheet", type="text/css", href="/css/authelia.css")/ if redirection_url - + meta(http-equiv="refresh" content="4;url=" + redirection_url) body -
-
-
- -
-
-
+ div(class="row footer poweredby-block") + div(class="poweredby col-xs-6 col-xs-offset-4 col-sm-6 col-sm-offset-4 col-md-6 col-md-offset-4") + | Powered by Authelia block entrypoint script(src="/js/authelia.js") \ No newline at end of file diff --git a/server/src/views/need-identity-validation.pug b/server/src/views/need-identity-validation.pug index c6690b0b2..4cfd62717 100644 --- a/server/src/views/need-identity-validation.pug +++ b/server/src/views/need-identity-validation.pug @@ -1,8 +1,12 @@ extends layout/layout.pug +block variables + - page_classname = "identity-validation"; + block form-header -

Registration

- + h1 Registration block content -

A confirmation email has been sent to your mailbox. Please open it and click on the link within 15 minutes to confirm the registration.

+ img(class="header-img" src="/img/mail.png" alt="mail") + p A confirmation email has been sent to your mailbox. + | Please open it and click on the link within 15 minutes to confirm the registration. diff --git a/server/src/views/password-reset-form.pug b/server/src/views/password-reset-form.pug index a6fd69349..5f14cdbb9 100644 --- a/server/src/views/password-reset-form.pug +++ b/server/src/views/password-reset-form.pug @@ -4,17 +4,15 @@ block variables - page_classname = "password-reset-form"; block form-header -

Reset password

- -

Set your new password and confirm it.

+ h1 Reset password block content -
-
-
- - -
- - -
\ No newline at end of file + img(class="header-img" src="/img/password.png" alt="password") + p Set your new password and confirm it. + div(class="notification") + form(class="form-signin") + div(class="form-inputs") + input(class="form-control" type="password" name="password1" id="password1" placeholder="New password" required="required") + input(class="form-control" type="password" name="password2" id="password2" placeholder="Password confirmation" required="required") + button(id="reset-password-button" class="btn btn-lg btn-primary btn-block" type="submit") Reset Password + span(class="clearfix") \ No newline at end of file diff --git a/server/src/views/password-reset-request.pug b/server/src/views/password-reset-request.pug index b72f2e2d3..8236508f1 100644 --- a/server/src/views/password-reset-request.pug +++ b/server/src/views/password-reset-request.pug @@ -4,16 +4,15 @@ block variables - page_classname = "password-reset-request"; block form-header -

Reset password

- -

After giving your username, you will receive an email to change your password.

+ h1 Reset password block content -
-
-
- -
- - -
\ No newline at end of file + div + img(class="header-img" src="/img/password.png" alt="password") + p After giving your username, you will receive an email to change your password. + div(class="notification") + form(class="form-signin") + div(class="form-inputs") + input(type="text" class="form-control" name="username" id="username" placeholder="Your username" required="required") + button(id="reset-password-button" class="btn btn-lg btn-primary btn-block" type="submit") Reset Password + span(class="clearfix") \ No newline at end of file diff --git a/server/src/views/secondfactor.pug b/server/src/views/secondfactor.pug index 03f1817b9..aaabeccb5 100644 --- a/server/src/views/secondfactor.pug +++ b/server/src/views/secondfactor.pug @@ -1,24 +1,30 @@ extends layout/layout.pug +block variables + - page_classname = "secondfactor"; + block form-header -

Sign in

- + h1 Sign in block content - p Hi #{username}, please complete second factor or logout. -
-
-
- -
- - a(href=totp_identity_start_endpoint, class="pull-right link register-totp") Need to register? - -
-
-
-
- - a(href=u2f_identity_start_endpoint, class="pull-right link register-u2f") Need to register? - -
\ No newline at end of file + div + h3 Hi #{username} + div(class="row") + div(class="u2f-token") + img(src="/img/pendrive.png", alt="security key") + p + | touch your U2F device
+ b Or
+ | get a one-time password + div(class="notification notification-totp") + form(class="form-signin totp") + div(class="form-inputs") + input(type="text" autocomplete="off" class="form-control" id="token" placeholder="Token" required autofocus) + button(class="btn btn-lg btn-primary btn-block totp-button" type="submit") Sign in + div(class="pull-right bottom-right-links") + div Need to register? + div + a(href=u2f_identity_start_endpoint, class="link register-u2f") U2F + | | + a(href=totp_identity_start_endpoint, class="link register-totp") Google Authenticator + span(class="clearfix") \ No newline at end of file diff --git a/server/src/views/totp-register.pug b/server/src/views/totp-register.pug index 1eeadb319..4436d82e3 100644 --- a/server/src/views/totp-register.pug +++ b/server/src/views/totp-register.pug @@ -4,12 +4,12 @@ block variables - page_classname = "totp-register"; block form-header -

One-time passwords

-

Open Google Authenticator and add this entry

+ h1 One-time passwords block content + p Open Google Authenticator and add this entry p(id="secret") #{ base32_secret } - p Or scan this barcode + p or scan this barcode div(id="qrcode") #{ otpauth_url } p a(href=login_endpoint, id="login-button") Login @@ -22,4 +22,4 @@ block content img(alt='Get it on Apple Store' src='/img/stores/applestore-badge.svg' class="store-badge") block entrypoint - + script(src="/js/qrcode.min.js") diff --git a/server/src/views/u2f-register.pug b/server/src/views/u2f-register.pug index caca0620c..5e24bc707 100644 --- a/server/src/views/u2f-register.pug +++ b/server/src/views/u2f-register.pug @@ -4,8 +4,8 @@ block variables - page_classname = "u2f-register"; block form-header -

U2F Registration

-

Touch the token to register your U2F device.

+ h1 Register your security key block content - pendrive \ No newline at end of file + p Touch the token to register your security key. + img(src="/img/pendrive.png" alt="pendrive") \ No newline at end of file diff --git a/test/features/access-control.feature b/test/features/access-control.feature index ea484ce99..0051c0ae6 100644 --- a/test/features/access-control.feature +++ b/test/features/access-control.feature @@ -5,7 +5,7 @@ Feature: User has access restricted access to domains When I visit "https://auth.test.local:8080?redirect=https%3A%2F%2Fhome.test.local%3A8080%2F" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" And I'm redirected to "https://home.test.local:8080/" Then I have access to: | url | @@ -27,7 +27,7 @@ Feature: User has access restricted access to domains When I visit "https://auth.test.local:8080?redirect=https%3A%2F%2Fhome.test.local%3A8080%2F" And I login with user "bob" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" And I'm redirected to "https://home.test.local:8080/" Then I have access to: | url | @@ -49,7 +49,7 @@ Feature: User has access restricted access to domains When I visit "https://auth.test.local:8080?redirect=https%3A%2F%2Fhome.test.local%3A8080%2F" And I login with user "harry" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" And I'm redirected to "https://home.test.local:8080/" Then I have access to: | url | diff --git a/test/features/auth-portal-redirection.feature b/test/features/auth-portal-redirection.feature index eb7eed132..988c1d09f 100644 --- a/test/features/auth-portal-redirection.feature +++ b/test/features/auth-portal-redirection.feature @@ -15,7 +15,7 @@ Feature: User is redirected when factors are already validated And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" And I'm redirected to "https://public.test.local:8080/secret.html" And I visit "https://auth.test.local:8080" Then I'm redirected to "https://auth.test.local:8080/loggedin" @@ -28,7 +28,7 @@ Feature: User is redirected when factors are already validated And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fpublic.test.local%3A8080%2Fsecret.html" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" And I'm redirected to "https://public.test.local:8080/secret.html" And I visit "https://auth.test.local:8080?redirect=https://public.test.local:8080/secret.html" Then I'm redirected to "https://public.test.local:8080/secret.html" diff --git a/test/features/authentication.feature b/test/features/authentication.feature index 11a600fcb..f71794006 100644 --- a/test/features/authentication.feature +++ b/test/features/authentication.feature @@ -22,7 +22,7 @@ Feature: Authentication scenarii And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fadmin.test.local%3A8080%2Fsecret.html" And I login with user "john" and password "password" And I use "Sec0" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://admin.test.local:8080/secret.html" Scenario: User fails TOTP second factor @@ -30,7 +30,7 @@ Feature: Authentication scenarii And I'm redirected to "https://auth.test.local:8080/?redirect=https%3A%2F%2Fadmin.test.local%3A8080%2Fsecret.html" And I login with user "john" and password "password" And I use "BADTOKEN" as TOTP token - And I click on "TOTP" + And I click on "Sign in" Then I get a notification of type "error" with message "Authentication failed. Have you already registered your secret?" Scenario: Logout redirects user to redirect URL given in parameter diff --git a/test/features/redirection.feature b/test/features/redirection.feature index b7d6584fe..19890a464 100644 --- a/test/features/redirection.feature +++ b/test/features/redirection.feature @@ -12,7 +12,7 @@ Feature: User is correctly redirected And I clear field "username" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://public.test.local:8080/secret.html" Scenario: User Harry does not have access to admin domain and thus he must get an error 403 @@ -39,7 +39,7 @@ Feature: User is correctly redirected When I visit "https://public.test.local:8080/secret.html" And I login with user "john" and password "password" And I use "Sec0" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://public.test.local:8080/secret.html" @need-registered-user-john @@ -47,5 +47,5 @@ Feature: User is correctly redirected When I visit "https://auth.test.local:8080" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://home.test.local:8080/" \ No newline at end of file diff --git a/test/features/regulation.feature b/test/features/regulation.feature index baac96a2b..fb8b99580 100644 --- a/test/features/regulation.feature +++ b/test/features/regulation.feature @@ -35,5 +35,5 @@ Feature: Authelia regulates authentication to avoid brute force And I set field "password" to "password" And I click on "Sign in" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://public.test.local:8080/secret.html" \ No newline at end of file diff --git a/test/features/resilience.feature b/test/features/resilience.feature index 0b444c75e..8debd46c1 100644 --- a/test/features/resilience.feature +++ b/test/features/resilience.feature @@ -13,5 +13,5 @@ Feature: Authelia keeps user sessions despite the application restart And I visit "https://admin.test.local:8080/secret.html" and get redirected "https://auth.test.local:8080/?redirect=https%3A%2F%2Fadmin.test.local%3A8080%2Fsecret.html" And I login with user "john" and password "password" And I use "REGISTERED" as TOTP token handle - And I click on "TOTP" + And I click on "Sign in" Then I'm redirected to "https://admin.test.local:8080/secret.html" \ No newline at end of file diff --git a/test/features/step_definitions/hooks.ts b/test/features/step_definitions/hooks.ts index b2ff9f75a..b90192ce2 100644 --- a/test/features/step_definitions/hooks.ts +++ b/test/features/step_definitions/hooks.ts @@ -97,7 +97,7 @@ Cucumber.defineSupportCode(function ({ After, Before }) { return context.useTotpTokenHandle("REGISTERED"); }) .then(function () { - return context.clickOnButton("TOTP"); + return context.clickOnButton("Sign in"); }); } diff --git a/test/features/support/world.ts b/test/features/support/world.ts index 275135b5f..e75e71f9d 100644 --- a/test/features/support/world.ts +++ b/test/features/support/world.ts @@ -164,7 +164,7 @@ function CustomWorld() { return that.useTotpTokenHandle(totpHandle); }) .then(function () { - return that.clickOnButton("TOTP"); + return that.clickOnButton("Sign in"); }); }; }