Browse Source

Added support for multiple domains in OAuth2 config

pull/3557/head
vzikratyi 6 years ago
parent
commit
c7e236499e
  1. 18
      application/src/main/data/upgrade/3.1.1/schema_update.sql
  2. 257
      application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java
  3. 6
      application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
  4. 2
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  5. 61
      application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java
  6. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java
  7. 2
      application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java
  9. 70
      application/src/main/java/org/thingsboard/server/utils/WebUtils.java
  10. 15
      common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Service.java
  11. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  12. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  13. 39
      common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationInfoId.java
  14. 6
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ClientRegistrationDto.java
  15. 9
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/DomainInfo.java
  16. 39
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ExtendedOAuth2ClientRegistrationInfo.java
  17. 56
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistration.java
  18. 76
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationInfo.java
  19. 6
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsDomainParams.java
  20. 8
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsParams.java
  21. 20
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/SchemeType.java
  22. 6
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  23. 231
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java
  24. 48
      dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java
  25. 162
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java
  26. 51
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java
  27. 12
      dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
  28. 9
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java
  29. 34
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java
  30. 89
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java
  31. 131
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java
  32. 25
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java
  33. 76
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java
  34. 41
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java
  35. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java
  36. 14
      dao/src/main/resources/sql/schema-entities-hsql.sql
  37. 14
      dao/src/main/resources/sql/schema-entities.sql
  38. 484
      dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java

18
application/src/main/data/upgrade/3.1.1/schema_update.sql

@ -14,19 +14,17 @@
-- limitations under the License.
--
DROP TABLE IF EXISTS oauth2_client_registration;
DROP TABLE IF EXISTS oauth2_client_registration_info;
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
enabled boolean,
created_time bigint NOT NULL,
additional_info varchar,
domain_name varchar(255),
client_id varchar(255),
client_secret varchar(255),
authorization_uri varchar(255),
token_uri varchar(255),
redirect_uri_template varchar(255),
scope varchar(255),
user_info_uri varchar(255),
user_name_attribute_name varchar(255),
@ -51,6 +49,16 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
custom_send_token boolean
);
DROP TABLE IF EXISTS oauth2_client_registration;
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
created_time bigint NOT NULL,
domain_name varchar(255),
domain_scheme varchar(31),
client_registration_info_id uuid
);
DROP TABLE IF EXISTS oauth2_client_registration_template;
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (

257
application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java

@ -0,0 +1,257 @@
/**
* 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
import org.springframework.security.crypto.keygen.StringKeyGenerator;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
import org.thingsboard.server.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
public static final String DEFAULT_LOGIN_PROCESSING_URI = "/login/oauth2/code/";
private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
private static final char PATH_DELIMITER = '/';
private final AntPathRequestMatcher authorizationRequestMatcher = new AntPathRequestMatcher(
DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}");
private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder());
private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Autowired(required = false)
private OAuth2Configuration oauth2Configuration;
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
String registrationId = this.resolveRegistrationId(request);
String redirectUriAction = getAction(request, "login");
return resolve(request, registrationId, redirectUriAction);
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId) {
if (registrationId == null) {
return null;
}
String redirectUriAction = getAction(request, "authorize");
return resolve(request, registrationId, redirectUriAction);
}
private String getAction(HttpServletRequest request, String defaultAction) {
String action = request.getParameter("action");
if (action == null) {
return defaultAction;
}
return action;
}
private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) {
if (registrationId == null) {
return null;
}
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
if (clientRegistration == null) {
throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId);
}
Map<String, Object> attributes = new HashMap<>();
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId());
OAuth2AuthorizationRequest.Builder builder;
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
builder = OAuth2AuthorizationRequest.authorizationCode();
Map<String, Object> additionalParameters = new HashMap<>();
if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) &&
clientRegistration.getScopes().contains(OidcScopes.OPENID)) {
// Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
// scope
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
addNonceParameters(attributes, additionalParameters);
}
if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())) {
addPkceParameters(attributes, additionalParameters);
}
builder.additionalParameters(additionalParameters);
} else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
builder = OAuth2AuthorizationRequest.implicit();
} else {
throw new IllegalArgumentException("Invalid Authorization Grant Type (" +
clientRegistration.getAuthorizationGrantType().getValue() +
") for Client Registration with Id: " + clientRegistration.getRegistrationId());
}
String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction);
return builder
.clientId(clientRegistration.getClientId())
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
.redirectUri(redirectUriStr)
.scopes(clientRegistration.getScopes())
.state(this.stateGenerator.generateKey())
.attributes(attributes)
.build();
}
private String resolveRegistrationId(HttpServletRequest request) {
if (this.authorizationRequestMatcher.matches(request)) {
return this.authorizationRequestMatcher
.matcher(request).getVariables().get(REGISTRATION_ID_URI_VARIABLE_NAME);
}
return null;
}
/**
* Expands the {@link ClientRegistration#getRedirectUriTemplate()} with following provided variables:<br/>
* - baseUrl (e.g. https://localhost/app) <br/>
* - baseScheme (e.g. https) <br/>
* - baseHost (e.g. localhost) <br/>
* - basePort (e.g. :8080) <br/>
* - basePath (e.g. /app) <br/>
* - registrationId (e.g. google) <br/>
* - action (e.g. login) <br/>
* <p/>
* Null variables are provided as empty strings.
* <p/>
* Default redirectUriTemplate is: {@link org.springframework.security.config.oauth2.client}.CommonOAuth2Provider#DEFAULT_REDIRECT_URL
*
* @return expanded URI
*/
private String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration, String action) {
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("registrationId", clientRegistration.getRegistrationId());
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
.replacePath(request.getContextPath())
.replaceQuery(null)
.fragment(null)
.build();
String scheme = uriComponents.getScheme();
uriVariables.put("baseScheme", scheme == null ? "" : scheme);
String host = uriComponents.getHost();
uriVariables.put("baseHost", host == null ? "" : host);
// following logic is based on HierarchicalUriComponents#toUriString()
int port = uriComponents.getPort();
uriVariables.put("basePort", port == -1 ? "" : ":" + port);
String path = uriComponents.getPath();
if (StringUtils.hasLength(path)) {
if (path.charAt(0) != PATH_DELIMITER) {
path = PATH_DELIMITER + path;
}
}
uriVariables.put("basePath", path == null ? "" : path);
uriVariables.put("baseUrl", uriComponents.toUriString());
uriVariables.put("action", action == null ? "" : action);
return UriComponentsBuilder.fromUriString(getRedirectUri(request))
.buildAndExpand(uriVariables)
.toUriString();
}
private String getRedirectUri(HttpServletRequest request) {
String loginProcessingUri = oauth2Configuration != null ? oauth2Configuration.getLoginProcessingUrl() : DEFAULT_LOGIN_PROCESSING_URI;
String scheme = WebUtils.getScheme(request);
String host = WebUtils.getHost(request);
String port = WebUtils.getPort(request);
log.trace("Scheme - {}, host - {}, port - {}.", scheme, host, port);
String requestHost = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
return requestHost + loginProcessingUri;
}
/**
* Creates nonce and its hash for use in OpenID Connect 1.0 Authentication Requests.
*
* @param attributes where the {@link OidcParameterNames#NONCE} is stored for the authentication request
* @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is added for the authentication request
*
* @since 5.2
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest">3.1.2.1. Authentication Request</a>
*/
private void addNonceParameters(Map<String, Object> attributes, Map<String, Object> additionalParameters) {
try {
String nonce = this.secureKeyGenerator.generateKey();
String nonceHash = createHash(nonce);
attributes.put(OidcParameterNames.NONCE, nonce);
additionalParameters.put(OidcParameterNames.NONCE, nonceHash);
} catch (NoSuchAlgorithmException e) { }
}
/**
* Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization and Access Token Requests
*
* @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the token request
* @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, usually,
* {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in the authorization request.
*
* @since 5.2
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-1.1">1.1. Protocol Flow</a>
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-4.1">4.1. Client Creates a Code Verifier</a>
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-4.2">4.2. Client Creates the Code Challenge</a>
*/
private void addPkceParameters(Map<String, Object> attributes, Map<String, Object> additionalParameters) {
String codeVerifier = this.secureKeyGenerator.generateKey();
attributes.put(PkceParameterNames.CODE_VERIFIER, codeVerifier);
try {
String codeChallenge = createHash(codeVerifier);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
} catch (NoSuchAlgorithmException e) {
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier);
}
}
private static String createHash(String value) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(value.getBytes(StandardCharsets.US_ASCII));
return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
}
}

6
application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java

@ -32,6 +32,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@ -175,6 +176,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**");
}
@Autowired
private OAuth2AuthorizationRequestResolver oAuth2AuthorizationRequestResolver;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl().and().frameOptions().disable()
@ -209,6 +213,8 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
.addFilterAfter(rateLimitProcessingFilter, UsernamePasswordAuthenticationFilter.class);
if (oauth2Configuration != null) {
http.oauth2Login()
.authorizationEndpoint().authorizationRequestResolver(oAuth2AuthorizationRequestResolver)
.and()
.loginPage("/oauth2Login")
.loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl())
.successHandler(oauth2AuthenticationSuccessHandler)

