Commit cc531daaeee9f4ff2f38b3f2dcaa25f5854358a6

Authored by Igor Kulikov
1 parent 8e4f8594

Add platform type filter for oauth2 registrations.

Showing 22 changed files with 187 additions and 44 deletions
@@ -96,6 +96,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( @@ -96,6 +96,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration (
96 authorization_uri varchar(255), 96 authorization_uri varchar(255),
97 token_uri varchar(255), 97 token_uri varchar(255),
98 scope varchar(255), 98 scope varchar(255),
  99 + platforms varchar(255),
99 user_info_uri varchar(255), 100 user_info_uri varchar(255),
100 user_name_attribute_name varchar(255), 101 user_name_attribute_name varchar(255),
101 jwk_set_uri varchar(255), 102 jwk_set_uri varchar(255),
@@ -26,9 +26,11 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -26,9 +26,11 @@ import org.springframework.web.bind.annotation.RequestParam;
26 import org.springframework.web.bind.annotation.ResponseBody; 26 import org.springframework.web.bind.annotation.ResponseBody;
27 import org.springframework.web.bind.annotation.ResponseStatus; 27 import org.springframework.web.bind.annotation.ResponseStatus;
28 import org.springframework.web.bind.annotation.RestController; 28 import org.springframework.web.bind.annotation.RestController;
  29 +import org.thingsboard.server.common.data.StringUtils;
29 import org.thingsboard.server.common.data.exception.ThingsboardException; 30 import org.thingsboard.server.common.data.exception.ThingsboardException;
30 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; 31 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
31 import org.thingsboard.server.common.data.oauth2.OAuth2Info; 32 import org.thingsboard.server.common.data.oauth2.OAuth2Info;
  33 +import org.thingsboard.server.common.data.oauth2.PlatformType;
32 import org.thingsboard.server.dao.oauth2.OAuth2Configuration; 34 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
33 import org.thingsboard.server.queue.util.TbCoreComponent; 35 import org.thingsboard.server.queue.util.TbCoreComponent;
34 import org.thingsboard.server.service.security.permission.Operation; 36 import org.thingsboard.server.service.security.permission.Operation;
@@ -51,7 +53,8 @@ public class OAuth2Controller extends BaseController { @@ -51,7 +53,8 @@ public class OAuth2Controller extends BaseController {
51 @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) 53 @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST)
52 @ResponseBody 54 @ResponseBody
53 public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request, 55 public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request,
54 - @RequestParam(required = false) String pkgName) throws ThingsboardException { 56 + @RequestParam(required = false) String pkgName,
  57 + @RequestParam(required = false) String platform) throws ThingsboardException {
55 try { 58 try {
56 if (log.isDebugEnabled()) { 59 if (log.isDebugEnabled()) {
57 log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort()); 60 log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort());
@@ -61,7 +64,13 @@ public class OAuth2Controller extends BaseController { @@ -61,7 +64,13 @@ public class OAuth2Controller extends BaseController {
61 log.debug("Header: {} {}", header, request.getHeader(header)); 64 log.debug("Header: {} {}", header, request.getHeader(header));
62 } 65 }
63 } 66 }
64 - return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName); 67 + PlatformType platformType = null;
  68 + if (StringUtils.isNotEmpty(platform)) {
  69 + try {
  70 + platformType = PlatformType.valueOf(platform);
  71 + } catch (Exception e) {}
  72 + }
  73 + return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName, platformType);
