committed by
Andrew Shvayka
9 changed files with 295 additions and 2 deletions
@ -0,0 +1,81 @@ |
|||
/** |
|||
* 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.config; |
|||
|
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.security.oauth2.client.registration.ClientRegistration; |
|||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; |
|||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; |
|||
import org.springframework.security.oauth2.core.AuthorizationGrantType; |
|||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod; |
|||
|
|||
import java.util.Collections; |
|||
|
|||
@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") |
|||
@Configuration |
|||
public class ThingsboardOAuth2Configuration { |
|||
|
|||
@Value("${security.oauth2.registrationId}") |
|||
private String registrationId; |
|||
@Value("${security.oauth2.userNameAttributeName}") |
|||
private String userNameAttributeName; |
|||
|
|||
@Value("${security.oauth2.client.clientId}") |
|||
private String clientId; |
|||
@Value("${security.oauth2.client.clientName}") |
|||
private String clientName; |
|||
@Value("${security.oauth2.client.clientSecret}") |
|||
private String clientSecret; |
|||
@Value("${security.oauth2.client.accessTokenUri}") |
|||
private String accessTokenUri; |
|||
@Value("${security.oauth2.client.authorizationUri}") |
|||
private String authorizationUri; |
|||
@Value("${security.oauth2.client.redirectUriTemplate}") |
|||
private String redirectUriTemplate; |
|||
@Value("${security.oauth2.client.scope}") |
|||
private String scope; |
|||
@Value("${security.oauth2.client.jwkSetUri}") |
|||
private String jwkSetUri; |
|||
@Value("${security.oauth2.client.authorizationGrantType}") |
|||
private String authorizationGrantType; |
|||
@Value("${security.oauth2.client.clientAuthenticationMethod}") |
|||
private String clientAuthenticationMethod; |
|||
|
|||
@Value("${security.oauth2.resource.userInfoUri}") |
|||
private String userInfoUri; |
|||
|
|||
@Bean |
|||
public ClientRegistrationRepository clientRegistrationRepository() { |
|||
ClientRegistration registration = ClientRegistration.withRegistrationId(registrationId) |
|||
.clientId(clientId) |
|||
.authorizationUri(authorizationUri) |
|||
.clientSecret(clientSecret) |
|||
.tokenUri(accessTokenUri) |
|||
.redirectUriTemplate(redirectUriTemplate) |
|||
.scope(scope.split(",")) |
|||
.clientName(clientName) |
|||
.authorizationGrantType(new AuthorizationGrantType(authorizationGrantType)) |
|||
.userInfoUri(userInfoUri) |
|||
.userNameAttributeName(userNameAttributeName) |
|||
.jwkSetUri(jwkSetUri) |
|||
.clientAuthenticationMethod(new ClientAuthenticationMethod(clientAuthenticationMethod)) |
|||
.build(); |
|||
return new InMemoryClientRegistrationRepository(Collections.singletonList(registration)); |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
/** |
|||
* 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.oauth; |
|||
|
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.security.authentication.InsufficientAuthenticationException; |
|||
import org.springframework.security.authentication.LockedException; |
|||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
|||
import org.springframework.security.core.Authentication; |
|||
import org.springframework.security.core.userdetails.UsernameNotFoundException; |
|||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.UserCredentials; |
|||
import org.thingsboard.server.dao.user.UserService; |
|||
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
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 javax.servlet.ServletException; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Component(value="oauth2AuthenticationSuccessHandler") |
|||
@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") |
|||
public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { |
|||
|
|||
private final ObjectMapper mapper; |
|||
private final JwtTokenFactory tokenFactory; |
|||
private final RefreshTokenRepository refreshTokenRepository; |
|||
private final SystemSecurityService systemSecurityService; |
|||
private final UserService userService; |
|||
|
|||
@Autowired |
|||
public Oauth2AuthenticationSuccessHandler(final ObjectMapper mapper, |
|||
final JwtTokenFactory tokenFactory, |
|||
final RefreshTokenRepository refreshTokenRepository, |
|||
final UserService userService, |
|||
final SystemSecurityService systemSecurityService) { |
|||
this.mapper = mapper; |
|||
this.tokenFactory = tokenFactory; |
|||
this.refreshTokenRepository = refreshTokenRepository; |
|||
this.userService = userService; |
|||
this.systemSecurityService = systemSecurityService; |
|||
} |
|||
|
|||
@Override |
|||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { |
|||
Object object = authentication.getPrincipal(); |
|||
|
|||
System.out.println(object); |
|||
|
|||
// active user check
|
|||
|
|||
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, "tenant@thingsboard.org"); |
|||
SecurityUser securityUser = (SecurityUser) authenticateByUsernameAndPassword(principal,"tenant@thingsboard.org", "tenant").getPrincipal(); |
|||
|
|||
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); |
|||
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); |
|||
|
|||
Map<String, String> tokenMap = new HashMap<String, String>(); |
|||
tokenMap.put("token", accessToken.getToken()); |
|||
tokenMap.put("refreshToken", refreshToken.getToken()); |
|||
|
|||
// response.setStatus(HttpStatus.OK.value());
|
|||
// response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|||
// mapper.writeValue(response.getWriter(), tokenMap);
|
|||
|
|||
request.setAttribute("token", accessToken.getToken()); |
|||
response.addHeader("token", accessToken.getToken()); |
|||
|
|||
getRedirectStrategy().sendRedirect(request, response, "http://localhost:4200/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); |
|||
} |
|||
|
|||
private Authentication authenticateByUsernameAndPassword(UserPrincipal userPrincipal, String username, String password) { |
|||
User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, username); |
|||
if (user == null) { |
|||
throw new UsernameNotFoundException("User not found: " + username); |
|||
} |
|||
|
|||
try { |
|||
|
|||
UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, user.getId()); |
|||
if (userCredentials == null) { |
|||
throw new UsernameNotFoundException("User credentials not found"); |
|||
} |
|||
|
|||
try { |
|||
systemSecurityService.validateUserCredentials(user.getTenantId(), userCredentials, username, password); |
|||
} catch (LockedException e) { |
|||
throw e; |
|||
} |
|||
|
|||
if (user.getAuthority() == null) |
|||
throw new InsufficientAuthenticationException("User has no authority assigned"); |
|||
|
|||
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal); |
|||
return new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities()); |
|||
} catch (Exception e) { |
|||
throw e; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue