Introduce OAuth failure handling

This commit is contained in:
Igor Kulikov 2020-05-06 20:04:09 +03:00
parent 9b18c408b2
commit d9bfd82926
5 changed files with 71 additions and 5 deletions

View File

@ -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);
}
}

View File

@ -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()));
}
}

View File

@ -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;

View File

@ -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') {

View File

@ -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",