65 } catch (Exception e) { 74 } catch (Exception e) {
66 throw handleException(e); 75 throw handleException(e);
67 } 76 }
@@ -199,6 +199,7 @@ public class ThingsboardInstallService { @@ -199,6 +199,7 @@ public class ThingsboardInstallService {
199 databaseEntitiesUpgradeService.upgradeDatabase("3.2.2"); 199 databaseEntitiesUpgradeService.upgradeDatabase("3.2.2");
200 200
201 dataUpdateService.updateData("3.2.2"); 201 dataUpdateService.updateData("3.2.2");
  202 + systemDataLoaderService.createOAuth2Templates();
202 203
203 log.info("Updating system data..."); 204 log.info("Updating system data...");
204 systemDataLoaderService.updateSystemWidgets(); 205 systemDataLoaderService.updateSystemWidgets();
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.oauth2; @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.oauth2;
18 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; 18 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
19 import org.thingsboard.server.common.data.oauth2.OAuth2Info; 19 import org.thingsboard.server.common.data.oauth2.OAuth2Info;
20 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 20 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  21 +import org.thingsboard.server.common.data.oauth2.PlatformType;
21 import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo; 22 import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
22 import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams; 23 import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
23 24
@@ -25,7 +26,7 @@ import java.util.List; @@ -25,7 +26,7 @@ import java.util.List;
25 import java.util.UUID; 26 import java.util.UUID;
26 27
27 public interface OAuth2Service { 28 public interface OAuth2Service {
28 - List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName); 29 + List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName, PlatformType platformType);
29 30
30 @Deprecated 31 @Deprecated
31 void saveOAuth2Params(OAuth2ClientsParams oauth2Params); 32 void saveOAuth2Params(OAuth2ClientsParams oauth2Params);
@@ -46,6 +46,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2 @@ -46,6 +46,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2
46 private String clientAuthenticationMethod; 46 private String clientAuthenticationMethod;
47 private String loginButtonLabel; 47 private String loginButtonLabel;
48 private String loginButtonIcon; 48 private String loginButtonIcon;
  49 + private List<PlatformType> platforms;
49 50
50 public OAuth2Registration(OAuth2Registration registration) { 51 public OAuth2Registration(OAuth2Registration registration) {
51 super(registration); 52 super(registration);
@@ -62,6 +63,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2 @@ -62,6 +63,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2
62 this.clientAuthenticationMethod = registration.clientAuthenticationMethod; 63 this.clientAuthenticationMethod = registration.clientAuthenticationMethod;
63 this.loginButtonLabel = registration.loginButtonLabel; 64 this.loginButtonLabel = registration.loginButtonLabel;
64 this.loginButtonIcon = registration.loginButtonIcon; 65 this.loginButtonIcon = registration.loginButtonIcon;
  66 + this.platforms = registration.platforms;
65 } 67 }
66 68
67 @Override 69 @Override
@@ -39,5 +39,6 @@ public class OAuth2RegistrationInfo { @@ -39,5 +39,6 @@ public class OAuth2RegistrationInfo {
39 private String clientAuthenticationMethod; 39 private String clientAuthenticationMethod;
40 private String loginButtonLabel; 40 private String loginButtonLabel;
41 private String loginButtonIcon; 41 private String loginButtonIcon;
  42 + private List<PlatformType> platforms;
42 private JsonNode additionalInfo; 43 private JsonNode additionalInfo;
43 } 44 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +public enum PlatformType {
  19 + WEB, ANDROID, IOS
  20 +}
@@ -433,6 +433,7 @@ public class ModelConstants { @@ -433,6 +433,7 @@ public class ModelConstants {
433 public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri"; 433 public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri";
434 public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri"; 434 public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri";
435 public static final String OAUTH2_SCOPE_PROPERTY = "scope"; 435 public static final String OAUTH2_SCOPE_PROPERTY = "scope";
  436 + public static final String OAUTH2_PLATFORMS_PROPERTY = "platforms";
436 public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri"; 437 public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri";
437 public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name"; 438 public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name";
438 public static final String OAUTH2_JWK_SET_URI_PROPERTY = "jwk_set_uri"; 439 public static final String OAUTH2_JWK_SET_URI_PROPERTY = "jwk_set_uri";
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.dao.model.sql; 16 package org.thingsboard.server.dao.model.sql;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
  19 +import io.micrometer.core.instrument.util.StringUtils;
19 import lombok.Data; 20 import lombok.Data;
20 import lombok.EqualsAndHashCode; 21 import lombok.EqualsAndHashCode;
21 import org.hibernate.annotations.Type; 22 import org.hibernate.annotations.Type;
@@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig; @@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
27 import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; 28 import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
28 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; 29 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
29 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 30 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  31 +import org.thingsboard.server.common.data.oauth2.PlatformType;
30 import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType; 32 import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
31 import org.thingsboard.server.dao.model.BaseSqlEntity; 33 import org.thingsboard.server.dao.model.BaseSqlEntity;
32 import org.thingsboard.server.dao.model.ModelConstants; 34 import org.thingsboard.server.dao.model.ModelConstants;
@@ -38,7 +40,9 @@ import javax.persistence.EnumType; @@ -38,7 +40,9 @@ import javax.persistence.EnumType;
38 import javax.persistence.Enumerated; 40 import javax.persistence.Enumerated;
39 import javax.persistence.Table; 41 import javax.persistence.Table;
40 import java.util.Arrays; 42 import java.util.Arrays;
  43 +import java.util.Collections;
41 import java.util.UUID; 44 import java.util.UUID;
  45 +import java.util.stream.Collectors;
42 46
43 @Data 47 @Data
44 @EqualsAndHashCode(callSuper = true) 48 @EqualsAndHashCode(callSuper = true)
@@ -59,6 +63,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> @@ -59,6 +63,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration>
59 private String tokenUri; 63 private String tokenUri;
60 @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY) 64 @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY)
61 private String scope; 65 private String scope;
  66 + @Column(name = ModelConstants.OAUTH2_PLATFORMS_PROPERTY)
  67 + private String platforms;
62 @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY) 68 @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY)
63 private String userInfoUri; 69 private String userInfoUri;
64 @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY) 70 @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY)
@@ -125,6 +131,7 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> @@ -125,6 +131,7 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration>
125 this.authorizationUri = registration.getAuthorizationUri(); 131 this.authorizationUri = registration.getAuthorizationUri();
126 this.tokenUri = registration.getAccessTokenUri(); 132 this.tokenUri = registration.getAccessTokenUri();
127 this.scope = registration.getScope().stream().reduce((result, element) -> result + "," + element).orElse(""); 133 this.scope = registration.getScope().stream().reduce((result, element) -> result + "," + element).orElse("");
  134 + this.platforms = registration.getPlatforms() != null ? registration.getPlatforms().stream().map(Enum::name).reduce((result, element) -> result + "," + element).orElse("") : "";