2
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -373,7 +373,7 @@ public abstract class BaseController {
case WIDGET_TYPE:
checkWidgetTypeId(new WidgetTypeId(entityId.getId()), operation);
return;
case OAUTH2_CLIENT_REGISTRATION:
case OAUTH2_CLIENT_REGISTRATION_INFO:
case OAUTH2_CLIENT_REGISTRATION_TEMPLATE:
return;
default:

61
application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java

@ -19,13 +19,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientsDomainParams;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.servlet.http.HttpServletRequest;
@ -36,14 +33,11 @@ import java.util.List;
@RequestMapping("/api")
@Slf4j
public class OAuth2Controller extends BaseController {
private static final String CLIENT_REGISTRATION_ID = "clientRegistrationId";
private static final String DOMAIN = "domain";
@RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST)
@ResponseBody
public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request) throws ThingsboardException {
try {
return oAuth2Service.getOAuth2Clients(request.getServerName());
return oAuth2Service.getOAuth2Clients(request.getScheme(), request.getServerName());
} catch (Exception e) {
throw handleException(e);
}
@ -65,56 +59,9 @@ public class OAuth2Controller extends BaseController {
@ResponseStatus(value = HttpStatus.OK)
public OAuth2ClientsParams saveOAuth2Params(@RequestBody OAuth2ClientsParams oauth2Params) throws ThingsboardException {
try {
return oAuth2Service.saveOAuth2Params(oauth2Params);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@RequestMapping(value = "/oauth2/config/{clientRegistrationId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteClientRegistration(@PathVariable(CLIENT_REGISTRATION_ID) String strClientRegistrationId) throws ThingsboardException {
checkParameter(CLIENT_REGISTRATION_ID, strClientRegistrationId);
try {
OAuth2ClientRegistrationId clientRegistrationId = new OAuth2ClientRegistrationId(toUUID(strClientRegistrationId));
oAuth2Service.deleteClientRegistrationById(clientRegistrationId);
logEntityAction(clientRegistrationId,
null,
null,
ActionType.DELETED, null, strClientRegistrationId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.OAUTH2_CLIENT_REGISTRATION),
null,
null,
ActionType.DELETED, e, strClientRegistrationId);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@RequestMapping(value = "/oauth2/config/domain/{domain}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteClientRegistrationForDomain(@PathVariable(DOMAIN) String domain) throws ThingsboardException {
checkParameter(DOMAIN, domain);
try {
oAuth2Service.deleteClientRegistrationsByDomain(domain);
logEntityAction(emptyId(EntityType.OAUTH2_CLIENT_REGISTRATION), null,
null,
ActionType.DELETED, null, domain);
oAuth2Service.saveOAuth2Params(oauth2Params);
return oAuth2Service.findOAuth2Params();
} catch (Exception e) {
logEntityAction(emptyId(EntityType.OAUTH2_CLIENT_REGISTRATION),
null,
null,
ActionType.DELETED, e, domain);
throw handleException(e);
}
}

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java

@ -22,7 +22,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.dao.oauth2.OAuth2Service;
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
import org.thingsboard.server.service.security.model.SecurityUser;
@ -68,7 +68,7 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
try {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
OAuth2ClientRegistration clientRegistration = oAuth2Service.findClientRegistration(UUID.fromString(token.getAuthorizedClientRegistrationId()));
OAuth2ClientRegistrationInfo clientRegistration = oAuth2Service.findClientRegistrationInfo(UUID.fromString(token.getAuthorizedClientRegistrationId()));
OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient(
token.getAuthorizedClientRegistrationId(),
token.getPrincipal().getName());

2
application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java

@ -32,7 +32,7 @@ public enum Resource {
USER(EntityType.USER),
WIDGETS_BUNDLE(EntityType.WIDGETS_BUNDLE),
WIDGET_TYPE(EntityType.WIDGET_TYPE),
OAUTH2_CONFIGURATION(EntityType.OAUTH2_CLIENT_REGISTRATION),
OAUTH2_CONFIGURATION_INFO(EntityType.OAUTH2_CLIENT_REGISTRATION_INFO),
OAUTH2_CONFIGURATION_TEMPLATE(EntityType.OAUTH2_CLIENT_REGISTRATION_TEMPLATE),
;

2
application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java

@ -35,7 +35,7 @@ public class SysAdminPermissions extends AbstractPermissions {
put(Resource.USER, userPermissionChecker);
put(Resource.WIDGETS_BUNDLE, systemEntityPermissionChecker);
put(Resource.WIDGET_TYPE, systemEntityPermissionChecker);
put(Resource.OAUTH2_CONFIGURATION, PermissionChecker.allowAllPermissionChecker);
put(Resource.OAUTH2_CONFIGURATION_INFO, PermissionChecker.allowAllPermissionChecker);
put(Resource.OAUTH2_CONFIGURATION_TEMPLATE, PermissionChecker.allowAllPermissionChecker);
}

70
application/src/main/java/org/thingsboard/server/utils/WebUtils.java

@ -0,0 +1,70 @@
/**
* 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.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class WebUtils {
private static final String X_FORWARDED_HOST_HEADER_KEY = "x-forwarded-host";
private static final String X_FORWARDED_PORT_HEADER_KEY = "x-forwarded-port";
private static final String X_FORWARDED_PROTO_HEADER_KEY = "x-forwarded-proto";
public static String getHost(HttpServletRequest request) {
String forwardedHost = request.getHeader(X_FORWARDED_HOST_HEADER_KEY);
log.trace("Forwarded host - {}.", forwardedHost);
if (!StringUtils.isEmpty(forwardedHost)) {
if (forwardedHost.contains(":")) {
return forwardedHost.substring(0, forwardedHost.indexOf(":"));
} else {
return forwardedHost;
}
} else {
return request.getServerName();
}
}
public static String getScheme(HttpServletRequest request) {
String forwardedProto = request.getHeader(X_FORWARDED_PROTO_HEADER_KEY);
log.trace("Forwarded proto - {}.", forwardedProto);
if (!StringUtils.isEmpty(forwardedProto)) {
return forwardedProto;
} else {
return request.getServerName();
}
}
public static String getPort(HttpServletRequest request) {
String forwardedPort = request.getHeader(X_FORWARDED_PORT_HEADER_KEY);
log.trace("Forwarded port - {}.", forwardedPort);
if (!StringUtils.isEmpty(forwardedPort)) {
return forwardedPort;
}
String forwardedHost = request.getHeader(X_FORWARDED_HOST_HEADER_KEY);
if (!StringUtils.isEmpty(forwardedHost)) {
if (forwardedHost.contains(":")) {
return forwardedHost.substring(forwardedHost.indexOf(":"));
} else {
return "HTTP".equals(getScheme(request).toUpperCase()) ?
"80" : "443";
}
}
return Integer.toString(request.getServerPort());
}
}

15
common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Service.java

@ -15,26 +15,21 @@
*/
package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams;
import java.util.List;
import java.util.UUID;
public interface OAuth2Service {
List<OAuth2ClientInfo> getOAuth2Clients(String domainName);
List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName);
OAuth2ClientsParams saveOAuth2Params(OAuth2ClientsParams oauth2Params);
void saveOAuth2Params(OAuth2ClientsParams oauth2Params);
OAuth2ClientsParams findOAuth2Params();
OAuth2ClientRegistration findClientRegistration(UUID id);
OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id);
List<OAuth2ClientRegistration> findAllClientRegistrations();
void deleteClientRegistrationById(OAuth2ClientRegistrationId id);
void deleteClientRegistrationsByDomain(String domain);
List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos();
}

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java

@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
* @author Andrew Shvayka
*/
public enum EntityType {
TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, OAUTH2_CLIENT_REGISTRATION, OAUTH2_CLIENT_REGISTRATION_TEMPLATE
TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, OAUTH2_CLIENT_REGISTRATION, OAUTH2_CLIENT_REGISTRATION_INFO, OAUTH2_CLIENT_REGISTRATION_TEMPLATE
}

4
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -62,8 +62,8 @@ public class EntityIdFactory {
return new WidgetsBundleId(uuid);
case WIDGET_TYPE:
return new WidgetTypeId(uuid);
case OAUTH2_CLIENT_REGISTRATION:
return new OAuth2ClientRegistrationId(uuid);
case OAUTH2_CLIENT_REGISTRATION_INFO:
return new OAuth2ClientRegistrationInfoId(uuid);
case OAUTH2_CLIENT_REGISTRATION_TEMPLATE:
return new OAuth2ClientRegistrationTemplateId(uuid);
}

39
common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationInfoId.java

@ -0,0 +1,39 @@
/**
* 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.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
public class OAuth2ClientRegistrationInfoId extends UUIDBased implements EntityId {
@JsonCreator
public OAuth2ClientRegistrationInfoId(@JsonProperty("id") UUID id) {
super(id);
}
public static OAuth2ClientRegistrationInfoId fromString(String clientRegistrationInfoId) {
return new OAuth2ClientRegistrationInfoId(UUID.fromString(clientRegistrationInfoId));
}
@Override
public EntityType getEntityType() {
return EntityType.OAUTH2_CLIENT_REGISTRATION_INFO;
}
}

6
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ClientRegistrationDto.java

@ -15,11 +15,9 @@
*/
package org.thingsboard.server.common.data.oauth2;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.*;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
import java.util.List;
@ -30,8 +28,6 @@ import java.util.List;
@AllArgsConstructor
@Builder
public class ClientRegistrationDto {
private OAuth2ClientRegistrationId id;
private long createdTime;
private OAuth2MapperConfig mapperConfig;
private String clientId;
private String clientSecret;

9
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ExtendedOAuth2ClientRegistration.java → common/data/src/main/java/org/thingsboard/server/common/data/oauth2/DomainInfo.java

@ -17,12 +17,13 @@ package org.thingsboard.server.common.data.oauth2;
import lombok.*;
@EqualsAndHashCode
@Data
@ToString
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class ExtendedOAuth2ClientRegistration {
private String redirectUriTemplate;
private OAuth2ClientRegistration clientRegistration;
@Builder
public class DomainInfo {
private SchemeType scheme;
private String name;
}

39
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ExtendedOAuth2ClientRegistrationInfo.java

@ -0,0 +1,39 @@
/**
* 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.common.data.oauth2;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ExtendedOAuth2ClientRegistrationInfo extends OAuth2ClientRegistrationInfo {
private String domainName;
private SchemeType domainScheme;
public ExtendedOAuth2ClientRegistrationInfo() {
super();
}
public ExtendedOAuth2ClientRegistrationInfo(OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo,
SchemeType domainScheme,
String domainName) {
super(oAuth2ClientRegistrationInfo);
this.domainScheme = domainScheme;
this.domainName = domainName;
}
}

56
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistration.java

@ -15,68 +15,28 @@
*/
package org.thingsboard.server.common.data.oauth2;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.List;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString(exclude = {"clientSecret"})
@ToString
@NoArgsConstructor
public class OAuth2ClientRegistration extends SearchTextBasedWithAdditionalInfo<OAuth2ClientRegistrationId> implements HasName {
public class OAuth2ClientRegistration extends BaseData<OAuth2ClientRegistrationId> {
private boolean enabled;
private OAuth2ClientRegistrationInfoId clientRegistrationId;
private String domainName;
private String redirectUriTemplate;
private OAuth2MapperConfig mapperConfig;
private String clientId;
private String clientSecret;
private String authorizationUri;
private String accessTokenUri;
private List<String> scope;
private String userInfoUri;
private String userNameAttributeName;
private String jwkSetUri;
private String clientAuthenticationMethod;
private String loginButtonLabel;
private String loginButtonIcon;
private SchemeType domainScheme;
public OAuth2ClientRegistration(OAuth2ClientRegistration clientRegistration) {
super(clientRegistration);
this.enabled = clientRegistration.enabled;
this.clientRegistrationId = clientRegistration.clientRegistrationId;
this.domainName = clientRegistration.domainName;
this.redirectUriTemplate = clientRegistration.redirectUriTemplate;
this.mapperConfig = clientRegistration.mapperConfig;
this.clientId = clientRegistration.clientId;
this.clientSecret = clientRegistration.clientSecret;
this.authorizationUri = clientRegistration.authorizationUri;
this.accessTokenUri = clientRegistration.accessTokenUri;
this.scope = clientRegistration.scope;
this.userInfoUri = clientRegistration.userInfoUri;
this.userNameAttributeName = clientRegistration.userNameAttributeName;
this.jwkSetUri = clientRegistration.jwkSetUri;
this.clientAuthenticationMethod = clientRegistration.clientAuthenticationMethod;
this.loginButtonLabel = clientRegistration.loginButtonLabel;
this.loginButtonIcon = clientRegistration.loginButtonIcon;
}
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() {
return loginButtonLabel;
}
@Override
public String getSearchText() {
return getName();
this.domainScheme = clientRegistration.domainScheme;
}
}

76
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationInfo.java

@ -0,0 +1,76 @@
/**
* 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.common.data.oauth2;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString(exclude = {"clientSecret"})
@NoArgsConstructor
public class OAuth2ClientRegistrationInfo extends SearchTextBasedWithAdditionalInfo<OAuth2ClientRegistrationInfoId> implements HasName {
private boolean enabled;
private OAuth2MapperConfig mapperConfig;
private String clientId;
private String clientSecret;
private String authorizationUri;
private String accessTokenUri;
private List<String> scope;
private String userInfoUri;
private String userNameAttributeName;
private String jwkSetUri;
private String clientAuthenticationMethod;
private String loginButtonLabel;
private String loginButtonIcon;
public OAuth2ClientRegistrationInfo(OAuth2ClientRegistrationInfo clientRegistration) {
super(clientRegistration);
this.enabled = clientRegistration.enabled;
this.mapperConfig = clientRegistration.mapperConfig;
this.clientId = clientRegistration.clientId;
this.clientSecret = clientRegistration.clientSecret;
this.authorizationUri = clientRegistration.authorizationUri;
this.accessTokenUri = clientRegistration.accessTokenUri;
this.scope = clientRegistration.scope;
this.userInfoUri = clientRegistration.userInfoUri;
this.userNameAttributeName = clientRegistration.userNameAttributeName;
this.jwkSetUri = clientRegistration.jwkSetUri;
this.clientAuthenticationMethod = clientRegistration.clientAuthenticationMethod;
this.loginButtonLabel = clientRegistration.loginButtonLabel;
this.loginButtonIcon = clientRegistration.loginButtonIcon;
}
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() {
return loginButtonLabel;
}
@Override
public String getSearchText() {
return getName();
}
}

6
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsDomainParams.java

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.oauth2;
import lombok.*;
import java.util.List;
import java.util.Set;
@EqualsAndHashCode
@Data
@ -26,7 +27,6 @@ import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2ClientsDomainParams {
private String domainName;
private String redirectUriTemplate;
private List<ClientRegistrationDto> clientRegistrations;
private Set<DomainInfo> domainInfos;
private Set<ClientRegistrationDto> clientRegistrations;
}

8
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsParams.java

@ -16,11 +16,7 @@
package org.thingsboard.server.common.data.oauth2;
import lombok.*;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@EqualsAndHashCode
@Data
@ -30,5 +26,5 @@ import java.util.Objects;
@AllArgsConstructor
public class OAuth2ClientsParams {
private boolean enabled;
private List<OAuth2ClientsDomainParams> oAuth2DomainDtos;
private Set<OAuth2ClientsDomainParams> oAuth2DomainDtos;
}

20
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/SchemeType.java

@ -0,0 +1,20 @@
/**
* 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.common.data.oauth2;
public enum SchemeType {
HTTP, HTTPS, MIXED;
}

6
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -358,11 +358,15 @@ public class ModelConstants {
* OAuth2 client registration constants.
*/
public static final String OAUTH2_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String OAUTH2_ENABLED_PROPERTY = "enabled";
public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info";
public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration";
public static final String OAUTH2_CLIENT_REGISTRATION_TO_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_client_registration_to_domain";
public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template";
public static final String OAUTH2_ENABLED_PROPERTY = "enabled";
public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id";
public static final String OAUTH2_CLIENT_REGISTRATION_INFO_ID_PROPERTY = "client_registration_info_id";
public static final String OAUTH2_DOMAIN_NAME_PROPERTY = "domain_name";
public static final String OAUTH2_DOMAIN_SCHEME_PROPERTY = "domain_scheme";
public static final String OAUTH2_CLIENT_ID_PROPERTY = "client_id";
public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret";
public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri";

231
dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java

@ -0,0 +1,231 @@
/**
* 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.dao.model.sql;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.*;
import java.util.Arrays;
@Data
@EqualsAndHashCode(callSuper = true)
@TypeDef(name = "json", typeClass = JsonStringType.class)
@MappedSuperclass
public abstract class AbstractOAuth2ClientRegistrationInfoEntity<T extends OAuth2ClientRegistrationInfo> extends BaseSqlEntity<T> {
@Column(name = ModelConstants.OAUTH2_ENABLED_PROPERTY)
private Boolean enabled;
@Column(name = ModelConstants.OAUTH2_CLIENT_ID_PROPERTY)
private String clientId;
@Column(name = ModelConstants.OAUTH2_CLIENT_SECRET_PROPERTY)
private String clientSecret;
@Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY)
private String authorizationUri;
@Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY)
private String tokenUri;
@Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY)
private String scope;
@Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY)
private String userInfoUri;
@Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY)
private String userNameAttributeName;
@Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY)
private String jwkSetUri;
@Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY)
private String clientAuthenticationMethod;
@Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY)
private String loginButtonLabel;
@Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_ICON_PROPERTY)
private String loginButtonIcon;
@Column(name = ModelConstants.OAUTH2_ALLOW_USER_CREATION_PROPERTY)
private Boolean allowUserCreation;
@Column(name = ModelConstants.OAUTH2_ACTIVATE_USER_PROPERTY)
private Boolean activateUser;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY)
private MapperType type;
@Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY)
private String emailAttributeKey;
@Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY)
private String firstNameAttributeKey;
@Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY)
private String lastNameAttributeKey;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY)
private TenantNameStrategyType tenantNameStrategy;
@Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY)
private String tenantNamePattern;
@Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY)
private String customerNamePattern;
@Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY)
private String defaultDashboardName;
@Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY)
private Boolean alwaysFullScreen;
@Column(name = ModelConstants.OAUTH2_MAPPER_URL_PROPERTY)
private String url;
@Column(name = ModelConstants.OAUTH2_MAPPER_USERNAME_PROPERTY)
private String username;
@Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY)
private String password;
@Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY)
private Boolean sendToken;
@Type(type = "json")
@Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
public AbstractOAuth2ClientRegistrationInfoEntity() {
super();
}
public AbstractOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfo clientRegistrationInfo) {
if (clientRegistrationInfo.getId() != null) {
this.setUuid(clientRegistrationInfo.getId().getId());
}
this.createdTime = clientRegistrationInfo.getCreatedTime();
this.enabled = clientRegistrationInfo.isEnabled();
this.clientId = clientRegistrationInfo.getClientId();
this.clientSecret = clientRegistrationInfo.getClientSecret();
this.authorizationUri = clientRegistrationInfo.getAuthorizationUri();
this.tokenUri = clientRegistrationInfo.getAccessTokenUri();
this.scope = clientRegistrationInfo.getScope().stream().reduce((result, element) -> result + "," + element).orElse("");
this.userInfoUri = clientRegistrationInfo.getUserInfoUri();
this.userNameAttributeName = clientRegistrationInfo.getUserNameAttributeName();
this.jwkSetUri = clientRegistrationInfo.getJwkSetUri();
this.clientAuthenticationMethod = clientRegistrationInfo.getClientAuthenticationMethod();
this.loginButtonLabel = clientRegistrationInfo.getLoginButtonLabel();
this.loginButtonIcon = clientRegistrationInfo.getLoginButtonIcon();
this.additionalInfo = clientRegistrationInfo.getAdditionalInfo();
OAuth2MapperConfig mapperConfig = clientRegistrationInfo.getMapperConfig();
if (mapperConfig != null) {
this.allowUserCreation = mapperConfig.isAllowUserCreation();
this.activateUser = mapperConfig.isActivateUser();
this.type = mapperConfig.getType();
OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
if (basicConfig != null) {
this.emailAttributeKey = basicConfig.getEmailAttributeKey();
this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey();
this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey();
this.tenantNameStrategy = basicConfig.getTenantNameStrategy();
this.tenantNamePattern = basicConfig.getTenantNamePattern();
this.customerNamePattern = basicConfig.getCustomerNamePattern();
this.defaultDashboardName = basicConfig.getDefaultDashboardName();
this.alwaysFullScreen = basicConfig.isAlwaysFullScreen();
}
OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
if (customConfig != null) {
this.url = customConfig.getUrl();
this.username = customConfig.getUsername();
this.password = customConfig.getPassword();
this.sendToken = customConfig.isSendToken();
}
}
}
public AbstractOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity) {
this.setId(oAuth2ClientRegistrationInfoEntity.getId());
this.setCreatedTime(oAuth2ClientRegistrationInfoEntity.getCreatedTime());
this.enabled = oAuth2ClientRegistrationInfoEntity.getEnabled();
this.clientId = oAuth2ClientRegistrationInfoEntity.getClientId();
this.clientSecret = oAuth2ClientRegistrationInfoEntity.getClientSecret();
this.authorizationUri = oAuth2ClientRegistrationInfoEntity.getAuthorizationUri();
this.tokenUri = oAuth2ClientRegistrationInfoEntity.getTokenUri();
this.scope = oAuth2ClientRegistrationInfoEntity.getScope();
this.userInfoUri = oAuth2ClientRegistrationInfoEntity.getUserInfoUri();
this.userNameAttributeName = oAuth2ClientRegistrationInfoEntity.getUserNameAttributeName();
this.jwkSetUri = oAuth2ClientRegistrationInfoEntity.getJwkSetUri();
this.clientAuthenticationMethod = oAuth2ClientRegistrationInfoEntity.getClientAuthenticationMethod();
this.loginButtonLabel = oAuth2ClientRegistrationInfoEntity.getLoginButtonLabel();
this.loginButtonIcon = oAuth2ClientRegistrationInfoEntity.getLoginButtonIcon();
this.additionalInfo = oAuth2ClientRegistrationInfoEntity.getAdditionalInfo();
this.allowUserCreation = oAuth2ClientRegistrationInfoEntity.getAllowUserCreation();
this.activateUser = oAuth2ClientRegistrationInfoEntity.getActivateUser();
this.type = oAuth2ClientRegistrationInfoEntity.getType();
this.emailAttributeKey = oAuth2ClientRegistrationInfoEntity.getEmailAttributeKey();
this.firstNameAttributeKey = oAuth2ClientRegistrationInfoEntity.getFirstNameAttributeKey();
this.lastNameAttributeKey = oAuth2ClientRegistrationInfoEntity.getLastNameAttributeKey();
this.tenantNameStrategy = oAuth2ClientRegistrationInfoEntity.getTenantNameStrategy();
this.tenantNamePattern = oAuth2ClientRegistrationInfoEntity.getTenantNamePattern();
this.customerNamePattern = oAuth2ClientRegistrationInfoEntity.getCustomerNamePattern();
this.defaultDashboardName = oAuth2ClientRegistrationInfoEntity.getDefaultDashboardName();
this.alwaysFullScreen = oAuth2ClientRegistrationInfoEntity.getAlwaysFullScreen();
this.url = oAuth2ClientRegistrationInfoEntity.getUrl();
this.username = oAuth2ClientRegistrationInfoEntity.getUsername();
this.password = oAuth2ClientRegistrationInfoEntity.getPassword();
this.sendToken = oAuth2ClientRegistrationInfoEntity.getSendToken();
}
protected OAuth2ClientRegistrationInfo toOAuth2ClientRegistrationInfo() {
OAuth2ClientRegistrationInfo clientRegistrationInfo = new OAuth2ClientRegistrationInfo();
clientRegistrationInfo.setId(new OAuth2ClientRegistrationInfoId(id));
clientRegistrationInfo.setEnabled(enabled);
clientRegistrationInfo.setCreatedTime(createdTime);
clientRegistrationInfo.setAdditionalInfo(additionalInfo);
clientRegistrationInfo.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(allowUserCreation)
.activateUser(activateUser)
.type(type)
.basic(
type == MapperType.BASIC ?
OAuth2BasicMapperConfig.builder()
.emailAttributeKey(emailAttributeKey)
.firstNameAttributeKey(firstNameAttributeKey)
.lastNameAttributeKey(lastNameAttributeKey)
.tenantNameStrategy(tenantNameStrategy)
.tenantNamePattern(tenantNamePattern)
.customerNamePattern(customerNamePattern)
.defaultDashboardName(defaultDashboardName)
.alwaysFullScreen(alwaysFullScreen)
.build()
: null
)
.custom(
type == MapperType.CUSTOM ?
OAuth2CustomMapperConfig.builder()
.url(url)
.username(username)
.password(password)
.sendToken(sendToken)
.build()
: null
)
.build()
);
clientRegistrationInfo.setClientId(clientId);
clientRegistrationInfo.setClientSecret(clientSecret);
clientRegistrationInfo.setAuthorizationUri(authorizationUri);
clientRegistrationInfo.setAccessTokenUri(tokenUri);
clientRegistrationInfo.setScope(Arrays.asList(scope.split(",")));
clientRegistrationInfo.setUserInfoUri(userInfoUri);
clientRegistrationInfo.setUserNameAttributeName(userNameAttributeName);
clientRegistrationInfo.setJwkSetUri(jwkSetUri);
clientRegistrationInfo.setClientAuthenticationMethod(clientAuthenticationMethod);
clientRegistrationInfo.setLoginButtonLabel(loginButtonLabel);
clientRegistrationInfo.setLoginButtonIcon(loginButtonIcon);
return clientRegistrationInfo;
}
}

48
dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java

@ -0,0 +1,48 @@
/**
* 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.dao.model.sql;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
@Data
@EqualsAndHashCode(callSuper = true)
public class ExtendedOAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<ExtendedOAuth2ClientRegistrationInfo> {
private String domainName;
private SchemeType domainScheme;
public ExtendedOAuth2ClientRegistrationInfoEntity() {
super();
}
public ExtendedOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity,
String domainName,
SchemeType domainScheme) {
super(oAuth2ClientRegistrationInfoEntity);
this.domainName = domainName;
this.domainScheme = domainScheme;
}
@Override
public ExtendedOAuth2ClientRegistrationInfo toData() {
return new ExtendedOAuth2ClientRegistrationInfo(super.toOAuth2ClientRegistrationInfo(),
domainScheme,
domainName);
}
}

162
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java

@ -15,13 +15,11 @@
*/
package org.thingsboard.server.dao.model.sql;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
@ -38,70 +36,15 @@ import java.util.UUID;
@Table(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME)
public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRegistration> {
@Column(name = ModelConstants.OAUTH2_ENABLED_PROPERTY)
private Boolean enabled;
@Column(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_INFO_ID_PROPERTY, columnDefinition = "uuid")
private UUID clientRegistrationInfoId;
@Column(name = ModelConstants.OAUTH2_DOMAIN_NAME_PROPERTY)
private String domainName;
@Column(name = ModelConstants.OAUTH2_CLIENT_ID_PROPERTY)
private String clientId;
@Column(name = ModelConstants.OAUTH2_CLIENT_SECRET_PROPERTY)
private String clientSecret;
@Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY)
private String authorizationUri;
@Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY)
private String tokenUri;
@Column(name = ModelConstants.OAUTH2_REDIRECT_URI_TEMPLATE_PROPERTY)
private String redirectUriTemplate;
@Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY)
private String scope;
@Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY)
private String userInfoUri;
@Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY)
private String userNameAttributeName;
@Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY)
private String jwkSetUri;
@Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY)
private String clientAuthenticationMethod;
@Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY)
private String loginButtonLabel;
@Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_ICON_PROPERTY)
private String loginButtonIcon;
@Column(name = ModelConstants.OAUTH2_ALLOW_USER_CREATION_PROPERTY)
private Boolean allowUserCreation;
@Column(name = ModelConstants.OAUTH2_ACTIVATE_USER_PROPERTY)
private Boolean activateUser;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY)
private MapperType type;
@Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY)
private String emailAttributeKey;
@Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY)
private String firstNameAttributeKey;
@Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY)
private String lastNameAttributeKey;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY)
private TenantNameStrategyType tenantNameStrategy;
@Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY)
private String tenantNamePattern;
@Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY)
private String customerNamePattern;
@Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY)
private String defaultDashboardName;
@Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY)
private Boolean alwaysFullScreen;
@Column(name = ModelConstants.OAUTH2_MAPPER_URL_PROPERTY)
private String url;
@Column(name = ModelConstants.OAUTH2_MAPPER_USERNAME_PROPERTY)
private String username;
@Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY)
private String password;
@Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY)
private Boolean sendToken;
@Type(type = "json")
@Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.OAUTH2_DOMAIN_SCHEME_PROPERTY)
private SchemeType domainScheme;
public OAuth2ClientRegistrationEntity() {
super();
@ -111,99 +54,22 @@ public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRe
if (clientRegistration.getId() != null) {
this.setUuid(clientRegistration.getId().getId());
}
this.enabled = clientRegistration.isEnabled();
this.domainName = clientRegistration.getDomainName();
this.createdTime = clientRegistration.getCreatedTime();
this.clientId = clientRegistration.getClientId();
this.clientSecret = clientRegistration.getClientSecret();
this.authorizationUri = clientRegistration.getAuthorizationUri();
this.tokenUri = clientRegistration.getAccessTokenUri();
this.redirectUriTemplate = clientRegistration.getRedirectUriTemplate();
this.scope = clientRegistration.getScope().stream().reduce((result, element) -> result + "," + element).orElse("");
this.userInfoUri = clientRegistration.getUserInfoUri();
this.userNameAttributeName = clientRegistration.getUserNameAttributeName();
this.jwkSetUri = clientRegistration.getJwkSetUri();
this.clientAuthenticationMethod = clientRegistration.getClientAuthenticationMethod();
this.loginButtonLabel = clientRegistration.getLoginButtonLabel();
this.loginButtonIcon = clientRegistration.getLoginButtonIcon();
this.additionalInfo = clientRegistration.getAdditionalInfo();
OAuth2MapperConfig mapperConfig = clientRegistration.getMapperConfig();
if (mapperConfig != null) {
this.allowUserCreation = mapperConfig.isAllowUserCreation();
this.activateUser = mapperConfig.isActivateUser();
this.type = mapperConfig.getType();
OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
if (basicConfig != null) {
this.emailAttributeKey = basicConfig.getEmailAttributeKey();
this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey();
this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey();
this.tenantNameStrategy = basicConfig.getTenantNameStrategy();
this.tenantNamePattern = basicConfig.getTenantNamePattern();
this.customerNamePattern = basicConfig.getCustomerNamePattern();
this.defaultDashboardName = basicConfig.getDefaultDashboardName();
this.alwaysFullScreen = basicConfig.isAlwaysFullScreen();
}
OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
if (customConfig != null) {
this.url = customConfig.getUrl();
this.username = customConfig.getUsername();
this.password = customConfig.getPassword();
this.sendToken = customConfig.isSendToken();
}
if (clientRegistration.getClientRegistrationId() != null){
this.clientRegistrationInfoId = clientRegistration.getClientRegistrationId().getId();
}
this.createdTime = clientRegistration.getCreatedTime();
this.domainName = clientRegistration.getDomainName();
this.domainScheme = clientRegistration.getDomainScheme();
}
@Override
public OAuth2ClientRegistration toData() {
OAuth2ClientRegistration clientRegistration = new OAuth2ClientRegistration();
clientRegistration.setId(new OAuth2ClientRegistrationId(id));
clientRegistration.setEnabled(enabled);
clientRegistration.setClientRegistrationId(new OAuth2ClientRegistrationInfoId(clientRegistrationInfoId));
clientRegistration.setCreatedTime(createdTime);
clientRegistration.setDomainName(domainName);
clientRegistration.setAdditionalInfo(additionalInfo);
clientRegistration.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(allowUserCreation)
.activateUser(activateUser)
.type(type)
.basic(
type == MapperType.BASIC ?
OAuth2BasicMapperConfig.builder()
.emailAttributeKey(emailAttributeKey)
.firstNameAttributeKey(firstNameAttributeKey)
.lastNameAttributeKey(lastNameAttributeKey)
.tenantNameStrategy(tenantNameStrategy)
.tenantNamePattern(tenantNamePattern)
.customerNamePattern(customerNamePattern)
.defaultDashboardName(defaultDashboardName)
.alwaysFullScreen(alwaysFullScreen)
.build()
: null
)
.custom(
type == MapperType.CUSTOM ?
OAuth2CustomMapperConfig.builder()
.url(url)
.username(username)
.password(password)
.sendToken(sendToken)
.build()
: null
)
.build()
);
clientRegistration.setClientId(clientId);
clientRegistration.setClientSecret(clientSecret);
clientRegistration.setAuthorizationUri(authorizationUri);
clientRegistration.setAccessTokenUri(tokenUri);
clientRegistration.setRedirectUriTemplate(redirectUriTemplate);
clientRegistration.setScope(Arrays.asList(scope.split(",")));
clientRegistration.setUserInfoUri(userInfoUri);
clientRegistration.setUserNameAttributeName(userNameAttributeName);
clientRegistration.setJwkSetUri(jwkSetUri);
clientRegistration.setClientAuthenticationMethod(clientAuthenticationMethod);
clientRegistration.setLoginButtonLabel(loginButtonLabel);
clientRegistration.setLoginButtonIcon(loginButtonIcon);
clientRegistration.setDomainScheme(domainScheme);
return clientRegistration;
}
}

