Showing
16 changed files
with
216 additions
and
55 deletions
... | ... | @@ -7,7 +7,10 @@ |
7 | 7 | "userInfoUri": "https://api.github.com/user", |
8 | 8 | "clientAuthenticationMethod": "BASIC", |
9 | 9 | "userNameAttributeName": "login", |
10 | - "basic": {}, | |
10 | + "basic": { | |
11 | + "lastNameAttributeKey": "name", | |
12 | + "tenantNameStrategy": "DOMAIN" | |
13 | + }, | |
11 | 14 | "comment": "In order to log into ThingsBoard you need to have user's email. You may configure and use Custom OAuth2 Mapper to get email information. Please refer to <a href=\"https://docs.github.com/en/rest/reference/users#list-email-addresses-for-the-authenticated-user\">Github Documentation</a>", |
12 | 15 | "loginButtonIcon": "mdi:github", |
13 | 16 | "loginButtonLabel": "Github", | ... | ... |
... | ... | @@ -67,6 +67,7 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( |
67 | 67 | user_name_attribute_name varchar(255), |
68 | 68 | jwk_set_uri varchar(255), |
69 | 69 | client_authentication_method varchar(255), |
70 | + type varchar(31), | |
70 | 71 | basic_email_attribute_key varchar(31), |
71 | 72 | basic_first_name_attribute_key varchar(31), |
72 | 73 | basic_last_name_attribute_key varchar(31), | ... | ... |
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicMapperUtils.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2020 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.service.security.auth.oauth2; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.apache.commons.lang3.text.StrSubstitutor; | |
20 | +import org.springframework.util.StringUtils; | |
21 | +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; | |
22 | +import org.thingsboard.server.dao.oauth2.OAuth2User; | |
23 | + | |
24 | +import java.util.Map; | |
25 | + | |
26 | +@Slf4j | |
27 | +public class BasicMapperUtils { | |
28 | + private static final String START_PLACEHOLDER_PREFIX = "%{"; | |
29 | + private static final String END_PLACEHOLDER_PREFIX = "}"; | |
30 | + | |
31 | + public static OAuth2User getOAuth2User(String email, Map<String, Object> attributes, OAuth2MapperConfig config) { | |
32 | + OAuth2User oauth2User = new OAuth2User(); | |
33 | + oauth2User.setEmail(email); | |
34 | + oauth2User.setTenantName(getTenantName(email, attributes, config)); | |
35 | + if (!StringUtils.isEmpty(config.getBasic().getLastNameAttributeKey())) { | |
36 | + String lastName = getStringAttributeByKey(attributes, config.getBasic().getLastNameAttributeKey()); | |
37 | + oauth2User.setLastName(lastName); | |
38 | + } | |
39 | + if (!StringUtils.isEmpty(config.getBasic().getFirstNameAttributeKey())) { | |
40 | + String firstName = getStringAttributeByKey(attributes, config.getBasic().getFirstNameAttributeKey()); | |
41 | + oauth2User.setFirstName(firstName); | |
42 | + } | |
43 | + if (!StringUtils.isEmpty(config.getBasic().getCustomerNamePattern())) { | |
44 | + StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | |
45 | + String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); | |
46 | + oauth2User.setCustomerName(customerName); | |
47 | + } | |
48 | + oauth2User.setAlwaysFullScreen(config.getBasic().isAlwaysFullScreen()); | |
49 | + if (!StringUtils.isEmpty(config.getBasic().getDefaultDashboardName())) { | |
50 | + oauth2User.setDefaultDashboardName(config.getBasic().getDefaultDashboardName()); | |
51 | + } | |
52 | + return oauth2User; | |
53 | + } | |
54 | + | |
55 | + public static String getTenantName(String email, Map<String, Object> attributes, OAuth2MapperConfig config) { | |
56 | + switch (config.getBasic().getTenantNameStrategy()) { | |
57 | + case EMAIL: | |
58 | + return email; | |
59 | + case DOMAIN: | |
60 | + return email.substring(email .indexOf("@") + 1); | |
61 | + case CUSTOM: | |
62 | + StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | |
63 | + return sub.replace(config.getBasic().getTenantNamePattern()); | |
64 | + default: | |
65 | + throw new RuntimeException("Tenant Name Strategy with type " + config.getBasic().getTenantNameStrategy() + " is not supported!"); | |
66 | + } | |
67 | + } | |
68 | + | |
69 | + public static String getStringAttributeByKey(Map<String, Object> attributes, String key) { | |
70 | + String result = null; | |
71 | + try { | |
72 | + result = (String) attributes.get(key); | |
73 | + } catch (Exception e) { | |
74 | + log.warn("Can't convert attribute to String by key " + key); | |
75 | + } | |
76 | + return result; | |
77 | + } | |
78 | +} | ... | ... |
... | ... | @@ -16,10 +16,8 @@ |
16 | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.apache.commons.lang3.text.StrSubstitutor; | |
20 | 19 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
21 | 20 | import org.springframework.stereotype.Service; |
22 | -import org.springframework.util.StringUtils; | |
23 | 21 | import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; |
24 | 22 | import org.thingsboard.server.dao.oauth2.OAuth2User; |
25 | 23 | import org.thingsboard.server.service.security.model.SecurityUser; |
... | ... | @@ -30,59 +28,12 @@ import java.util.Map; |
30 | 28 | @Slf4j |
31 | 29 | public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { |
32 | 30 | |
33 | - private static final String START_PLACEHOLDER_PREFIX = "%{"; | |
34 | - private static final String END_PLACEHOLDER_PREFIX = "}"; | |
35 | - | |
36 | 31 | @Override |
37 | 32 | public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2MapperConfig config) { |
38 | - OAuth2User oauth2User = new OAuth2User(); | |
39 | 33 | Map<String, Object> attributes = token.getPrincipal().getAttributes(); |
40 | - String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | |
41 | - oauth2User.setEmail(email); | |
42 | - oauth2User.setTenantName(getTenantName(attributes, config)); | |
43 | - if (!StringUtils.isEmpty(config.getBasic().getLastNameAttributeKey())) { | |
44 | - String lastName = getStringAttributeByKey(attributes, config.getBasic().getLastNameAttributeKey()); | |
45 | - oauth2User.setLastName(lastName); | |
46 | - } | |
47 | - if (!StringUtils.isEmpty(config.getBasic().getFirstNameAttributeKey())) { | |
48 | - String firstName = getStringAttributeByKey(attributes, config.getBasic().getFirstNameAttributeKey()); | |
49 | - oauth2User.setFirstName(firstName); | |
50 | - } | |
51 | - if (!StringUtils.isEmpty(config.getBasic().getCustomerNamePattern())) { | |
52 | - StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | |
53 | - String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); | |
54 | - oauth2User.setCustomerName(customerName); | |
55 | - } | |
56 | - oauth2User.setAlwaysFullScreen(config.getBasic().isAlwaysFullScreen()); | |
57 | - if (!StringUtils.isEmpty(config.getBasic().getDefaultDashboardName())) { | |
58 | - oauth2User.setDefaultDashboardName(config.getBasic().getDefaultDashboardName()); | |
59 | - } | |
34 | + String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | |
35 | + OAuth2User oauth2User = BasicMapperUtils.getOAuth2User(email, attributes, config); | |
60 | 36 | |
61 | 37 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); |
62 | 38 | } |
63 | - | |
64 | - private String getTenantName(Map<String, Object> attributes, OAuth2MapperConfig config) { | |
65 | - switch (config.getBasic().getTenantNameStrategy()) { | |
66 | - case EMAIL: | |
67 | - return getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | |
68 | - case DOMAIN: | |
69 | - String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | |
70 | - return email.substring(email .indexOf("@") + 1); | |
71 | - case CUSTOM: | |
72 | - StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | |
73 | - return sub.replace(config.getBasic().getTenantNamePattern()); | |
74 | - default: | |
75 | - throw new RuntimeException("Tenant Name Strategy with type " + config.getBasic().getTenantNameStrategy() + " is not supported!"); | |
76 | - } | |
77 | - } | |
78 | - | |
79 | - private String getStringAttributeByKey(Map<String, Object> attributes, String key) { | |
80 | - String result = null; | |
81 | - try { | |
82 | - result = (String) attributes.get(key); | |
83 | - } catch (Exception e) { | |
84 | - log.warn("Can't convert attribute to String by key " + key); | |
85 | - } | |
86 | - return result; | |
87 | - } | |
88 | 39 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2020 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.service.security.auth.oauth2; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import lombok.ToString; | |
20 | +import lombok.extern.slf4j.Slf4j; | |
21 | +import org.springframework.beans.factory.annotation.Autowired; | |
22 | +import org.springframework.boot.web.client.RestTemplateBuilder; | |
23 | +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | |
24 | +import org.springframework.stereotype.Service; | |
25 | +import org.springframework.web.client.RestTemplate; | |
26 | +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; | |
27 | +import org.thingsboard.server.dao.oauth2.OAuth2Configuration; | |
28 | +import org.thingsboard.server.dao.oauth2.OAuth2User; | |
29 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
30 | + | |
31 | +import java.util.ArrayList; | |
32 | +import java.util.Map; | |
33 | +import java.util.Optional; | |
34 | + | |
35 | +@Service(value = "githubOAuth2ClientMapper") | |
36 | +@Slf4j | |
37 | +public class GithubOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { | |
38 | + private static final String EMAIL_URL_KEY = "emailUrl"; | |
39 | + | |
40 | + private static final String AUTHORIZATION = "Authorization"; | |
41 | + | |
42 | + private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); | |
43 | + | |
44 | + @Autowired | |
45 | + private OAuth2Configuration oAuth2Configuration; | |
46 | + | |
47 | + @Override | |
48 | + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2MapperConfig config) { | |
49 | + Map<String, String> githubMapperConfig = oAuth2Configuration.getGithubMapper(); | |
50 | + String email = getEmail(githubMapperConfig.get(EMAIL_URL_KEY), providerAccessToken); | |
51 | + Map<String, Object> attributes = token.getPrincipal().getAttributes(); | |
52 | + OAuth2User oAuth2User = BasicMapperUtils.getOAuth2User(email, attributes, config); | |
53 | + return getOrCreateSecurityUserFromOAuth2User(oAuth2User, config.isAllowUserCreation(), config.isActivateUser()); | |
54 | + } | |
55 | + | |
56 | + private synchronized String getEmail(String emailUrl, String oauth2Token) { | |
57 | + restTemplateBuilder = restTemplateBuilder.defaultHeader(AUTHORIZATION, "token " + oauth2Token); | |
58 | + | |
59 | + RestTemplate restTemplate = restTemplateBuilder.build(); | |
60 | + GithubEmailsResponse githubEmailsResponse; | |
61 | + try { | |
62 | + githubEmailsResponse = restTemplate.getForEntity(emailUrl, GithubEmailsResponse.class).getBody(); | |
63 | + if (githubEmailsResponse == null){ | |
64 | + throw new RuntimeException("Empty Github response!"); | |
65 | + } | |
66 | + } catch (Exception e) { | |
67 | + log.error("There was an error during connection to Github API", e); | |
68 | + throw new RuntimeException("Unable to login. Please contact your Administrator!"); | |
69 | + } | |
70 | + Optional<String> emailOpt = githubEmailsResponse.stream() | |
71 | + .filter(GithubEmailResponse::isPrimary) | |
72 | + .map(GithubEmailResponse::getEmail) | |
73 | + .findAny(); | |
74 | + if (emailOpt.isPresent()){ | |
75 | + return emailOpt.get(); | |
76 | + } else { | |
77 | + log.error("Could not find primary email from {}.", githubEmailsResponse); | |
78 | + throw new RuntimeException("Unable to login. Please contact your Administrator!"); | |
79 | + } | |
80 | + } | |
81 | + private static class GithubEmailsResponse extends ArrayList<GithubEmailResponse> {} | |
82 | + | |
83 | + @Data | |
84 | + @ToString | |
85 | + private static class GithubEmailResponse { | |
86 | + private String email; | |
87 | + private boolean verified; | |
88 | + private boolean primary; | |
89 | + private String visibility; | |
90 | + } | |
91 | +} | ... | ... |
... | ... | @@ -33,12 +33,18 @@ public class OAuth2ClientMapperProvider { |
33 | 33 | @Qualifier("customOAuth2ClientMapper") |
34 | 34 | private OAuth2ClientMapper customOAuth2ClientMapper; |
35 | 35 | |
36 | + @Autowired | |
37 | + @Qualifier("githubOAuth2ClientMapper") | |
38 | + private OAuth2ClientMapper githubOAuth2ClientMapper; | |
39 | + | |
36 | 40 | public OAuth2ClientMapper getOAuth2ClientMapperByType(MapperType oauth2MapperType) { |
37 | 41 | switch (oauth2MapperType) { |
38 | 42 | case CUSTOM: |
39 | 43 | return customOAuth2ClientMapper; |
40 | 44 | case BASIC: |
41 | 45 | return basicOAuth2ClientMapper; |
46 | + case GITHUB: | |
47 | + return githubOAuth2ClientMapper; | |
42 | 48 | default: |
43 | 49 | throw new RuntimeException("OAuth2ClientRegistrationMapper with type " + oauth2MapperType + " is not supported!"); |
44 | 50 | } | ... | ... |
... | ... | @@ -115,6 +115,8 @@ security: |
115 | 115 | oauth2: |
116 | 116 | # Redirect URL where access code from external user management system will be processed |
117 | 117 | loginProcessingUrl: "${SECURITY_OAUTH2_LOGIN_PROCESSING_URL:/login/oauth2/code/}" |
118 | + githubMapper: | |
119 | + emailUrl: "${SECURITY_OAUTH2_GITHUB_MAPPER_EMAIL_URL_KEY:https://api.github.com/user/emails}" | |
118 | 120 | |
119 | 121 | # Dashboard parameters |
120 | 122 | dashboard: | ... | ... |
... | ... | @@ -34,6 +34,7 @@ import java.util.List; |
34 | 34 | public class OAuth2ClientRegistrationTemplate extends SearchTextBasedWithAdditionalInfo<OAuth2ClientRegistrationTemplateId> implements HasName { |
35 | 35 | |
36 | 36 | private String providerId; |
37 | + private MapperType mapperType; | |
37 | 38 | private OAuth2BasicMapperConfig basic; |
38 | 39 | private String authorizationUri; |
39 | 40 | private String accessTokenUri; |
... | ... | @@ -50,6 +51,7 @@ public class OAuth2ClientRegistrationTemplate extends SearchTextBasedWithAdditio |
50 | 51 | public OAuth2ClientRegistrationTemplate(OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { |
51 | 52 | super(clientRegistrationTemplate); |
52 | 53 | this.providerId = clientRegistrationTemplate.providerId; |
54 | + this.mapperType = clientRegistrationTemplate.mapperType; | |
53 | 55 | this.basic = clientRegistrationTemplate.basic; |
54 | 56 | this.authorizationUri = clientRegistrationTemplate.authorizationUri; |
55 | 57 | this.accessTokenUri = clientRegistrationTemplate.accessTokenUri; | ... | ... |
... | ... | @@ -190,7 +190,7 @@ public abstract class AbstractOAuth2ClientRegistrationInfoEntity<T extends OAuth |
190 | 190 | .activateUser(activateUser) |
191 | 191 | .type(type) |
192 | 192 | .basic( |
193 | - type == MapperType.BASIC ? | |
193 | + (type == MapperType.BASIC || type == MapperType.GITHUB) ? | |
194 | 194 | OAuth2BasicMapperConfig.builder() |
195 | 195 | .emailAttributeKey(emailAttributeKey) |
196 | 196 | .firstNameAttributeKey(firstNameAttributeKey) | ... | ... |
... | ... | @@ -55,6 +55,9 @@ public class OAuth2ClientRegistrationTemplateEntity extends BaseSqlEntity<OAuth2 |
55 | 55 | private String jwkSetUri; |
56 | 56 | @Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY) |
57 | 57 | private String clientAuthenticationMethod; |
58 | + @Enumerated(EnumType.STRING) | |
59 | + @Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY) | |
60 | + private MapperType type; | |
58 | 61 | @Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY) |
59 | 62 | private String emailAttributeKey; |
60 | 63 | @Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY) |
... | ... | @@ -106,6 +109,7 @@ public class OAuth2ClientRegistrationTemplateEntity extends BaseSqlEntity<OAuth2 |
106 | 109 | this.loginButtonLabel = clientRegistrationTemplate.getLoginButtonLabel(); |
107 | 110 | this.helpLink = clientRegistrationTemplate.getHelpLink(); |
108 | 111 | this.additionalInfo = clientRegistrationTemplate.getAdditionalInfo(); |
112 | + this.type = clientRegistrationTemplate.getMapperType(); | |
109 | 113 | OAuth2BasicMapperConfig basicConfig = clientRegistrationTemplate.getBasic(); |
110 | 114 | if (basicConfig != null) { |
111 | 115 | this.emailAttributeKey = basicConfig.getEmailAttributeKey(); |
... | ... | @@ -126,6 +130,7 @@ public class OAuth2ClientRegistrationTemplateEntity extends BaseSqlEntity<OAuth2 |
126 | 130 | clientRegistrationTemplate.setCreatedTime(createdTime); |
127 | 131 | clientRegistrationTemplate.setAdditionalInfo(additionalInfo); |
128 | 132 | |
133 | + clientRegistrationTemplate.setMapperType(type); | |
129 | 134 | clientRegistrationTemplate.setProviderId(providerId); |
130 | 135 | clientRegistrationTemplate.setBasic( |
131 | 136 | OAuth2BasicMapperConfig.builder() | ... | ... |
... | ... | @@ -20,10 +20,12 @@ import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; |
21 | 21 | import org.springframework.context.annotation.Configuration; |
22 | 22 | |
23 | +import java.util.Map; | |
24 | + | |
23 | 25 | @Configuration |
24 | 26 | @ConfigurationProperties(prefix = "security.oauth2") |
25 | 27 | @Data |
26 | -@Slf4j | |
27 | 28 | public class OAuth2Configuration { |
28 | 29 | private String loginProcessingUrl; |
30 | + private Map<String, String> githubMapper; | |
29 | 31 | } | ... | ... |
... | ... | @@ -184,6 +184,22 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se |
184 | 184 | throw new DataValidationException("Tenant name pattern should be specified!"); |
185 | 185 | } |
186 | 186 | } |
187 | + if (mapperConfig.getType() == MapperType.GITHUB) { | |
188 | + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic(); | |
189 | + if (basicConfig == null) { | |
190 | + throw new DataValidationException("Basic config should be specified!"); | |
191 | + } | |
192 | + if (!StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) { | |
193 | + throw new DataValidationException("Email attribute key cannot be configured for GITHUB mapper type!"); | |
194 | + } | |
195 | + if (basicConfig.getTenantNameStrategy() == null) { | |
196 | + throw new DataValidationException("Tenant name strategy should be specified!"); | |
197 | + } | |
198 | + if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM | |
199 | + && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) { | |
200 | + throw new DataValidationException("Tenant name pattern should be specified!"); | |
201 | + } | |
202 | + } | |
187 | 203 | if (mapperConfig.getType() == MapperType.CUSTOM) { |
188 | 204 | OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom(); |
189 | 205 | if (customConfig == null) { | ... | ... |
... | ... | @@ -386,6 +386,7 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( |
386 | 386 | user_name_attribute_name varchar(255), |
387 | 387 | jwk_set_uri varchar(255), |
388 | 388 | client_authentication_method varchar(255), |
389 | + type varchar(31), | |
389 | 390 | basic_email_attribute_key varchar(31), |
390 | 391 | basic_first_name_attribute_key varchar(31), |
391 | 392 | basic_last_name_attribute_key varchar(31), | ... | ... |
... | ... | @@ -412,6 +412,7 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( |
412 | 412 | user_name_attribute_name varchar(255), |
413 | 413 | jwk_set_uri varchar(255), |
414 | 414 | client_authentication_method varchar(255), |
415 | + type varchar(31), | |
415 | 416 | basic_email_attribute_key varchar(31), |
416 | 417 | basic_first_name_attribute_key varchar(31), |
417 | 418 | basic_last_name_attribute_key varchar(31), | ... | ... |
... | ... | @@ -21,6 +21,7 @@ import org.junit.Before; |
21 | 21 | import org.junit.Test; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | +import org.thingsboard.server.common.data.oauth2.MapperType; | |
24 | 25 | import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig; |
25 | 26 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; |
26 | 27 | import org.thingsboard.server.dao.exception.DataValidationException; |
... | ... | @@ -105,6 +106,7 @@ public class BaseOAuth2ConfigTemplateServiceTest extends AbstractServiceTest { |
105 | 106 | OAuth2ClientRegistrationTemplate clientRegistrationTemplate = new OAuth2ClientRegistrationTemplate(); |
106 | 107 | clientRegistrationTemplate.setProviderId(providerId); |
107 | 108 | clientRegistrationTemplate.setAdditionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString())); |
109 | + clientRegistrationTemplate.setMapperType(MapperType.BASIC); | |
108 | 110 | clientRegistrationTemplate.setBasic( |
109 | 111 | OAuth2BasicMapperConfig.builder() |
110 | 112 | .firstNameAttributeKey("firstName") | ... | ... |