128 this.userInfoUri = registration.getUserInfoUri(); 135 this.userInfoUri = registration.getUserInfoUri();
129 this.userNameAttributeName = registration.getUserNameAttributeName(); 136 this.userNameAttributeName = registration.getUserNameAttributeName();
130 this.jwkSetUri = registration.getJwkSetUri(); 137 this.jwkSetUri = registration.getJwkSetUri();
@@ -201,6 +208,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> @@ -201,6 +208,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration>
201 registration.setAuthorizationUri(authorizationUri); 208 registration.setAuthorizationUri(authorizationUri);
202 registration.setAccessTokenUri(tokenUri); 209 registration.setAccessTokenUri(tokenUri);
203 registration.setScope(Arrays.asList(scope.split(","))); 210 registration.setScope(Arrays.asList(scope.split(",")));
  211 + registration.setPlatforms(StringUtils.isNotEmpty(platforms) ? Arrays.stream(platforms.split(","))
  212 + .map(str -> PlatformType.valueOf(str)).collect(Collectors.toList()) : Collections.emptyList());
204 registration.setUserInfoUri(userInfoUri); 213 registration.setUserInfoUri(userInfoUri);
205 registration.setUserNameAttributeName(userNameAttributeName); 214 registration.setUserNameAttributeName(userNameAttributeName);
206 registration.setJwkSetUri(jwkSetUri); 215 registration.setJwkSetUri(jwkSetUri);
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.dao.oauth2; 16 package org.thingsboard.server.dao.oauth2;
17 17
18 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 18 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  19 +import org.thingsboard.server.common.data.oauth2.PlatformType;
19 import org.thingsboard.server.common.data.oauth2.SchemeType; 20 import org.thingsboard.server.common.data.oauth2.SchemeType;
20 import org.thingsboard.server.dao.Dao; 21 import org.thingsboard.server.dao.Dao;
21 22
@@ -24,7 +25,7 @@ import java.util.UUID; @@ -24,7 +25,7 @@ import java.util.UUID;
24 25
25 public interface OAuth2RegistrationDao extends Dao<OAuth2Registration> { 26 public interface OAuth2RegistrationDao extends Dao<OAuth2Registration> {
26 27
27 - List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName); 28 + List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List<SchemeType> domainSchemes, String domainName, String pkgName, PlatformType platformType);
28 29
29 List<OAuth2Registration> findByOAuth2ParamsId(UUID oauth2ParamsId); 30 List<OAuth2Registration> findByOAuth2ParamsId(UUID oauth2ParamsId);
30 31
@@ -65,8 +65,8 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -65,8 +65,8 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
65 private OAuth2MobileDao oauth2MobileDao; 65 private OAuth2MobileDao oauth2MobileDao;
66 66
67 @Override 67 @Override
68 - public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName) {  
69 - log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName); 68 + public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName, PlatformType platformType) {
  69 + log.trace("Executing getOAuth2Clients [{}://{}] pkgName=[{}] platformType=[{}]", domainSchemeStr, domainName, pkgName, platformType);
70 if (domainSchemeStr == null) { 70 if (domainSchemeStr == null) {
71 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); 71 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
72 } 72 }
@@ -77,7 +77,9 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -77,7 +77,9 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
77 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); 77 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
78 } 78 }
79 validateString(domainName, INCORRECT_DOMAIN_NAME + domainName); 79 validateString(domainName, INCORRECT_DOMAIN_NAME + domainName);
80 - return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName).stream() 80 + return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(
  81 + Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName, platformType)
  82 + .stream()
