From ab27084e7ea85f17c173f8c2b2802d72ee800dbf Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 6 May 2020 15:43:08 +0300 Subject: [PATCH 1/4] Improve OAuth button style --- ui/src/app/login/login.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/login/login.tpl.html b/ui/src/app/login/login.tpl.html index e4f7f2559e..77308e464a 100644 --- a/ui/src/app/login/login.tpl.html +++ b/ui/src/app/login/login.tpl.html @@ -51,7 +51,7 @@
{{ "login.or" | translate | uppercase }}
- {{ 'login.login-with' | translate: {name: oauth2Client.name} }} From f29c9c9452bb310637c5f53e186f6dc63f69ae2b Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 6 May 2020 16:22:18 +0300 Subject: [PATCH 2/4] Improve OAuth button style --- ui/src/app/login/login.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/login/login.tpl.html b/ui/src/app/login/login.tpl.html index 77308e464a..f12a207856 100644 --- a/ui/src/app/login/login.tpl.html +++ b/ui/src/app/login/login.tpl.html @@ -51,7 +51,7 @@
{{ "login.or" | translate | uppercase }}
- {{ 'login.login-with' | translate: {name: oauth2Client.name} }} From 9b18c408b2e2104d55df8d0c36ec9b68b2870641 Mon Sep 17 00:00:00 2001 From: VoBa Date: Wed, 6 May 2020 19:20:18 +0300 Subject: [PATCH 3/4] Added activate user config. Fixed https issue (#2737) * Added activate user config. Fixed https issue * Update OAuth2User.java Co-authored-by: Igor Kulikov --- .../ThingsboardSecurityConfiguration.java | 4 +-- .../server/controller/AuthController.java | 7 ++-- .../server/controller/BaseController.java | 33 ------------------ .../server/controller/UserController.java | 7 ++-- .../oauth2/AbstractOAuth2ClientMapper.java | 8 +++-- .../auth/oauth2/BasicOAuth2ClientMapper.java | 3 +- .../auth/oauth2/CustomOAuth2ClientMapper.java | 2 +- .../Oauth2AuthenticationSuccessHandler.java | 4 ++- .../thingsboard/server/utils/MiscUtils.java | 34 ++++++++++++++++++- .../src/main/resources/thingsboard.yml | 6 ++-- .../dao/oauth2/OAuth2ClientMapperConfig.java | 3 +- 11 files changed, 60 insertions(+), 51 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 9e967158b4..8a21fd229f 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -204,11 +204,11 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt http.oauth2Login() .loginPage("/oauth2Login") .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl()) - .successHandler(oauth2AuthenticationSuccessHandler); + .successHandler(oauth2AuthenticationSuccessHandler) + .failureHandler(failureHandler); } } - @Bean @ConditionalOnMissingBean(CorsFilter.class) public CorsFilter corsFilter(@Autowired MvcCorsProperties mvcCorsProperties) { diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index 49cfe482df..9f6c6f3b44 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -52,6 +52,7 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.model.token.JwtToken; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; +import org.thingsboard.server.utils.MiscUtils; import ua_parser.Client; import javax.servlet.http.HttpServletRequest; @@ -170,7 +171,7 @@ public class AuthController extends BaseController { try { String email = resetPasswordByEmailRequest.get("email").asText(); UserCredentials userCredentials = userService.requestPasswordReset(TenantId.SYS_TENANT_ID, email); - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, userCredentials.getResetToken()); @@ -218,7 +219,7 @@ public class AuthController extends BaseController { User user = userService.findUserById(TenantId.SYS_TENANT_ID, credentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal); - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String loginUrl = String.format("%s/login", baseUrl); String email = user.getEmail(); @@ -265,7 +266,7 @@ public class AuthController extends BaseController { User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), principal); - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String loginUrl = String.format("%s/login", baseUrl); String email = user.getEmail(); mailService.sendPasswordWasResetEmail(loginUrl, email); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 8385e61a20..a8d6098c4a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -521,39 +521,6 @@ public abstract class BaseController { return ruleNode; } - - protected String constructBaseUrl(HttpServletRequest request) { - String scheme = request.getScheme(); - - String forwardedProto = request.getHeader("x-forwarded-proto"); - if (forwardedProto != null) { - scheme = forwardedProto; - } - - int serverPort = request.getServerPort(); - if (request.getHeader("x-forwarded-port") != null) { - try { - serverPort = request.getIntHeader("x-forwarded-port"); - } catch (NumberFormatException e) { - } - } else if (forwardedProto != null) { - switch (forwardedProto) { - case "http": - serverPort = 80; - break; - case "https": - serverPort = 443; - break; - } - } - - String baseUrl = String.format("%s://%s:%d", - scheme, - request.getServerName(), - serverPort); - return baseUrl; - } - protected I emptyId(EntityType entityType) { return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index a37d9c29b6..bf64ad7d6f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -52,6 +52,7 @@ import org.thingsboard.server.service.security.model.token.JwtToken; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import org.thingsboard.server.utils.MiscUtils; import javax.servlet.http.HttpServletRequest; @@ -148,7 +149,7 @@ public class UserController extends BaseController { if (sendEmail) { SecurityUser authUser = getCurrentUser(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), savedUser.getId()); - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); String email = savedUser.getEmail(); @@ -188,7 +189,7 @@ public class UserController extends BaseController { UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId()); if (!userCredentials.isEnabled()) { - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); mailService.sendActivationEmail(activateUrl, email); @@ -213,7 +214,7 @@ public class UserController extends BaseController { SecurityUser authUser = getCurrentUser(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId()); if (!userCredentials.isEnabled()) { - String baseUrl = constructBaseUrl(request); + String baseUrl = MiscUtils.constructBaseUrl(request); String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); return activateUrl; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java index f620c34436..dd49418204 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java @@ -63,7 +63,7 @@ public abstract class AbstractOAuth2ClientMapper { private final Lock userCreationLock = new ReentrantLock(); - protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, boolean allowUserCreation) { + protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, boolean allowUserCreation, boolean activateUser) { UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail()); User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, oauth2User.getEmail()); @@ -93,8 +93,10 @@ public abstract class AbstractOAuth2ClientMapper { user.setFirstName(oauth2User.getFirstName()); user.setLastName(oauth2User.getLastName()); user = userService.saveUser(user); - UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); - userService.activateUserCredentials(user.getTenantId(), userCredentials.getActivateToken(), passwordEncoder.encode("")); + if (activateUser) { + UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); + userService.activateUserCredentials(user.getTenantId(), userCredentials.getActivateToken(), passwordEncoder.encode("")); + } } } catch (Exception e) { log.error("Can't get or create security user from oauth2 user", e); diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java index 1d44a772aa..c6b6aeaae3 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java @@ -56,7 +56,8 @@ public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); oauth2User.setCustomerName(customerName); } - return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.getBasic().isAllowUserCreation()); + + return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); } private String getTenantName(Map attributes, OAuth2ClientMapperConfig config) { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java index 832a1cd39b..0fb4563987 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java @@ -38,7 +38,7 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme @Override public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig config) { OAuth2User oauth2User = getOAuth2User(token, config.getCustom()); - return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.getBasic().isAllowUserCreation()); + return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); } private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig.CustomOAuth2ClientMapperConfig custom) { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java index be8f7ca7c2..8702661196 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java @@ -27,6 +27,7 @@ import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtToken; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; +import org.thingsboard.server.utils.MiscUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -65,6 +66,7 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); - getRedirectStrategy().sendRedirect(request, response, "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); + String baseUrl = MiscUtils.constructBaseUrl(request); + getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); } } \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java b/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java index bec28a3bdb..ed13ca603d 100644 --- a/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java +++ b/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java @@ -18,8 +18,8 @@ package org.thingsboard.server.utils; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; +import javax.servlet.http.HttpServletRequest; import java.nio.charset.Charset; -import java.util.Random; /** @@ -47,4 +47,36 @@ public class MiscUtils { throw new IllegalArgumentException("Can't find hash function with name " + name); } } + + public static String constructBaseUrl(HttpServletRequest request) { + String scheme = request.getScheme(); + + String forwardedProto = request.getHeader("x-forwarded-proto"); + if (forwardedProto != null) { + scheme = forwardedProto; + } + + int serverPort = request.getServerPort(); + if (request.getHeader("x-forwarded-port") != null) { + try { + serverPort = request.getIntHeader("x-forwarded-port"); + } catch (NumberFormatException e) { + } + } else if (forwardedProto != null) { + switch (forwardedProto) { + case "http": + serverPort = 80; + break; + case "https": + serverPort = 443; + break; + } + } + + String baseUrl = String.format("%s://%s:%d", + scheme, + request.getServerName(), + serverPort); + return baseUrl; + } } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 8010987a43..aa1d03d92c 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -127,11 +127,13 @@ security: userInfoUri: "${SECURITY_OAUTH2_DEFAULT_USER_INFO_URI:}" userNameAttributeName: "${SECURITY_OAUTH2_DEFAULT_USER_NAME_ATTRIBUTE_NAME:email}" mapperConfig: + # Allows to create user if it not exists + allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ALLOW_USER_CREATION:true}" + # Allows user to setup ThingsBoard internal password and login over default Login window + activateUser: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ACTIVATE_USER:false}" # Mapper type of converter from external user into internal - 'basic' or 'custom' type: "${SECURITY_OAUTH2_DEFAULT_MAPPER_TYPE:basic}" basic: - # Allows to create user if it not exists - allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALLOW_USER_CREATION:true}" # Key from attributes of external user object to use as email emailAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_EMAIL_ATTRIBUTE_KEY:email}" firstNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_FIRST_NAME_ATTRIBUTE_KEY:}" diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientMapperConfig.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientMapperConfig.java index 695bb0aa0e..47f3746980 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientMapperConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientMapperConfig.java @@ -20,13 +20,14 @@ import lombok.Data; @Data public class OAuth2ClientMapperConfig { + private boolean allowUserCreation; + private boolean activateUser; private String type; private BasicOAuth2ClientMapperConfig basic; private CustomOAuth2ClientMapperConfig custom; @Data public static class BasicOAuth2ClientMapperConfig { - private boolean allowUserCreation; private String emailAttributeKey; private String firstNameAttributeKey; private String lastNameAttributeKey; From d9bfd829260df7e313e92472e83a4f87e95d93b9 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 6 May 2020 20:04:09 +0300 Subject: [PATCH 4/4] Introduce OAuth failure handling --- .../ThingsboardSecurityConfiguration.java | 11 ++++- .../Oauth2AuthenticationFailureHandler.java | 43 +++++++++++++++++++ ...RestAwareAuthenticationFailureHandler.java | 2 +- ui/src/app/api/user.service.js | 17 +++++++- ui/src/app/locale/locale.constant-en_US.json | 3 +- 5 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 8a21fd229f..683345fe7f 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -79,11 +79,18 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt @Qualifier("oauth2AuthenticationSuccessHandler") private AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler; + @Autowired(required = false) + @Qualifier("oauth2AuthenticationFailureHandler") + private AuthenticationFailureHandler oauth2AuthenticationFailureHandler; + @Autowired @Qualifier("defaultAuthenticationSuccessHandler") private AuthenticationSuccessHandler successHandler; - @Autowired private AuthenticationFailureHandler failureHandler; + @Autowired + @Qualifier("defaultAuthenticationFailureHandler") + private AuthenticationFailureHandler failureHandler; + @Autowired private RestAuthenticationProvider restAuthenticationProvider; @Autowired private JwtAuthenticationProvider jwtAuthenticationProvider; @Autowired private RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider; @@ -205,7 +212,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt .loginPage("/oauth2Login") .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl()) .successHandler(oauth2AuthenticationSuccessHandler) - .failureHandler(failureHandler); + .failureHandler(oauth2AuthenticationFailureHandler); } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java new file mode 100644 index 0000000000..653be85f72 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java @@ -0,0 +1,43 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.security.auth.oauth2; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; +import org.thingsboard.server.utils.MiscUtils; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +@Component(value = "oauth2AuthenticationFailureHandler") +@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") +public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, + HttpServletResponse response, AuthenticationException exception) + throws IOException, ServletException { + String baseUrl = MiscUtils.constructBaseUrl(request); + getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" + + URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8.toString())); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java index 726ee76a2d..38486e9a48 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java @@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -@Component +@Component(value = "defaultAuthenticationFailureHandler") public class RestAwareAuthenticationFailureHandler implements AuthenticationFailureHandler { private final ThingsboardErrorResponseHandler errorResponseHandler; diff --git a/ui/src/app/api/user.service.js b/ui/src/app/api/user.service.js index 9ac8270403..b84bcf8428 100644 --- a/ui/src/app/api/user.service.js +++ b/ui/src/app/api/user.service.js @@ -22,7 +22,7 @@ export default angular.module('thingsboard.api.user', [thingsboardApiLogin, .name; /*@ngInject*/ -function UserService($http, $q, $rootScope, adminService, dashboardService, timeService, loginService, toast, store, jwtHelper, $translate, $state, $location) { +function UserService($http, $q, $rootScope, adminService, dashboardService, timeService, loginService, toast, store, jwtHelper, $translate, $state, $location, $mdDialog) { var currentUser = null, currentUserDetails = null, lastPublicDashboardId = null, @@ -406,6 +406,10 @@ function UserService($http, $q, $rootScope, adminService, dashboardService, time }, function fail() { deferred.reject(); }); + } else if (locationSearch.loginError) { + showLoginErrorDialog(locationSearch.loginError); + $location.search('loginError', null); + deferred.reject(); } else { procceedJwtTokenValidate(); } @@ -415,6 +419,17 @@ function UserService($http, $q, $rootScope, adminService, dashboardService, time return deferred.promise; } + function showLoginErrorDialog(loginError) { + $translate(['login.error', + 'action.close']).then(function (translations) { + var alert = $mdDialog.alert() + .title(translations['login.error']) + .htmlContent(loginError) + .ok(translations['action.close']); + $mdDialog.show(alert); + }); + } + function loadIsUserTokenAccessEnabled() { var deferred = $q.defer(); if (currentUser.authority === 'SYS_ADMIN' || currentUser.authority === 'TENANT_ADMIN') { diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 6693875edf..5a8a588446 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -1334,7 +1334,8 @@ "password-link-sent-message": "Password reset link was successfully sent!", "email": "Email", "login-with": "Login with {{name}}", - "or": "or" + "or": "or", + "error": "Login error" }, "position": { "top": "Top",