51
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java

@ -0,0 +1,51 @@
/**
* 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.dao.model.sql;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Entity;
import javax.persistence.Table;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME)
public class OAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<OAuth2ClientRegistrationInfo> {
public OAuth2ClientRegistrationInfoEntity() {
super();
}
public OAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfo clientRegistration) {
super(clientRegistration);
}
public OAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity) {
super(oAuth2ClientRegistrationInfoEntity);
}
@Override
public OAuth2ClientRegistrationInfo toData() {
return super.toOAuth2ClientRegistrationInfo();
}
}

12
dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java

@ -21,8 +21,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistration;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import java.util.UUID;
@ -34,12 +33,12 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
@Override
public ClientRegistration findByRegistrationId(String registrationId) {
OAuth2ClientRegistration oAuth2ClientRegistration = oAuth2Service.findClientRegistration(UUID.fromString(registrationId));
return oAuth2ClientRegistration == null ?
null : toSpringClientRegistration(oAuth2ClientRegistration);
OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(UUID.fromString(registrationId));
return oAuth2ClientRegistrationInfo == null ?
null : toSpringClientRegistration(oAuth2ClientRegistrationInfo);
}
private ClientRegistration toSpringClientRegistration(OAuth2ClientRegistration localClientRegistration){
private ClientRegistration toSpringClientRegistration(OAuth2ClientRegistrationInfo localClientRegistration){
String registrationId = localClientRegistration.getUuidId().toString();
return ClientRegistration.withRegistrationId(registrationId)
.clientName(localClientRegistration.getName())
@ -47,7 +46,6 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
.authorizationUri(localClientRegistration.getAuthorizationUri())
.clientSecret(localClientRegistration.getClientSecret())
.tokenUri(localClientRegistration.getAccessTokenUri())
.redirectUriTemplate(localClientRegistration.getRedirectUriTemplate())
.scope(localClientRegistration.getScope())
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.userInfoUri(localClientRegistration.getUserInfoUri())

9
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java

@ -18,13 +18,6 @@ package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.dao.Dao;
import java.util.List;
import java.util.UUID;
public interface OAuth2ClientRegistrationDao extends Dao<OAuth2ClientRegistration> {
List<OAuth2ClientRegistration> findAll();
List<OAuth2ClientRegistration> findByDomainName(String domainName);
int removeByDomainName(String domainName);
void deleteAll();
}

34
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java

@ -0,0 +1,34 @@
/**
* 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.dao.oauth2;
import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.Dao;
import java.util.List;
import java.util.Set;
public interface OAuth2ClientRegistrationInfoDao extends Dao<OAuth2ClientRegistrationInfo> {
List<OAuth2ClientRegistrationInfo> findAll();
List<ExtendedOAuth2ClientRegistrationInfo> findAllExtended();
List<OAuth2ClientRegistrationInfo> findByDomainSchemesAndDomainName(List<SchemeType> domainSchemes, String domainName);
void deleteAll();
}

89
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java

@ -19,11 +19,11 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.*;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import javax.transaction.Transactional;
import java.util.*;
@ -39,78 +39,89 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String INCORRECT_CLIENT_REGISTRATION_ID = "Incorrect clientRegistrationId ";
public static final String INCORRECT_DOMAIN_NAME = "Incorrect domainName ";
public static final String INCORRECT_DOMAIN_SCHEME = "Incorrect domainScheme ";
@Autowired
private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao;
@Autowired
private OAuth2ClientRegistrationDao clientRegistrationDao;
@Override
public List<OAuth2ClientInfo> getOAuth2Clients(String domainName) {
log.trace("Executing getOAuth2Clients [{}]", domainName);
public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName) {
log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName);
if (domainSchemeStr == null) {
throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
}
SchemeType domainScheme;
try {
domainScheme = SchemeType.valueOf(domainSchemeStr.toUpperCase());
} catch (IllegalArgumentException e){
throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
}
validateString(domainName, INCORRECT_DOMAIN_NAME + domainName);
return clientRegistrationDao.findByDomainName(domainName).stream()
.filter(OAuth2ClientRegistration::isEnabled)
return clientRegistrationInfoDao.findByDomainSchemesAndDomainName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName).stream()
.filter(OAuth2ClientRegistrationInfo::isEnabled)
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList());
}
@Override
@Transactional
public OAuth2ClientsParams saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
log.trace("Executing saveOAuth2Params [{}]", oauth2Params);
clientParamsValidator.accept(oauth2Params);
List<OAuth2ClientRegistration> inputClientRegistrations = OAuth2Utils.toClientRegistrations(oauth2Params);
List<OAuth2ClientRegistration> savedClientRegistrations = inputClientRegistrations.stream()
.map(clientRegistration -> clientRegistrationDao.save(TenantId.SYS_TENANT_ID, clientRegistration))
.collect(Collectors.toList());
return OAuth2Utils.toOAuth2Params(savedClientRegistrations);
clientRegistrationDao.deleteAll();
clientRegistrationInfoDao.deleteAll();
oauth2Params.getOAuth2DomainDtos().forEach(domainParams -> {
domainParams.getClientRegistrations().forEach(clientRegistrationDto -> {
OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = OAuth2Utils.toClientRegistrationInfo(oauth2Params.isEnabled(), clientRegistrationDto);
OAuth2ClientRegistrationInfo savedClientRegistrationInfo = clientRegistrationInfoDao.save(TenantId.SYS_TENANT_ID, oAuth2ClientRegistrationInfo);
domainParams.getDomainInfos().forEach(domainInfo -> {
OAuth2ClientRegistration oAuth2ClientRegistration = OAuth2Utils.toClientRegistration(savedClientRegistrationInfo.getId(),
domainInfo.getScheme(), domainInfo.getName());
clientRegistrationDao.save(TenantId.SYS_TENANT_ID, oAuth2ClientRegistration);
});
});
});
}
@Override
public OAuth2ClientsParams findOAuth2Params() {
log.trace("Executing findOAuth2Params");
return OAuth2Utils.toOAuth2Params(clientRegistrationDao.findAll());
}
@Override
public OAuth2ClientRegistration findClientRegistration(UUID id) {
log.trace("Executing findClientRegistration [{}]", id);
validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
return clientRegistrationDao.findById(null, id);
}
@Override
public List<OAuth2ClientRegistration> findAllClientRegistrations() {
log.trace("Executing findAllClientRegistrations");
return clientRegistrationDao.findAll();
List<ExtendedOAuth2ClientRegistrationInfo> extendedInfos = clientRegistrationInfoDao.findAllExtended();
return OAuth2Utils.toOAuth2Params(extendedInfos);
}
@Override
public void deleteClientRegistrationById(OAuth2ClientRegistrationId id) {
log.trace("Executing deleteClientRegistrationById [{}]", id);
public OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id) {
log.trace("Executing findClientRegistrationInfo [{}]", id);
validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
clientRegistrationDao.removeById(TenantId.SYS_TENANT_ID, id.getId());
return clientRegistrationInfoDao.findById(null, id);
}
@Override
@Transactional
public void deleteClientRegistrationsByDomain(String domain) {
log.trace("Executing deleteClientRegistrationsByDomain [{}]", domain);
validateString(domain, INCORRECT_DOMAIN_NAME + domain);
clientRegistrationDao.removeByDomainName(domain);
public List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos() {
log.trace("Executing findAllClientRegistrationInfos");
return clientRegistrationInfoDao.findAll();
}
private final Consumer<OAuth2ClientsParams> clientParamsValidator = oauth2Params -> {
if (oauth2Params == null
|| oauth2Params.getOAuth2DomainDtos() == null
|| oauth2Params.getOAuth2DomainDtos().isEmpty()) {
|| oauth2Params.getOAuth2DomainDtos() == null) {
throw new DataValidationException("Domain params should be specified!");
}
for (OAuth2ClientsDomainParams domainParams : oauth2Params.getOAuth2DomainDtos()) {
if (StringUtils.isEmpty(domainParams.getDomainName())) {
throw new DataValidationException("Domain name should be specified!");
if (domainParams.getDomainInfos() == null
|| domainParams.getDomainInfos().isEmpty()) {
throw new DataValidationException("List of domain configuration should be specified!");
}
if (StringUtils.isEmpty(domainParams.getRedirectUriTemplate())) {
throw new DataValidationException("Redirect URI template should be specified!");
for (DomainInfo domainInfo : domainParams.getDomainInfos()) {
if (StringUtils.isEmpty(domainInfo.getName())) {
throw new DataValidationException("Domain name should be specified!");
}
if (StringUtils.isEmpty(domainInfo.getScheme())) {
throw new DataValidationException("Domain scheme should be specified!");
}
}
if (domainParams.getClientRegistrations() == null || domainParams.getClientRegistrations().isEmpty()) {
throw new DataValidationException("Client registrations should be specified!");

131
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java

@ -15,93 +15,88 @@
*/
package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.*;
public class OAuth2Utils {
public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s";
public static OAuth2ClientInfo toClientInfo(OAuth2ClientRegistration clientRegistration) {
public static OAuth2ClientInfo toClientInfo(OAuth2ClientRegistrationInfo clientRegistrationInfo) {
OAuth2ClientInfo client = new OAuth2ClientInfo();
client.setName(clientRegistration.getLoginButtonLabel());
client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, clientRegistration.getUuidId().toString()));
client.setIcon(clientRegistration.getLoginButtonIcon());
client.setName(clientRegistrationInfo.getLoginButtonLabel());
client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, clientRegistrationInfo.getUuidId().toString()));
client.setIcon(clientRegistrationInfo.getLoginButtonIcon());
return client;
}
public static List<OAuth2ClientRegistration> toClientRegistrations(OAuth2ClientsParams oAuth2Params) {
return oAuth2Params.getOAuth2DomainDtos().stream()
.flatMap(domainParams -> domainParams.getClientRegistrations().stream()
.map(clientRegistrationDto -> OAuth2Utils.toClientRegistration(oAuth2Params.isEnabled(),
domainParams.getDomainName(),
domainParams.getRedirectUriTemplate(),
clientRegistrationDto)
))
.collect(Collectors.toList());
}
public static OAuth2ClientsParams toOAuth2Params(List<OAuth2ClientRegistration> clientRegistrations) {
Map<String, OAuth2ClientsDomainParams> domainParamsMap = new HashMap<>();
boolean enabled = true;
for (OAuth2ClientRegistration clientRegistration : clientRegistrations) {
enabled = clientRegistration.isEnabled();
String domainName = clientRegistration.getDomainName();
OAuth2ClientsDomainParams domainParams = domainParamsMap.computeIfAbsent(domainName,
key -> new OAuth2ClientsDomainParams(domainName, clientRegistration.getRedirectUriTemplate(), new ArrayList<>())
);
domainParams.getClientRegistrations()
.add(toClientRegistrationDto(clientRegistration));
public static OAuth2ClientsParams toOAuth2Params(List<ExtendedOAuth2ClientRegistrationInfo> extendedOAuth2ClientRegistrationInfos) {
Map<OAuth2ClientRegistrationInfoId, Set<DomainInfo>> domainsByInfoId = new HashMap<>();
Map<OAuth2ClientRegistrationInfoId, OAuth2ClientRegistrationInfo> infoById = new HashMap<>();
for (ExtendedOAuth2ClientRegistrationInfo extendedClientRegistrationInfo : extendedOAuth2ClientRegistrationInfos) {
String domainName = extendedClientRegistrationInfo.getDomainName();
SchemeType domainScheme = extendedClientRegistrationInfo.getDomainScheme();
domainsByInfoId.computeIfAbsent(extendedClientRegistrationInfo.getId(), key -> new HashSet<>())
.add(new DomainInfo(domainScheme, domainName));
infoById.put(extendedClientRegistrationInfo.getId(), extendedClientRegistrationInfo);
}
return new OAuth2ClientsParams(enabled, new ArrayList<>(domainParamsMap.values()));
Map<Set<DomainInfo>, OAuth2ClientsDomainParams> domainParamsMap = new HashMap<>();
domainsByInfoId.forEach((clientRegistrationInfoId, domainInfos) -> {
domainParamsMap.computeIfAbsent(domainInfos,
key -> new OAuth2ClientsDomainParams(key, new HashSet<>())
)
.getClientRegistrations()
.add(toClientRegistrationDto(infoById.get(clientRegistrationInfoId)));
});
boolean enabled = extendedOAuth2ClientRegistrationInfos.stream()
.map(OAuth2ClientRegistrationInfo::isEnabled)
.findFirst().orElse(false);
return new OAuth2ClientsParams(enabled, new HashSet<>(domainParamsMap.values()));
}
public static ClientRegistrationDto toClientRegistrationDto(OAuth2ClientRegistration oAuth2ClientRegistration) {
public static ClientRegistrationDto toClientRegistrationDto(OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo) {
return ClientRegistrationDto.builder()
.id(oAuth2ClientRegistration.getId())
.createdTime(oAuth2ClientRegistration.getCreatedTime())
.mapperConfig(oAuth2ClientRegistration.getMapperConfig())
.clientId(oAuth2ClientRegistration.getClientId())
.clientSecret(oAuth2ClientRegistration.getClientSecret())
.authorizationUri(oAuth2ClientRegistration.getAuthorizationUri())
.accessTokenUri(oAuth2ClientRegistration.getAccessTokenUri())
.scope(oAuth2ClientRegistration.getScope())
.userInfoUri(oAuth2ClientRegistration.getUserInfoUri())
.userNameAttributeName(oAuth2ClientRegistration.getUserNameAttributeName())
.jwkSetUri(oAuth2ClientRegistration.getJwkSetUri())
.clientAuthenticationMethod(oAuth2ClientRegistration.getClientAuthenticationMethod())
.loginButtonLabel(oAuth2ClientRegistration.getLoginButtonLabel())
.loginButtonIcon(oAuth2ClientRegistration.getLoginButtonIcon())
.additionalInfo(oAuth2ClientRegistration.getAdditionalInfo())
.mapperConfig(oAuth2ClientRegistrationInfo.getMapperConfig())
.clientId(oAuth2ClientRegistrationInfo.getClientId())
.clientSecret(oAuth2ClientRegistrationInfo.getClientSecret())
.authorizationUri(oAuth2ClientRegistrationInfo.getAuthorizationUri())
.accessTokenUri(oAuth2ClientRegistrationInfo.getAccessTokenUri())
.scope(oAuth2ClientRegistrationInfo.getScope())
.userInfoUri(oAuth2ClientRegistrationInfo.getUserInfoUri())
.userNameAttributeName(oAuth2ClientRegistrationInfo.getUserNameAttributeName())
.jwkSetUri(oAuth2ClientRegistrationInfo.getJwkSetUri())
.clientAuthenticationMethod(oAuth2ClientRegistrationInfo.getClientAuthenticationMethod())
.loginButtonLabel(oAuth2ClientRegistrationInfo.getLoginButtonLabel())
.loginButtonIcon(oAuth2ClientRegistrationInfo.getLoginButtonIcon())
.additionalInfo(oAuth2ClientRegistrationInfo.getAdditionalInfo())
.build();
}
private static OAuth2ClientRegistration toClientRegistration(boolean enabled, String domainName,
String redirectUriTemplate,
ClientRegistrationDto clientRegistrationDto) {
public static OAuth2ClientRegistrationInfo toClientRegistrationInfo(boolean enabled, ClientRegistrationDto clientRegistrationDto) {
OAuth2ClientRegistrationInfo clientRegistrationInfo = new OAuth2ClientRegistrationInfo();
clientRegistrationInfo.setEnabled(enabled);
clientRegistrationInfo.setMapperConfig(clientRegistrationDto.getMapperConfig());
clientRegistrationInfo.setClientId(clientRegistrationDto.getClientId());
clientRegistrationInfo.setClientSecret(clientRegistrationDto.getClientSecret());
clientRegistrationInfo.setAuthorizationUri(clientRegistrationDto.getAuthorizationUri());
clientRegistrationInfo.setAccessTokenUri(clientRegistrationDto.getAccessTokenUri());
clientRegistrationInfo.setScope(clientRegistrationDto.getScope());
clientRegistrationInfo.setUserInfoUri(clientRegistrationDto.getUserInfoUri());
clientRegistrationInfo.setUserNameAttributeName(clientRegistrationDto.getUserNameAttributeName());
clientRegistrationInfo.setJwkSetUri(clientRegistrationDto.getJwkSetUri());
clientRegistrationInfo.setClientAuthenticationMethod(clientRegistrationDto.getClientAuthenticationMethod());
clientRegistrationInfo.setLoginButtonLabel(clientRegistrationDto.getLoginButtonLabel());
clientRegistrationInfo.setLoginButtonIcon(clientRegistrationDto.getLoginButtonIcon());
clientRegistrationInfo.setAdditionalInfo(clientRegistrationDto.getAdditionalInfo());
return clientRegistrationInfo;
}
public static OAuth2ClientRegistration toClientRegistration(OAuth2ClientRegistrationInfoId clientRegistrationInfoId, SchemeType domainScheme, String domainName) {
OAuth2ClientRegistration clientRegistration = new OAuth2ClientRegistration();
clientRegistration.setId(clientRegistrationDto.getId());
clientRegistration.setEnabled(enabled);
clientRegistration.setCreatedTime(clientRegistrationDto.getCreatedTime());
clientRegistration.setClientRegistrationId(clientRegistrationInfoId);
clientRegistration.setDomainName(domainName);
clientRegistration.setRedirectUriTemplate(redirectUriTemplate);
clientRegistration.setMapperConfig(clientRegistrationDto.getMapperConfig());
clientRegistration.setClientId(clientRegistrationDto.getClientId());
clientRegistration.setClientSecret(clientRegistrationDto.getClientSecret());
clientRegistration.setAuthorizationUri(clientRegistrationDto.getAuthorizationUri());
clientRegistration.setAccessTokenUri(clientRegistrationDto.getAccessTokenUri());
clientRegistration.setScope(clientRegistrationDto.getScope());
clientRegistration.setUserInfoUri(clientRegistrationDto.getUserInfoUri());
clientRegistration.setUserNameAttributeName(clientRegistrationDto.getUserNameAttributeName());
clientRegistration.setJwkSetUri(clientRegistrationDto.getJwkSetUri());
clientRegistration.setClientAuthenticationMethod(clientRegistrationDto.getClientAuthenticationMethod());
clientRegistration.setLoginButtonLabel(clientRegistrationDto.getLoginButtonLabel());
clientRegistration.setLoginButtonIcon(clientRegistrationDto.getLoginButtonIcon());
clientRegistration.setAdditionalInfo(clientRegistrationDto.getAdditionalInfo());
clientRegistration.setDomainScheme(domainScheme);
return clientRegistration;
}
}

25
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java

@ -16,18 +16,15 @@
package org.thingsboard.server.dao.sql.oauth2;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity;
import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Component
@RequiredArgsConstructor
@ -45,23 +42,7 @@ public class JpaOAuth2ClientRegistrationDao extends JpaAbstractDao<OAuth2ClientR
}
@Override
public List<OAuth2ClientRegistration> findAll() {
Iterable<OAuth2ClientRegistrationEntity> entities = repository.findAll();
List<OAuth2ClientRegistration> result = new ArrayList<>();
entities.forEach(entity -> {
result.add(DaoUtil.getData(entity));
});
return result;
}
@Override
public List<OAuth2ClientRegistration> findByDomainName(String domainName) {
List<OAuth2ClientRegistrationEntity> entities = repository.findAllByDomainName(domainName);
return entities.stream().map(DaoUtil::getData).collect(Collectors.toList());
}
@Override
public int removeByDomainName(String domainName) {
return repository.deleteByDomainName(domainName);
public void deleteAll() {
repository.deleteAll();
}
}

76
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java

@ -0,0 +1,76 @@
/**
* 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.dao.sql.oauth2;
import lombok.RequiredArgsConstructor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity;
import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationInfoDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Component
@RequiredArgsConstructor
public class JpaOAuth2ClientRegistrationInfoDao extends JpaAbstractDao<OAuth2ClientRegistrationInfoEntity, OAuth2ClientRegistrationInfo> implements OAuth2ClientRegistrationInfoDao {
private final OAuth2ClientRegistrationInfoRepository repository;
@Override
protected Class<OAuth2ClientRegistrationInfoEntity> getEntityClass() {
return OAuth2ClientRegistrationInfoEntity.class;
}
@Override
protected CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> getCrudRepository() {
return repository;
}
@Override
public List<OAuth2ClientRegistrationInfo> findAll() {
Iterable<OAuth2ClientRegistrationInfoEntity> entities = repository.findAll();
List<OAuth2ClientRegistrationInfo> result = new ArrayList<>();
entities.forEach(entity -> {
result.add(DaoUtil.getData(entity));
});
return result;
}
@Override
public List<ExtendedOAuth2ClientRegistrationInfo> findAllExtended() {
return repository.findAllExtended().stream()
.map(DaoUtil::getData)
.collect(Collectors.toList());
}
@Override
public List<OAuth2ClientRegistrationInfo> findByDomainSchemesAndDomainName(List<SchemeType> domainSchemes, String domainName) {
List<OAuth2ClientRegistrationInfoEntity> entities = repository.findAllByDomainSchemesAndName(domainSchemes, domainName);
return entities.stream().map(DaoUtil::getData).collect(Collectors.toList());
}
@Override
public void deleteAll() {
repository.deleteAll();
}
}

41
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java

@ -0,0 +1,41 @@
/**
* 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.dao.sql.oauth2;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity;
import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity;
import java.util.List;
import java.util.UUID;
public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> {
@Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " +
"FROM OAuth2ClientRegistrationInfoEntity cr_info " +
"LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId " +
"WHERE cr.domainName = :domainName " +
"AND cr.domainScheme IN (:domainSchemes)")
List<OAuth2ClientRegistrationInfoEntity> findAllByDomainSchemesAndName(@Param("domainSchemes") List<SchemeType> domainSchemes,
@Param("domainName") String domainName);
@Query("SELECT new org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " +
"FROM OAuth2ClientRegistrationInfoEntity cr_info " +
"LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ")
List<ExtendedOAuth2ClientRegistrationInfoEntity> findAllExtended();
}

4
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java

@ -18,11 +18,7 @@ package org.thingsboard.server.dao.sql.oauth2;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity;
import java.util.List;
import java.util.UUID;
public interface OAuth2ClientRegistrationRepository extends CrudRepository<OAuth2ClientRegistrationEntity, UUID> {
List<OAuth2ClientRegistrationEntity> findAllByDomainName(String domainName);
int deleteByDomainName(String domainName);
}

14
dao/src/main/resources/sql/schema-entities-hsql.sql

@ -291,17 +291,15 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary (
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
enabled boolean,
created_time bigint NOT NULL,
additional_info varchar,
domain_name varchar(255),
client_id varchar(255),
client_secret varchar(255),
authorization_uri varchar(255),
token_uri varchar(255),
redirect_uri_template varchar(255),
scope varchar(255),
user_info_uri varchar(255),
user_name_attribute_name varchar(255),
@ -326,6 +324,14 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
custom_send_token boolean
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
created_time bigint NOT NULL,
domain_name varchar(255),
domain_scheme varchar(31),
client_registration_info_id uuid
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY,
created_time bigint NOT NULL,

14
dao/src/main/resources/sql/schema-entities.sql

@ -316,17 +316,15 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary
CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
enabled boolean,
created_time bigint NOT NULL,
additional_info varchar,
domain_name varchar(255),
client_id varchar(255),
client_secret varchar(255),
authorization_uri varchar(255),
token_uri varchar(255),
redirect_uri_template varchar(255),
scope varchar(255),
user_info_uri varchar(255),
user_name_attribute_name varchar(255),
@ -351,6 +349,14 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration (
custom_send_token boolean
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
created_time bigint NOT NULL,
domain_name varchar(255),
domain_scheme varchar(31),
client_registration_info_id uuid
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY,
created_time bigint NOT NULL,

484
dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.service;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -22,170 +23,413 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.oauth2.*;
import org.thingsboard.server.dao.oauth2.OAuth2Service;
import org.thingsboard.server.dao.oauth2.OAuth2Utils;
import java.util.*;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.oauth2.OAuth2Utils.toClientRegistrations;
public class BaseOAuth2ServiceTest extends AbstractServiceTest {
private static final OAuth2ClientsParams EMPTY_PARAMS = new OAuth2ClientsParams(false, new HashSet<>());
@Autowired
protected OAuth2Service oAuth2Service;
@Before
public void beforeRun() {
Assert.assertTrue(oAuth2Service.findAllClientRegistrations().isEmpty());
Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());
}
@After
public void after() {
oAuth2Service.findAllClientRegistrations().forEach(clientRegistration -> {
oAuth2Service.deleteClientRegistrationById(clientRegistration.getId());
});
Assert.assertTrue(oAuth2Service.findAllClientRegistrations().isEmpty());
oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);
Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());
Assert.assertTrue(oAuth2Service.findOAuth2Params().getOAuth2DomainDtos().isEmpty());
}
@Test
public void testCreateAndFindParams() {
OAuth2ClientsParams clientsParams = createDefaultClientsParams();
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundClientsParams);
// TODO ask if it's safe to check equality on AdditionalProperties
Assert.assertEquals(clientsParams, foundClientsParams);
}
@Test
public void testCreateNewParams() {
OAuth2ClientRegistration clientRegistration = validClientRegistration("domain-name");
OAuth2ClientsParams savedOAuth2Params = oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(clientRegistration)));
Assert.assertNotNull(savedOAuth2Params);
public void testDisableParams() {
OAuth2ClientsParams clientsParams = createDefaultClientsParams();
clientsParams.setEnabled(true);
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundClientsParams);
Assert.assertEquals(clientsParams, foundClientsParams);
List<OAuth2ClientRegistration> savedClientRegistrations = OAuth2Utils.toClientRegistrations(savedOAuth2Params);
Assert.assertEquals(1, savedClientRegistrations.size());
clientsParams.setEnabled(false);
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundDisabledClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertEquals(clientsParams, foundDisabledClientsParams);
}
OAuth2ClientRegistration savedClientRegistration = savedClientRegistrations.get(0);
Assert.assertNotNull(savedClientRegistration.getId());
clientRegistration.setId(savedClientRegistration.getId());
clientRegistration.setCreatedTime(savedClientRegistration.getCreatedTime());
Assert.assertEquals(clientRegistration, savedClientRegistration);
@Test
public void testClearDomainParams() {
OAuth2ClientsParams clientsParams = createDefaultClientsParams();
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundClientsParams);
Assert.assertEquals(clientsParams, foundClientsParams);
oAuth2Service.deleteClientRegistrationsByDomain("domain-name");
oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);
OAuth2ClientsParams foundAfterClearClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundAfterClearClientsParams);
Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams);
}
@Test
public void testFindDomainParams() {
OAuth2ClientRegistration clientRegistration = validClientRegistration();
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(clientRegistration)));
OAuth2ClientsParams foundOAuth2Params = oAuth2Service.findOAuth2Params();
Assert.assertEquals(1, foundOAuth2Params.getOAuth2DomainDtos().size());
Assert.assertEquals(1, oAuth2Service.findAllClientRegistrations().size());
List<OAuth2ClientRegistration> foundClientRegistrations = OAuth2Utils.toClientRegistrations(foundOAuth2Params);
OAuth2ClientRegistration foundClientRegistration = foundClientRegistrations.get(0);
Assert.assertNotNull(foundClientRegistration);
clientRegistration.setId(foundClientRegistration.getId());
clientRegistration.setCreatedTime(foundClientRegistration.getCreatedTime());
Assert.assertEquals(clientRegistration, foundClientRegistration);
public void testUpdateClientsParams() {
OAuth2ClientsParams clientsParams = createDefaultClientsParams();
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundClientsParams);
Assert.assertEquals(clientsParams, foundClientsParams);
OAuth2ClientsParams newClientsParams = new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto()
))
.build()
));
oAuth2Service.saveOAuth2Params(newClientsParams);
OAuth2ClientsParams foundAfterUpdateClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundAfterUpdateClientsParams);
Assert.assertEquals(newClientsParams, foundAfterUpdateClientsParams);
}
@Test
public void testGetOAuth2Clients() {
String testDomainName = "test_domain";
OAuth2ClientRegistration first = validClientRegistration(testDomainName);
first.setEnabled(true);
OAuth2ClientRegistration second = validClientRegistration(testDomainName);
second.setEnabled(true);
Set<ClientRegistrationDto> firstGroup = Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto()
);
Set<ClientRegistrationDto> secondGroup = Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto()
);
Set<ClientRegistrationDto> thirdGroup = Sets.newHashSet(
validClientRegistrationDto()
);
OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(firstGroup)
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(secondGroup)
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
.clientRegistrations(thirdGroup)
.build()
));
oAuth2Service.saveOAuth2Params(clientsParams);
OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
Assert.assertNotNull(foundClientsParams);
Assert.assertEquals(clientsParams, foundClientsParams);
List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream()
.map(clientRegistrationDto -> new OAuth2ClientInfo(
clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
.collect(Collectors.toList());
List<OAuth2ClientInfo> secondGroupClientInfos = secondGroup.stream()
.map(clientRegistrationDto -> new OAuth2ClientInfo(
clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
.collect(Collectors.toList());
List<OAuth2ClientInfo> thirdGroupClientInfos = thirdGroup.stream()
.map(clientRegistrationDto -> new OAuth2ClientInfo(
clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
.collect(Collectors.toList());
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(first)));
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(second)));
List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain");
Assert.assertTrue(nonExistentDomainClients.isEmpty());
List<OAuth2ClientInfo> oAuth2Clients = oAuth2Service.getOAuth2Clients(testDomainName);
List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain");
Assert.assertEquals(firstDomainHttpClients.size(), firstDomainHttpClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
firstDomainHttpClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
&& clientInfo.getName().equals(firstGroupClientInfo.getName()))
);
});
Set<String> actualLabels = new HashSet<>(Arrays.asList(first.getLoginButtonLabel(),
second.getLoginButtonLabel()));
List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain");
Assert.assertTrue(firstDomainHttpsClients.isEmpty());
Set<String> foundLabels = oAuth2Clients.stream().map(OAuth2ClientInfo::getName).collect(Collectors.toSet());
Assert.assertEquals(actualLabels, foundLabels);
List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain");
Assert.assertEquals(fourthDomainHttpClients.size(), secondGroupClientInfos.size());
secondGroupClientInfos.forEach(secondGroupClientInfo -> {
Assert.assertTrue(
fourthDomainHttpClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
&& clientInfo.getName().equals(secondGroupClientInfo.getName()))
);
});
List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain");
Assert.assertEquals(fourthDomainHttpsClients.size(), secondGroupClientInfos.size());
secondGroupClientInfos.forEach(secondGroupClientInfo -> {
Assert.assertTrue(
fourthDomainHttpsClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
&& clientInfo.getName().equals(secondGroupClientInfo.getName()))
);
});
List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
Assert.assertEquals(secondDomainHttpClients.size(), firstGroupClientInfos.size() + secondGroupClientInfos.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
secondDomainHttpClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
&& clientInfo.getName().equals(firstGroupClientInfo.getName()))
);
});
secondGroupClientInfos.forEach(secondGroupClientInfo -> {
Assert.assertTrue(
secondDomainHttpClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
&& clientInfo.getName().equals(secondGroupClientInfo.getName()))
);
});
List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain");
Assert.assertEquals(secondDomainHttpsClients.size(), firstGroupClientInfos.size() + thirdGroupClientInfos.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
secondDomainHttpsClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
&& clientInfo.getName().equals(firstGroupClientInfo.getName()))
);
});
thirdGroupClientInfos.forEach(thirdGroupClientInfo -> {
Assert.assertTrue(
secondDomainHttpsClients.stream().anyMatch(clientInfo ->
clientInfo.getIcon().equals(thirdGroupClientInfo.getIcon())
&& clientInfo.getName().equals(thirdGroupClientInfo.getName()))
);
});
}
@Test
public void testGetEmptyOAuth2Clients() {
String testDomainName = "test_domain";
OAuth2ClientRegistration tenantClientRegistration = validClientRegistration(testDomainName);
OAuth2ClientRegistration sysAdminClientRegistration = validClientRegistration(testDomainName);
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(tenantClientRegistration)));
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Collections.singletonList(sysAdminClientRegistration)));
List<OAuth2ClientInfo> oAuth2Clients = oAuth2Service.getOAuth2Clients("random-domain");
Assert.assertTrue(oAuth2Clients.isEmpty());
public void testGetDisabledOAuth2Clients() {
OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build()
));
oAuth2Service.saveOAuth2Params(clientsParams);
List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
Assert.assertEquals(5, secondDomainHttpClients.size());
clientsParams.setEnabled(false);
oAuth2Service.saveOAuth2Params(clientsParams);
List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
}
@Test
public void testDeleteOAuth2ClientRegistration() {
OAuth2ClientRegistration first = validClientRegistration();
OAuth2ClientRegistration second = validClientRegistration();
OAuth2ClientsParams savedFirstOAuth2Params = oAuth2Service.saveOAuth2Params(
OAuth2Utils.toOAuth2Params(Collections.singletonList(first)));
OAuth2ClientsParams savedSecondOAuth2Params = oAuth2Service.saveOAuth2Params(
OAuth2Utils.toOAuth2Params(Collections.singletonList(second)));
OAuth2ClientRegistration savedFirstRegistration = toClientRegistrations(savedFirstOAuth2Params).get(0);
OAuth2ClientRegistration savedSecondRegistration = toClientRegistrations(savedSecondOAuth2Params).get(0);
oAuth2Service.deleteClientRegistrationById(savedFirstRegistration.getId());
List<OAuth2ClientRegistration> foundRegistrations = oAuth2Service.findAllClientRegistrations();
Assert.assertEquals(1, foundRegistrations.size());
Assert.assertEquals(savedSecondRegistration, foundRegistrations.get(0));
public void testFindAllClientRegistrationInfos() {
OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto()
))
.build()
));
oAuth2Service.saveOAuth2Params(clientsParams);
List<OAuth2ClientRegistrationInfo> foundClientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();
Assert.assertEquals(6, foundClientRegistrationInfos.size());
clientsParams.getOAuth2DomainDtos().stream()
.flatMap(domainParams -> domainParams.getClientRegistrations().stream())
.forEach(clientRegistrationDto ->
Assert.assertTrue(
foundClientRegistrationInfos.stream()
.anyMatch(clientRegistrationInfo -> clientRegistrationInfo.getClientId().equals(clientRegistrationDto.getClientId()))
)
);
}
@Test
public void testDeleteDomainOAuth2ClientRegistrations() {
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Arrays.asList(
validClientRegistration("domain1"),
validClientRegistration("domain1"),
validClientRegistration("domain2")
)));
oAuth2Service.saveOAuth2Params(OAuth2Utils.toOAuth2Params(Arrays.asList(
validClientRegistration("domain2")
)));
Assert.assertEquals(4, oAuth2Service.findAllClientRegistrations().size());
OAuth2ClientsParams oAuth2Params = oAuth2Service.findOAuth2Params();
List<OAuth2ClientRegistration> clientRegistrations = toClientRegistrations(oAuth2Params);
Assert.assertEquals(2, oAuth2Params.getOAuth2DomainDtos().size());
Assert.assertEquals(4, clientRegistrations.size());
oAuth2Service.deleteClientRegistrationsByDomain("domain1");
Assert.assertEquals(2, oAuth2Service.findAllClientRegistrations().size());
Assert.assertEquals(1, oAuth2Service.findOAuth2Params().getOAuth2DomainDtos().size());
Assert.assertEquals(2, toClientRegistrations(oAuth2Service.findOAuth2Params()).size());
}
public void testFindClientRegistrationById() {
OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto()
))
.build()
));
private OAuth2ClientRegistration validClientRegistration() {
return validClientRegistration(UUID.randomUUID().toString());
oAuth2Service.saveOAuth2Params(clientsParams);
List<OAuth2ClientRegistrationInfo> clientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();
clientRegistrationInfos.forEach(clientRegistrationInfo -> {
OAuth2ClientRegistrationInfo foundClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(clientRegistrationInfo.getUuidId());
Assert.assertEquals(clientRegistrationInfo, foundClientRegistrationInfo);
});
}
private OAuth2ClientRegistration validClientRegistration(String domainName) {
OAuth2ClientRegistration clientRegistration = new OAuth2ClientRegistration();
clientRegistration.setDomainName(domainName);
clientRegistration.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url("UUID.randomUUID().toString()")
.build()
)
private OAuth2ClientsParams createDefaultClientsParams() {
return new OAuth2ClientsParams(true, Sets.newHashSet(
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build(),
OAuth2ClientsDomainParams.builder()
.domainInfos(Sets.newHashSet(
DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Sets.newHashSet(
validClientRegistrationDto(),
validClientRegistrationDto()
))
.build()
);
clientRegistration.setClientId(UUID.randomUUID().toString());
clientRegistration.setClientSecret(UUID.randomUUID().toString());
clientRegistration.setAuthorizationUri(UUID.randomUUID().toString());
clientRegistration.setAccessTokenUri(UUID.randomUUID().toString());
clientRegistration.setRedirectUriTemplate(UUID.randomUUID().toString());
clientRegistration.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
clientRegistration.setUserInfoUri(UUID.randomUUID().toString());
clientRegistration.setUserNameAttributeName(UUID.randomUUID().toString());
clientRegistration.setJwkSetUri(UUID.randomUUID().toString());
clientRegistration.setClientAuthenticationMethod(UUID.randomUUID().toString());
clientRegistration.setLoginButtonLabel(UUID.randomUUID().toString());
clientRegistration.setLoginButtonIcon(UUID.randomUUID().toString());
clientRegistration.setAdditionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
return clientRegistration;
));
}
private ClientRegistrationDto validClientRegistrationDto() {
return ClientRegistrationDto.builder()
.clientId(UUID.randomUUID().toString())
.clientSecret(UUID.randomUUID().toString())
.authorizationUri(UUID.randomUUID().toString())
.accessTokenUri(UUID.randomUUID().toString())
.scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
.userInfoUri(UUID.randomUUID().toString())
.userNameAttributeName(UUID.randomUUID().toString())
.jwkSetUri(UUID.randomUUID().toString())
.clientAuthenticationMethod(UUID.randomUUID().toString())
.loginButtonLabel(UUID.randomUUID().toString())
.loginButtonIcon(UUID.randomUUID().toString())
.additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
.mapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build()
)
.build();
}
}

Loading…
Cancel
Save