81 .map(OAuth2Utils::toClientInfo) 83 .map(OAuth2Utils::toClientInfo)
82 .collect(Collectors.toList()); 84 .collect(Collectors.toList());
83 } 85 }
@@ -127,6 +127,7 @@ public class OAuth2Utils { @@ -127,6 +127,7 @@ public class OAuth2Utils {
127 .authorizationUri(registration.getAuthorizationUri()) 127 .authorizationUri(registration.getAuthorizationUri())
128 .accessTokenUri(registration.getAccessTokenUri()) 128 .accessTokenUri(registration.getAccessTokenUri())
129 .scope(registration.getScope()) 129 .scope(registration.getScope())
  130 + .platforms(registration.getPlatforms())
130 .userInfoUri(registration.getUserInfoUri()) 131 .userInfoUri(registration.getUserInfoUri())
131 .userNameAttributeName(registration.getUserNameAttributeName()) 132 .userNameAttributeName(registration.getUserNameAttributeName())
132 .jwkSetUri(registration.getJwkSetUri()) 133 .jwkSetUri(registration.getJwkSetUri())
@@ -167,6 +168,7 @@ public class OAuth2Utils { @@ -167,6 +168,7 @@ public class OAuth2Utils {
167 registration.setAuthorizationUri(registrationInfo.getAuthorizationUri()); 168 registration.setAuthorizationUri(registrationInfo.getAuthorizationUri());
168 registration.setAccessTokenUri(registrationInfo.getAccessTokenUri()); 169 registration.setAccessTokenUri(registrationInfo.getAccessTokenUri());
169 registration.setScope(registrationInfo.getScope()); 170 registration.setScope(registrationInfo.getScope());
  171 + registration.setPlatforms(registrationInfo.getPlatforms());
170 registration.setUserInfoUri(registrationInfo.getUserInfoUri()); 172 registration.setUserInfoUri(registrationInfo.getUserInfoUri());
171 registration.setUserNameAttributeName(registrationInfo.getUserNameAttributeName()); 173 registration.setUserNameAttributeName(registrationInfo.getUserNameAttributeName());
172 registration.setJwkSetUri(registrationInfo.getJwkSetUri()); 174 registration.setJwkSetUri(registrationInfo.getJwkSetUri());
@@ -224,6 +226,7 @@ public class OAuth2Utils { @@ -224,6 +226,7 @@ public class OAuth2Utils {
224 .loginButtonLabel(clientRegistrationDto.getLoginButtonLabel()) 226 .loginButtonLabel(clientRegistrationDto.getLoginButtonLabel())
225 .loginButtonIcon(clientRegistrationDto.getLoginButtonIcon()) 227 .loginButtonIcon(clientRegistrationDto.getLoginButtonIcon())
226 .additionalInfo(clientRegistrationDto.getAdditionalInfo()) 228 .additionalInfo(clientRegistrationDto.getAdditionalInfo())
  229 + .platforms(Collections.emptyList())
227 .build(); 230 .build();
228 } 231 }
229 232
@@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor;
19 import org.springframework.data.repository.CrudRepository; 19 import org.springframework.data.repository.CrudRepository;
20 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
21 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 21 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  22 +import org.thingsboard.server.common.data.oauth2.PlatformType;
22 import org.thingsboard.server.common.data.oauth2.SchemeType; 23 import org.thingsboard.server.common.data.oauth2.SchemeType;
23 import org.thingsboard.server.dao.DaoUtil; 24 import org.thingsboard.server.dao.DaoUtil;
24 import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity; 25 import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
@@ -45,8 +46,9 @@ public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationE @@ -45,8 +46,9 @@ public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationE
45 } 46 }
46 47
47 @Override 48 @Override
48 - public List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName) {  
49 - return DaoUtil.convertDataList(repository.findAllEnabledByDomainSchemesNameAndPkgName(domainSchemes, domainName, pkgName)); 49 + public List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List<SchemeType> domainSchemes, String domainName, String pkgName, PlatformType platformType) {
  50 + return DaoUtil.convertDataList(repository.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(domainSchemes, domainName, pkgName,
  51 + platformType != null ? "%" + platformType.name() + "%" : null));
50 } 52 }
51 53
52 @Override 54 @Override
@@ -30,14 +30,15 @@ public interface OAuth2RegistrationRepository extends CrudRepository<OAuth2Regis @@ -30,14 +30,15 @@ public interface OAuth2RegistrationRepository extends CrudRepository<OAuth2Regis
30 "FROM OAuth2RegistrationEntity reg " + 30 "FROM OAuth2RegistrationEntity reg " +
31 "LEFT JOIN OAuth2ParamsEntity params on reg.oauth2ParamsId = params.id " + 31 "LEFT JOIN OAuth2ParamsEntity params on reg.oauth2ParamsId = params.id " +
32 "LEFT JOIN OAuth2DomainEntity domain on reg.oauth2ParamsId = domain.oauth2ParamsId " + 32 "LEFT JOIN OAuth2DomainEntity domain on reg.oauth2ParamsId = domain.oauth2ParamsId " +
33 - "LEFT JOIN OAuth2MobileEntity mobile on reg.oauth2ParamsId = mobile.oauth2ParamsId " +  
34 "WHERE params.enabled = true " + 33 "WHERE params.enabled = true " +
35 "AND domain.domainName = :domainName " + 34 "AND domain.domainName = :domainName " +
36 "AND domain.domainScheme IN (:domainSchemes) " + 35 "AND domain.domainScheme IN (:domainSchemes) " +
37 - "AND (:pkgName IS NULL OR mobile.pkgName = :pkgName)")  
38 - List<OAuth2RegistrationEntity> findAllEnabledByDomainSchemesNameAndPkgName(@Param("domainSchemes") List<SchemeType> domainSchemes,  
39 - @Param("domainName") String domainName,  
40 - @Param("pkgName") String pkgName); 36 + "AND (:pkgName IS NULL OR EXISTS (SELECT mobile FROM OAuth2MobileEntity mobile WHERE mobile.oauth2ParamsId = reg.oauth2ParamsId AND mobile.pkgName = :pkgName)) " +
  37 + "AND (:platformFilter IS NULL OR reg.platforms IS NULL OR reg.platforms = '' OR reg.platforms LIKE :platformFilter)")
  38 + List<OAuth2RegistrationEntity> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(@Param("domainSchemes") List<SchemeType> domainSchemes,
  39 + @Param("domainName") String domainName,
  40 + @Param("pkgName") String pkgName,
  41 + @Param("platformFilter") String platformFilter);
41 42
42 List<OAuth2RegistrationEntity> findByOauth2ParamsId(UUID oauth2ParamsId); 43 List<OAuth2RegistrationEntity> findByOauth2ParamsId(UUID oauth2ParamsId);
43 44
@@ -391,6 +391,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( @@ -391,6 +391,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration (
391 authorization_uri varchar(255), 391 authorization_uri varchar(255),
392 token_uri varchar(255), 392 token_uri varchar(255),
393 scope varchar(255), 393 scope varchar(255),
  394 + platforms varchar(255),
394 user_info_uri varchar(255), 395 user_info_uri varchar(255),
395 user_name_attribute_name varchar(255), 396 user_name_attribute_name varchar(255),
396 jwk_set_uri varchar(255), 397 jwk_set_uri varchar(255),
@@ -428,6 +428,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( @@ -428,6 +428,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration (
428 authorization_uri varchar(255), 428 authorization_uri varchar(255),
429 token_uri varchar(255), 429 token_uri varchar(255),
430 scope varchar(255), 430 scope varchar(255),
  431 + platforms varchar(255),
431 user_info_uri varchar(255), 432 user_info_uri varchar(255),
432 user_name_attribute_name varchar(255), 433 user_name_attribute_name varchar(255),
433 jwk_set_uri varchar(255), 434 jwk_set_uri varchar(255),
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.dao.service; 16 package org.thingsboard.server.dao.service;
17 17
  18 +import com.fasterxml.jackson.databind.node.ObjectNode;
18 import com.google.common.collect.Lists; 19 import com.google.common.collect.Lists;
19 import org.junit.After; 20 import org.junit.After;
20 import org.junit.Assert; 21 import org.junit.Assert;
@@ -31,6 +32,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2MobileInfo; @@ -31,6 +32,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2MobileInfo;
31 import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo; 32 import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo;
32 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 33 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
33 import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo; 34 import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
  35 +import org.thingsboard.server.common.data.oauth2.PlatformType;
34 import org.thingsboard.server.common.data.oauth2.SchemeType; 36 import org.thingsboard.server.common.data.oauth2.SchemeType;
35 import org.thingsboard.server.dao.exception.DataValidationException; 37 import org.thingsboard.server.dao.exception.DataValidationException;
36 import org.thingsboard.server.dao.oauth2.OAuth2Service; 38 import org.thingsboard.server.dao.oauth2.OAuth2Service;
@@ -231,10 +233,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -231,10 +233,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
231 registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null)) 233 registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
232 .collect(Collectors.toList()); 234 .collect(Collectors.toList());
233 235
234 - List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null); 236 + List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null, null);
235 Assert.assertTrue(nonExistentDomainClients.isEmpty()); 237 Assert.assertTrue(nonExistentDomainClients.isEmpty());
236 238
237 - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null); 239 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
238 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); 240 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
239 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 241 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
240 Assert.assertTrue( 242 Assert.assertTrue(
@@ -244,10 +246,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -244,10 +246,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
244 ); 246 );
245 }); 247 });
246 248
247 - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null); 249 + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
248 Assert.assertTrue(firstDomainHttpsClients.isEmpty()); 250 Assert.assertTrue(firstDomainHttpsClients.isEmpty());
249 251
250 - List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null); 252 + List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null, null);
251 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size()); 253 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size());
252 secondGroupClientInfos.forEach(secondGroupClientInfo -> { 254 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
253 Assert.assertTrue( 255 Assert.assertTrue(
@@ -256,7 +258,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -256,7 +258,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
256 && clientInfo.getName().equals(secondGroupClientInfo.getName())) 258 && clientInfo.getName().equals(secondGroupClientInfo.getName()))
257 ); 259 );
258 }); 260 });
259 - List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null); 261 + List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null, null);
260 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size()); 262 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size());
261 secondGroupClientInfos.forEach(secondGroupClientInfo -> { 263 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
262 Assert.assertTrue( 264 Assert.assertTrue(
@@ -266,7 +268,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -266,7 +268,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
266 ); 268 );
267 }); 269 });
268 270
269 - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); 271 + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
270 Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size()); 272 Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size());
271 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 273 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
272 Assert.assertTrue( 274 Assert.assertTrue(
@@ -283,7 +285,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -283,7 +285,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
283 ); 285 );
284 }); 286 });
285 287
286 - List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null); 288 + List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null, null);
287 Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size()); 289 Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size());
288 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 290 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
289 Assert.assertTrue( 291 Assert.assertTrue(
@@ -331,7 +333,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -331,7 +333,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
331 registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null)) 333 registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
332 .collect(Collectors.toList()); 334 .collect(Collectors.toList());
333 335
334 - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null); 336 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
335 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); 337 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
336 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 338 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
337 Assert.assertTrue( 339 Assert.assertTrue(
@@ -341,7 +343,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -341,7 +343,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
341 ); 343 );
342 }); 344 });
343 345
344 - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null); 346 + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
345 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size()); 347 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size());
346 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 348 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
347 Assert.assertTrue( 349 Assert.assertTrue(
@@ -381,13 +383,13 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -381,13 +383,13 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
381 383
382 oAuth2Service.saveOAuth2Info(oAuth2Info); 384 oAuth2Service.saveOAuth2Info(oAuth2Info);
383 385
384 - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); 386 + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
385 Assert.assertEquals(5, secondDomainHttpClients.size()); 387 Assert.assertEquals(5, secondDomainHttpClients.size());
386 388
387 oAuth2Info.setEnabled(false); 389 oAuth2Info.setEnabled(false);
388 oAuth2Service.saveOAuth2Info(oAuth2Info); 390 oAuth2Service.saveOAuth2Info(oAuth2Info);
389 391
390 - List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); 392 + List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
391 Assert.assertEquals(0, secondDomainHttpDisabledClients.size()); 393 Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
392 } 394 }
393 395
@@ -520,7 +522,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -520,7 +522,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
520 OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info(); 522 OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
521 Assert.assertEquals(oAuth2Info, foundOAuth2Info); 523 Assert.assertEquals(oAuth2Info, foundOAuth2Info);
522 524
523 - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1"); 525 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
524 Assert.assertEquals(3, firstDomainHttpClients.size()); 526 Assert.assertEquals(3, firstDomainHttpClients.size());
525 for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) { 527 for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) {
526 String[] segments = clientInfo.getUrl().split("/"); 528 String[] segments = clientInfo.getUrl().split("/");
@@ -536,6 +538,56 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -536,6 +538,56 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
536 } 538 }
537 } 539 }
538 540
  541 + @Test
  542 + public void testFindClientsByPackageAndPlatform() {
  543 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  544 + OAuth2ParamsInfo.builder()
  545 + .domainInfos(Lists.newArrayList(
  546 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  547 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  548 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
  549 + ))
  550 + .mobileInfos(Lists.newArrayList(
  551 + OAuth2MobileInfo.builder().pkgName("com.test.pkg1").callbackUrlScheme("testPkg1Callback").build(),
  552 + OAuth2MobileInfo.builder().pkgName("com.test.pkg2").callbackUrlScheme("testPkg2Callback").build()
  553 + ))
  554 + .clientRegistrations(Lists.newArrayList(
  555 + validRegistrationInfo("Google", Arrays.asList(PlatformType.WEB, PlatformType.ANDROID)),
  556 + validRegistrationInfo("Facebook", Arrays.asList(PlatformType.IOS)),
  557 + validRegistrationInfo("GitHub", Collections.emptyList())
  558 + ))
  559 + .build(),
  560 + OAuth2ParamsInfo.builder()
  561 + .domainInfos(Lists.newArrayList(
  562 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  563 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
  564 + ))
  565 + .mobileInfos(Collections.emptyList())
  566 + .clientRegistrations(Lists.newArrayList(
  567 + validRegistrationInfo(),
  568 + validRegistrationInfo()
  569 + ))
  570 + .build()
  571 + ));
  572 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  573 +
  574 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  575 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
  576 +
  577 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
  578 + Assert.assertEquals(3, firstDomainHttpClients.size());
  579 + List<OAuth2ClientInfo> pkg1Clients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
  580 + Assert.assertEquals(3, pkg1Clients.size());
  581 + List<OAuth2ClientInfo> pkg1AndroidClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.ANDROID);
  582 + Assert.assertEquals(2, pkg1AndroidClients.size());
  583 + Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("Google")));
  584 + Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
  585 + List<OAuth2ClientInfo> pkg1IOSClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.IOS);
  586 + Assert.assertEquals(2, pkg1IOSClients.size());
  587 + Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("Facebook")));
  588 + Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
  589 + }
  590 +
539 private OAuth2Info createDefaultOAuth2Info() { 591 private OAuth2Info createDefaultOAuth2Info() {
540 return new OAuth2Info(true, Lists.newArrayList( 592 return new OAuth2Info(true, Lists.newArrayList(
541 OAuth2ParamsInfo.builder() 593 OAuth2ParamsInfo.builder()
@@ -567,17 +619,22 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -567,17 +619,22 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
567 } 619 }
568 620
569 private OAuth2RegistrationInfo validRegistrationInfo() { 621 private OAuth2RegistrationInfo validRegistrationInfo() {
  622 + return validRegistrationInfo(null, Collections.emptyList());
  623 + }
  624 +
  625 + private OAuth2RegistrationInfo validRegistrationInfo(String label, List<PlatformType> platforms) {
570 return OAuth2RegistrationInfo.builder() 626 return OAuth2RegistrationInfo.builder()
571 .clientId(UUID.randomUUID().toString()) 627 .clientId(UUID.randomUUID().toString())
572 .clientSecret(UUID.randomUUID().toString()) 628 .clientSecret(UUID.randomUUID().toString())
573 .authorizationUri(UUID.randomUUID().toString()) 629 .authorizationUri(UUID.randomUUID().toString())
574 .accessTokenUri(UUID.randomUUID().toString()) 630 .accessTokenUri(UUID.randomUUID().toString())
575 .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString())) 631 .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
  632 + .platforms(platforms == null ? Collections.emptyList() : platforms)
576 .userInfoUri(UUID.randomUUID().toString()) 633 .userInfoUri(UUID.randomUUID().toString())
577 .userNameAttributeName(UUID.randomUUID().toString()) 634 .userNameAttributeName(UUID.randomUUID().toString())
578 .jwkSetUri(UUID.randomUUID().toString()) 635 .jwkSetUri(UUID.randomUUID().toString())
579 .clientAuthenticationMethod(UUID.randomUUID().toString()) 636 .clientAuthenticationMethod(UUID.randomUUID().toString())
580 - .loginButtonLabel(UUID.randomUUID().toString()) 637 + .loginButtonLabel(label != null ? label : UUID.randomUUID().toString())
581 .loginButtonIcon(UUID.randomUUID().toString()) 638 .loginButtonIcon(UUID.randomUUID().toString())
582 .additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString())) 639 .additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
583 .mapperConfig( 640 .mapperConfig(
@@ -44,7 +44,7 @@ import { AdminService } from '@core/http/admin.service'; @@ -44,7 +44,7 @@ import { AdminService } from '@core/http/admin.service';
44 import { ActionNotificationShow } from '@core/notification/notification.actions'; 44 import { ActionNotificationShow } from '@core/notification/notification.actions';
45 import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; 45 import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
46 import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component'; 46 import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
47 -import { OAuth2ClientInfo } from '@shared/models/oauth2.models'; 47 +import { OAuth2ClientInfo, PlatformType } from '@shared/models/oauth2.models';
48 import { isDefinedAndNotNull, isMobileApp } from '@core/utils'; 48 import { isDefinedAndNotNull, isMobileApp } from '@core/utils';
49 49
50 @Injectable({ 50 @Injectable({
@@ -204,11 +204,8 @@ export class AuthService { @@ -204,11 +204,8 @@ export class AuthService {
204 } 204 }
205 } 205 }
206 206
207 - public loadOAuth2Clients(pkgName?: string): Observable<Array<OAuth2ClientInfo>> {  
208 - let url = '/api/noauth/oauth2Clients';  
209 - if (isDefinedAndNotNull(pkgName)) {  
210 - url += `?pkgName=${pkgName}`;  
211 - } 207 + public loadOAuth2Clients(): Observable<Array<OAuth2ClientInfo>> {
  208 + const url = '/api/noauth/oauth2Clients?platform=' + PlatformType.WEB;
212 return this.http.post<Array<OAuth2ClientInfo>>(url, 209 return this.http.post<Array<OAuth2ClientInfo>>(url,
213 null, defaultHttpOptions()).pipe( 210 null, defaultHttpOptions()).pipe(
214 catchError(err => of([])), 211 catchError(err => of([])),
@@ -201,18 +201,27 @@ @@ -201,18 +201,27 @@
201 201
202 <ng-template matExpansionPanelContent> 202 <ng-template matExpansionPanelContent>
203 <section [formGroupName]="j"> 203 <section [formGroupName]="j">
204 - <section formGroupName="additionalInfo" fxLayout="row">  
205 - <mat-form-field fxFlex class="mat-block">  
206 - <mat-label translate>admin.oauth2.login-provider</mat-label>  
207 - <mat-select formControlName="providerName">  
208 - <mat-option *ngFor="let provider of templateProvider" [value]="provider">  
209 - {{ provider }} 204 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  205 + <section fxFlex formGroupName="additionalInfo" fxLayout="row">
  206 + <mat-form-field fxFlex class="mat-block">
  207 + <mat-label translate>admin.oauth2.login-provider</mat-label>
  208 + <mat-select formControlName="providerName">
  209 + <mat-option *ngFor="let provider of templateProvider" [value]="provider">
  210 + {{ provider }}
  211 + </mat-option>
  212 + </mat-select>
  213 + </mat-form-field>
  214 + <div [tb-help]="getHelpLink(registration)" *ngIf="!isCustomProvider(registration)"></div>
  215 + </section>
  216 + <mat-form-field floatLabel="always" fxFlex class="mat-block">
  217 + <mat-label translate>admin.oauth2.allowed-platforms</mat-label>
  218 + <mat-select formControlName="platforms" multiple placeholder="{{ 'admin.oauth2.all-platforms' | translate }}">
  219 + <mat-option *ngFor="let platform of platformTypes" [value]="platform">
  220 + {{ platformTypeTranslations.get(platform) | translate }}
210 </mat-option> 221 </mat-option>
211 </mat-select> 222 </mat-select>
212 </mat-form-field> 223 </mat-form-field>
213 - <div [tb-help]="getHelpLink(registration)" *ngIf="!isCustomProvider(registration)"></div>  
214 - </section>  
215 - 224 + </div>
216 <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> 225 <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
217 <mat-form-field fxFlex class="mat-block"> 226 <mat-form-field fxFlex class="mat-block">
218 <mat-label translate>admin.oauth2.client-id</mat-label> 227 <mat-label translate>admin.oauth2.client-id</mat-label>
@@ -28,7 +28,8 @@ import { @@ -28,7 +28,8 @@ import {
28 OAuth2DomainInfo, 28 OAuth2DomainInfo,
29 OAuth2Info, OAuth2MobileInfo, 29 OAuth2Info, OAuth2MobileInfo,
30 OAuth2ParamsInfo, 30 OAuth2ParamsInfo,
31 - OAuth2RegistrationInfo, 31 + OAuth2RegistrationInfo, PlatformType,
  32 + platformTypeTranslations,
32 TenantNameStrategy 33 TenantNameStrategy
33 } from '@shared/models/oauth2.models'; 34 } from '@shared/models/oauth2.models';
34 import { Store } from '@ngrx/store'; 35 import { Store } from '@ngrx/store';
@@ -99,6 +100,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -99,6 +100,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
99 tenantNameStrategies = Object.keys(TenantNameStrategy); 100 tenantNameStrategies = Object.keys(TenantNameStrategy);
100 protocols = Object.keys(DomainSchema); 101 protocols = Object.keys(DomainSchema);
101 domainSchemaTranslations = domainSchemaTranslations; 102 domainSchemaTranslations = domainSchemaTranslations;
  103 + platformTypes = Object.keys(PlatformType);
  104 + platformTypeTranslations = platformTypeTranslations;
102 105
103 templateProvider = ['Custom']; 106 templateProvider = ['Custom'];
104 107
@@ -293,6 +296,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -293,6 +296,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
293 additionalInfo: this.fb.group({ 296 additionalInfo: this.fb.group({
294 providerName: [additionalInfo?.providerName ? additionalInfo?.providerName : defaultProviderName, Validators.required] 297 providerName: [additionalInfo?.providerName ? additionalInfo?.providerName : defaultProviderName, Validators.required]
295 }), 298 }),
  299 + platforms: [registration?.platforms ? registration.platforms : []],
296 loginButtonLabel: [registration?.loginButtonLabel ? registration.loginButtonLabel : null, Validators.required], 300 loginButtonLabel: [registration?.loginButtonLabel ? registration.loginButtonLabel : null, Validators.required],
297 loginButtonIcon: [registration?.loginButtonIcon ? registration.loginButtonIcon : null], 301 loginButtonIcon: [registration?.loginButtonIcon ? registration.loginButtonIcon : null],
298 clientId: [registration?.clientId ? registration.clientId : '', Validators.required], 302 clientId: [registration?.clientId ? registration.clientId : '', Validators.required],
@@ -63,6 +63,20 @@ export enum TenantNameStrategy{ @@ -63,6 +63,20 @@ export enum TenantNameStrategy{
63 CUSTOM = 'CUSTOM' 63 CUSTOM = 'CUSTOM'
64 } 64 }
65 65
  66 +export enum PlatformType {
  67 + WEB = 'WEB',
  68 + ANDROID = 'ANDROID',
  69 + IOS = 'IOS'
  70 +}
  71 +
  72 +export const platformTypeTranslations = new Map<PlatformType, string>(
  73 + [
  74 + [PlatformType.WEB, 'admin.oauth2.platform-web'],
  75 + [PlatformType.ANDROID, 'admin.oauth2.platform-android'],
  76 + [PlatformType.IOS, 'admin.oauth2.platform-ios']
  77 + ]
  78 +);
  79 +
66 export interface OAuth2ClientRegistrationTemplate extends OAuth2RegistrationInfo{ 80 export interface OAuth2ClientRegistrationTemplate extends OAuth2RegistrationInfo{
67 comment: string; 81 comment: string;
68 createdTime: number; 82 createdTime: number;
@@ -80,6 +94,7 @@ export interface OAuth2RegistrationInfo { @@ -80,6 +94,7 @@ export interface OAuth2RegistrationInfo {
80 accessTokenUri: string; 94 accessTokenUri: string;
81 authorizationUri: string; 95 authorizationUri: string;
82 scope: string[]; 96 scope: string[];
  97 + platforms: PlatformType[];
83 jwkSetUri?: string; 98 jwkSetUri?: string;
84 userInfoUri: string; 99 userInfoUri: string;
85 clientAuthenticationMethod: ClientAuthenticationMethod; 100 clientAuthenticationMethod: ClientAuthenticationMethod;
@@ -228,7 +228,12 @@ @@ -228,7 +228,12 @@
228 "mobile-callback-url-scheme": "Callback URL scheme", 228 "mobile-callback-url-scheme": "Callback URL scheme",
229 "add-mobile-app": "Add application", 229 "add-mobile-app": "Add application",
230 "delete-mobile-app": "Delete application info", 230 "delete-mobile-app": "Delete application info",
231 - "providers": "Providers" 231 + "providers": "Providers",
  232 + "platform-web": "Web",
  233 + "platform-android": "Android",
  234 + "platform-ios": "iOS",
  235 + "all-platforms": "All platforms",
  236 + "allowed-platforms": "Allowed platforms"
232 } 237 }
233 }, 238 },
234 "alarm": { 239 "alarm": {