Commit 628ce7991da43b50aeeed7d349ea184cdfd96adc
Merge branch 'vzikratyi-tb-feature/dynamic-oauth2-new-table'
Showing
82 changed files
with
3738 additions
and
317 deletions
Too many changes to show.
To preserve performance only 82 of 88 files are displayed.
1 | +{ | ||
2 | + "providerId": "Facebook", | ||
3 | + "accessTokenUri": "https://graph.facebook.com/v2.8/oauth/access_token", | ||
4 | + "authorizationUri": "https://www.facebook.com/v2.8/dialog/oauth", | ||
5 | + "scope": ["email","public_profile"], | ||
6 | + "jwkSetUri": null, | ||
7 | + "userInfoUri": "https://graph.facebook.com/me?fields=id,name,first_name,last_name,email", | ||
8 | + "clientAuthenticationMethod": "BASIC", | ||
9 | + "userNameAttributeName": "email", | ||
10 | + "basic": { | ||
11 | + "emailAttributeKey": "email", | ||
12 | + "firstNameAttributeKey": "first_name", | ||
13 | + "lastNameAttributeKey": "last_name", | ||
14 | + "tenantNameStrategy": "DOMAIN" | ||
15 | + }, | ||
16 | + "comment": null, | ||
17 | + "loginButtonIcon": "mdi:facebook", | ||
18 | + "loginButtonLabel": "Facebook", | ||
19 | + "helpLink": "https://developers.facebook.com/docs/facebook-login/web#logindialog" | ||
20 | +} |
1 | +{ | ||
2 | + "providerId": "Github", | ||
3 | + "accessTokenUri": "https://github.com/login/oauth/access_token", | ||
4 | + "authorizationUri": "https://github.com/login/oauth/authorize", | ||
5 | + "scope": ["read:user","user:email"], | ||
6 | + "jwkSetUri": null, | ||
7 | + "userInfoUri": "https://api.github.com/user", | ||
8 | + "clientAuthenticationMethod": "BASIC", | ||
9 | + "userNameAttributeName": "login", | ||
10 | + "basic": { | ||
11 | + "tenantNameStrategy": "DOMAIN" | ||
12 | + }, | ||
13 | + "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>", | ||
14 | + "loginButtonIcon": "mdi:github", | ||
15 | + "loginButtonLabel": "Github", | ||
16 | + "helpLink": "https://docs.github.com/en/developers/apps/creating-an-oauth-app" | ||
17 | +} |
1 | +{ | ||
2 | + "providerId": "Google", | ||
3 | + "additionalInfo": null, | ||
4 | + "accessTokenUri": "https://oauth2.googleapis.com/token", | ||
5 | + "authorizationUri": "https://accounts.google.com/o/oauth2/v2/auth", | ||
6 | + "scope": ["email","openid","profile"], | ||
7 | + "jwkSetUri": "https://www.googleapis.com/oauth2/v3/certs", | ||
8 | + "userInfoUri": "https://openidconnect.googleapis.com/v1/userinfo", | ||
9 | + "clientAuthenticationMethod": "BASIC", | ||
10 | + "userNameAttributeName": "email", | ||
11 | + "basic": { | ||
12 | + "emailAttributeKey": "email", | ||
13 | + "firstNameAttributeKey": "given_name", | ||
14 | + "lastNameAttributeKey": "family_name", | ||
15 | + "tenantNameStrategy": "DOMAIN" | ||
16 | + }, | ||
17 | + "comment": null, | ||
18 | + "loginButtonIcon": "mdi:google", | ||
19 | + "loginButtonLabel": "Google", | ||
20 | + "helpLink": "https://developers.google.com/adwords/api/docs/guides/authentication" | ||
21 | +} |
@@ -14,6 +14,75 @@ | @@ -14,6 +14,75 @@ | ||
14 | -- limitations under the License. | 14 | -- limitations under the License. |
15 | -- | 15 | -- |
16 | 16 | ||
17 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( | ||
18 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, | ||
19 | + enabled boolean, | ||
20 | + created_time bigint NOT NULL, | ||
21 | + additional_info varchar, | ||
22 | + client_id varchar(255), | ||
23 | + client_secret varchar(255), | ||
24 | + authorization_uri varchar(255), | ||
25 | + token_uri varchar(255), | ||
26 | + scope varchar(255), | ||
27 | + user_info_uri varchar(255), | ||
28 | + user_name_attribute_name varchar(255), | ||
29 | + jwk_set_uri varchar(255), | ||
30 | + client_authentication_method varchar(255), | ||
31 | + login_button_label varchar(255), | ||
32 | + login_button_icon varchar(255), | ||
33 | + allow_user_creation boolean, | ||
34 | + activate_user boolean, | ||
35 | + type varchar(31), | ||
36 | + basic_email_attribute_key varchar(31), | ||
37 | + basic_first_name_attribute_key varchar(31), | ||
38 | + basic_last_name_attribute_key varchar(31), | ||
39 | + basic_tenant_name_strategy varchar(31), | ||
40 | + basic_tenant_name_pattern varchar(255), | ||
41 | + basic_customer_name_pattern varchar(255), | ||
42 | + basic_default_dashboard_name varchar(255), | ||
43 | + basic_always_full_screen boolean, | ||
44 | + custom_url varchar(255), | ||
45 | + custom_username varchar(255), | ||
46 | + custom_password varchar(255), | ||
47 | + custom_send_token boolean | ||
48 | +); | ||
49 | + | ||
50 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration ( | ||
51 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, | ||
52 | + created_time bigint NOT NULL, | ||
53 | + domain_name varchar(255), | ||
54 | + domain_scheme varchar(31), | ||
55 | + client_registration_info_id uuid | ||
56 | +); | ||
57 | + | ||
58 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | ||
59 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY, | ||
60 | + created_time bigint NOT NULL, | ||
61 | + additional_info varchar, | ||
62 | + provider_id varchar(255), | ||
63 | + authorization_uri varchar(255), | ||
64 | + token_uri varchar(255), | ||
65 | + scope varchar(255), | ||
66 | + user_info_uri varchar(255), | ||
67 | + user_name_attribute_name varchar(255), | ||
68 | + jwk_set_uri varchar(255), | ||
69 | + client_authentication_method varchar(255), | ||
70 | + type varchar(31), | ||
71 | + basic_email_attribute_key varchar(31), | ||
72 | + basic_first_name_attribute_key varchar(31), | ||
73 | + basic_last_name_attribute_key varchar(31), | ||
74 | + basic_tenant_name_strategy varchar(31), | ||
75 | + basic_tenant_name_pattern varchar(255), | ||
76 | + basic_customer_name_pattern varchar(255), | ||
77 | + basic_default_dashboard_name varchar(255), | ||
78 | + basic_always_full_screen boolean, | ||
79 | + comment varchar, | ||
80 | + login_button_icon varchar(255), | ||
81 | + login_button_label varchar(255), | ||
82 | + help_link varchar(255), | ||
83 | + CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) | ||
84 | +); | ||
85 | + | ||
17 | CREATE TABLE IF NOT EXISTS device_profile ( | 86 | CREATE TABLE IF NOT EXISTS device_profile ( |
18 | id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY, | 87 | id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY, |
19 | created_time bigint NOT NULL, | 88 | created_time bigint NOT NULL, |
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.config; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.beans.factory.annotation.Autowired; | ||
20 | +import org.springframework.security.crypto.keygen.Base64StringKeyGenerator; | ||
21 | +import org.springframework.security.crypto.keygen.StringKeyGenerator; | ||
22 | +import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||
23 | +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||
24 | +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; | ||
25 | +import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||
26 | +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||
27 | +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||
28 | +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||
29 | +import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; | ||
30 | +import org.springframework.security.oauth2.core.oidc.OidcScopes; | ||
31 | +import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; | ||
32 | +import org.springframework.security.web.util.UrlUtils; | ||
33 | +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | ||
34 | +import org.springframework.stereotype.Service; | ||
35 | +import org.springframework.util.CollectionUtils; | ||
36 | +import org.springframework.util.StringUtils; | ||
37 | +import org.springframework.web.util.UriComponents; | ||
38 | +import org.springframework.web.util.UriComponentsBuilder; | ||
39 | +import org.thingsboard.server.dao.oauth2.OAuth2Configuration; | ||
40 | +import org.thingsboard.server.utils.MiscUtils; | ||
41 | + | ||
42 | +import javax.servlet.http.HttpServletRequest; | ||
43 | +import java.nio.charset.StandardCharsets; | ||
44 | +import java.security.MessageDigest; | ||
45 | +import java.security.NoSuchAlgorithmException; | ||
46 | +import java.util.Base64; | ||
47 | +import java.util.HashMap; | ||
48 | +import java.util.Map; | ||
49 | + | ||
50 | +@Service | ||
51 | +@Slf4j | ||
52 | +public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver { | ||
53 | + public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization"; | ||
54 | + public static final String DEFAULT_LOGIN_PROCESSING_URI = "/login/oauth2/code/"; | ||
55 | + private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId"; | ||
56 | + private static final char PATH_DELIMITER = '/'; | ||
57 | + | ||
58 | + private final AntPathRequestMatcher authorizationRequestMatcher = new AntPathRequestMatcher( | ||
59 | + DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}"); | ||
60 | + private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder()); | ||
61 | + private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); | ||
62 | + | ||
63 | + @Autowired | ||
64 | + private ClientRegistrationRepository clientRegistrationRepository; | ||
65 | + | ||
66 | + @Autowired(required = false) | ||
67 | + private OAuth2Configuration oauth2Configuration; | ||
68 | + | ||
69 | + | ||
70 | + @Override | ||
71 | + public OAuth2AuthorizationRequest resolve(HttpServletRequest request) { | ||
72 | + String registrationId = this.resolveRegistrationId(request); | ||
73 | + String redirectUriAction = getAction(request, "login"); | ||
74 | + return resolve(request, registrationId, redirectUriAction); | ||
75 | + } | ||
76 | + | ||
77 | + @Override | ||
78 | + public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId) { | ||
79 | + if (registrationId == null) { | ||
80 | + return null; | ||
81 | + } | ||
82 | + String redirectUriAction = getAction(request, "authorize"); | ||
83 | + return resolve(request, registrationId, redirectUriAction); | ||
84 | + } | ||
85 | + | ||
86 | + private String getAction(HttpServletRequest request, String defaultAction) { | ||
87 | + String action = request.getParameter("action"); | ||
88 | + if (action == null) { | ||
89 | + return defaultAction; | ||
90 | + } | ||
91 | + return action; | ||
92 | + } | ||
93 | + | ||
94 | + private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) { | ||
95 | + if (registrationId == null) { | ||
96 | + return null; | ||
97 | + } | ||
98 | + | ||
99 | + ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); | ||
100 | + if (clientRegistration == null) { | ||
101 | + throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId); | ||
102 | + } | ||
103 | + | ||
104 | + Map<String, Object> attributes = new HashMap<>(); | ||
105 | + attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); | ||
106 | + | ||
107 | + OAuth2AuthorizationRequest.Builder builder; | ||
108 | + if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) { | ||
109 | + builder = OAuth2AuthorizationRequest.authorizationCode(); | ||
110 | + Map<String, Object> additionalParameters = new HashMap<>(); | ||
111 | + if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) && | ||
112 | + clientRegistration.getScopes().contains(OidcScopes.OPENID)) { | ||
113 | + // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest | ||
114 | + // scope | ||
115 | + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. | ||
116 | + addNonceParameters(attributes, additionalParameters); | ||
117 | + } | ||
118 | + if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())) { | ||
119 | + addPkceParameters(attributes, additionalParameters); | ||
120 | + } | ||
121 | + builder.additionalParameters(additionalParameters); | ||
122 | + } else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) { | ||
123 | + builder = OAuth2AuthorizationRequest.implicit(); | ||
124 | + } else { | ||
125 | + throw new IllegalArgumentException("Invalid Authorization Grant Type (" + | ||
126 | + clientRegistration.getAuthorizationGrantType().getValue() + | ||
127 | + ") for Client Registration with Id: " + clientRegistration.getRegistrationId()); | ||
128 | + } | ||
129 | + | ||
130 | + String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction); | ||
131 | + | ||
132 | + return builder | ||
133 | + .clientId(clientRegistration.getClientId()) | ||
134 | + .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) | ||
135 | + .redirectUri(redirectUriStr) | ||
136 | + .scopes(clientRegistration.getScopes()) | ||
137 | + .state(this.stateGenerator.generateKey()) | ||
138 | + .attributes(attributes) | ||
139 | + .build(); | ||
140 | + } | ||
141 | + | ||
142 | + private String resolveRegistrationId(HttpServletRequest request) { | ||
143 | + if (this.authorizationRequestMatcher.matches(request)) { | ||
144 | + return this.authorizationRequestMatcher | ||
145 | + .matcher(request).getVariables().get(REGISTRATION_ID_URI_VARIABLE_NAME); | ||
146 | + } | ||
147 | + return null; | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * Expands the {@link ClientRegistration#getRedirectUriTemplate()} with following provided variables:<br/> | ||
152 | + * - baseUrl (e.g. https://localhost/app) <br/> | ||
153 | + * - baseScheme (e.g. https) <br/> | ||
154 | + * - baseHost (e.g. localhost) <br/> | ||
155 | + * - basePort (e.g. :8080) <br/> | ||
156 | + * - basePath (e.g. /app) <br/> | ||
157 | + * - registrationId (e.g. google) <br/> | ||
158 | + * - action (e.g. login) <br/> | ||
159 | + * <p/> | ||
160 | + * Null variables are provided as empty strings. | ||
161 | + * <p/> | ||
162 | + * Default redirectUriTemplate is: {@link org.springframework.security.config.oauth2.client}.CommonOAuth2Provider#DEFAULT_REDIRECT_URL | ||
163 | + * | ||
164 | + * @return expanded URI | ||
165 | + */ | ||
166 | + private String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration, String action) { | ||
167 | + Map<String, String> uriVariables = new HashMap<>(); | ||
168 | + uriVariables.put("registrationId", clientRegistration.getRegistrationId()); | ||
169 | + | ||
170 | + UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) | ||
171 | + .replacePath(request.getContextPath()) | ||
172 | + .replaceQuery(null) | ||
173 | + .fragment(null) | ||
174 | + .build(); | ||
175 | + String scheme = uriComponents.getScheme(); | ||
176 | + uriVariables.put("baseScheme", scheme == null ? "" : scheme); | ||
177 | + String host = uriComponents.getHost(); | ||
178 | + uriVariables.put("baseHost", host == null ? "" : host); | ||
179 | + // following logic is based on HierarchicalUriComponents#toUriString() | ||
180 | + int port = uriComponents.getPort(); | ||
181 | + uriVariables.put("basePort", port == -1 ? "" : ":" + port); | ||
182 | + String path = uriComponents.getPath(); | ||
183 | + if (StringUtils.hasLength(path)) { | ||
184 | + if (path.charAt(0) != PATH_DELIMITER) { | ||
185 | + path = PATH_DELIMITER + path; | ||
186 | + } | ||
187 | + } | ||
188 | + uriVariables.put("basePath", path == null ? "" : path); | ||
189 | + uriVariables.put("baseUrl", uriComponents.toUriString()); | ||
190 | + | ||
191 | + uriVariables.put("action", action == null ? "" : action); | ||
192 | + | ||
193 | + String redirectUri = getRedirectUri(request); | ||
194 | + log.trace("Redirect URI - {}.", redirectUri); | ||
195 | + | ||
196 | + return UriComponentsBuilder.fromUriString(redirectUri) | ||
197 | + .buildAndExpand(uriVariables) | ||
198 | + .toUriString(); | ||
199 | + } | ||
200 | + | ||
201 | + private String getRedirectUri(HttpServletRequest request) { | ||
202 | + String loginProcessingUri = oauth2Configuration != null ? oauth2Configuration.getLoginProcessingUrl() : DEFAULT_LOGIN_PROCESSING_URI; | ||
203 | + | ||
204 | + String scheme = MiscUtils.getScheme(request); | ||
205 | + String domainName = MiscUtils.getDomainName(request); | ||
206 | + int port = MiscUtils.getPort(request); | ||
207 | + String baseUrl = scheme + "://" + domainName; | ||
208 | + if (needsPort(scheme, port)){ | ||
209 | + baseUrl += ":" + port; | ||
210 | + } | ||
211 | + return baseUrl + loginProcessingUri; | ||
212 | + } | ||
213 | + | ||
214 | + private boolean needsPort(String scheme, int port) { | ||
215 | + boolean isHttpDefault = "http".equals(scheme.toLowerCase()) && port == 80; | ||
216 | + boolean isHttpsDefault = "https".equals(scheme.toLowerCase()) && port == 443; | ||
217 | + return !isHttpDefault && !isHttpsDefault; | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * Creates nonce and its hash for use in OpenID Connect 1.0 Authentication Requests. | ||
222 | + * | ||
223 | + * @param attributes where the {@link OidcParameterNames#NONCE} is stored for the authentication request | ||
224 | + * @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is added for the authentication request | ||
225 | + * | ||
226 | + * @since 5.2 | ||
227 | + * @see <a target="_blank" href="https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest">3.1.2.1. Authentication Request</a> | ||
228 | + */ | ||
229 | + private void addNonceParameters(Map<String, Object> attributes, Map<String, Object> additionalParameters) { | ||
230 | + try { | ||
231 | + String nonce = this.secureKeyGenerator.generateKey(); | ||
232 | + String nonceHash = createHash(nonce); | ||
233 | + attributes.put(OidcParameterNames.NONCE, nonce); | ||
234 | + additionalParameters.put(OidcParameterNames.NONCE, nonceHash); | ||
235 | + } catch (NoSuchAlgorithmException e) { } | ||
236 | + } | ||
237 | + | ||
238 | + /** | ||
239 | + * Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization and Access Token Requests | ||
240 | + * | ||
241 | + * @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the token request | ||
242 | + * @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, usually, | ||
243 | + * {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in the authorization request. | ||
244 | + * | ||
245 | + * @since 5.2 | ||
246 | + * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-1.1">1.1. Protocol Flow</a> | ||
247 | + * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-4.1">4.1. Client Creates a Code Verifier</a> | ||
248 | + * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7636#section-4.2">4.2. Client Creates the Code Challenge</a> | ||
249 | + */ | ||
250 | + private void addPkceParameters(Map<String, Object> attributes, Map<String, Object> additionalParameters) { | ||
251 | + String codeVerifier = this.secureKeyGenerator.generateKey(); | ||
252 | + attributes.put(PkceParameterNames.CODE_VERIFIER, codeVerifier); | ||
253 | + try { | ||
254 | + String codeChallenge = createHash(codeVerifier); | ||
255 | + additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge); | ||
256 | + additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256"); | ||
257 | + } catch (NoSuchAlgorithmException e) { | ||
258 | + additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier); | ||
259 | + } | ||
260 | + } | ||
261 | + | ||
262 | + private static String createHash(String value) throws NoSuchAlgorithmException { | ||
263 | + MessageDigest md = MessageDigest.getInstance("SHA-256"); | ||
264 | + byte[] digest = md.digest(value.getBytes(StandardCharsets.US_ASCII)); | ||
265 | + return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); | ||
266 | + } | ||
267 | +} |
@@ -32,6 +32,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe | @@ -32,6 +32,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe | ||
32 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | 32 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
33 | import org.springframework.security.config.http.SessionCreationPolicy; | 33 | import org.springframework.security.config.http.SessionCreationPolicy; |
34 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | 34 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
35 | +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; | ||
35 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; | 36 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
36 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | 37 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
37 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | 38 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
@@ -175,6 +176,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | @@ -175,6 +176,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | ||
175 | web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**"); | 176 | web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**"); |
176 | } | 177 | } |
177 | 178 | ||
179 | + @Autowired | ||
180 | + private OAuth2AuthorizationRequestResolver oAuth2AuthorizationRequestResolver; | ||
181 | + | ||
178 | @Override | 182 | @Override |
179 | protected void configure(HttpSecurity http) throws Exception { | 183 | protected void configure(HttpSecurity http) throws Exception { |
180 | http.headers().cacheControl().and().frameOptions().disable() | 184 | http.headers().cacheControl().and().frameOptions().disable() |
@@ -207,8 +211,10 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | @@ -207,8 +211,10 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | ||
207 | .addFilterBefore(buildRefreshTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class) | 211 | .addFilterBefore(buildRefreshTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class) |
208 | .addFilterBefore(buildWsJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class) | 212 | .addFilterBefore(buildWsJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class) |
209 | .addFilterAfter(rateLimitProcessingFilter, UsernamePasswordAuthenticationFilter.class); | 213 | .addFilterAfter(rateLimitProcessingFilter, UsernamePasswordAuthenticationFilter.class); |
210 | - if (oauth2Configuration != null && oauth2Configuration.isEnabled()) { | 214 | + if (oauth2Configuration != null) { |
211 | http.oauth2Login() | 215 | http.oauth2Login() |
216 | + .authorizationEndpoint().authorizationRequestResolver(oAuth2AuthorizationRequestResolver) | ||
217 | + .and() | ||
212 | .loginPage("/oauth2Login") | 218 | .loginPage("/oauth2Login") |
213 | .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl()) | 219 | .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl()) |
214 | .successHandler(oauth2AuthenticationSuccessHandler) | 220 | .successHandler(oauth2AuthenticationSuccessHandler) |
@@ -38,10 +38,8 @@ import org.thingsboard.server.common.data.audit.ActionType; | @@ -38,10 +38,8 @@ import org.thingsboard.server.common.data.audit.ActionType; | ||
38 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 38 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
39 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 39 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
40 | import org.thingsboard.server.common.data.id.TenantId; | 40 | import org.thingsboard.server.common.data.id.TenantId; |
41 | -import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; | ||
42 | import org.thingsboard.server.common.data.security.UserCredentials; | 41 | import org.thingsboard.server.common.data.security.UserCredentials; |
43 | import org.thingsboard.server.dao.audit.AuditLogService; | 42 | import org.thingsboard.server.dao.audit.AuditLogService; |
44 | -import org.thingsboard.server.dao.oauth2.OAuth2Service; | ||
45 | import org.thingsboard.server.queue.util.TbCoreComponent; | 43 | import org.thingsboard.server.queue.util.TbCoreComponent; |
46 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | 44 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
47 | import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; | 45 | import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; |
@@ -84,9 +82,6 @@ public class AuthController extends BaseController { | @@ -84,9 +82,6 @@ public class AuthController extends BaseController { | ||
84 | @Autowired | 82 | @Autowired |
85 | private AuditLogService auditLogService; | 83 | private AuditLogService auditLogService; |
86 | 84 | ||
87 | - @Autowired | ||
88 | - private OAuth2Service oauth2Service; | ||
89 | - | ||
90 | @PreAuthorize("isAuthenticated()") | 85 | @PreAuthorize("isAuthenticated()") |
91 | @RequestMapping(value = "/auth/user", method = RequestMethod.GET) | 86 | @RequestMapping(value = "/auth/user", method = RequestMethod.GET) |
92 | public @ResponseBody User getUser() throws ThingsboardException { | 87 | public @ResponseBody User getUser() throws ThingsboardException { |
@@ -336,14 +331,4 @@ public class AuthController extends BaseController { | @@ -336,14 +331,4 @@ public class AuthController extends BaseController { | ||
336 | throw handleException(e); | 331 | throw handleException(e); |
337 | } | 332 | } |
338 | } | 333 | } |
339 | - | ||
340 | - @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) | ||
341 | - @ResponseBody | ||
342 | - public List<OAuth2ClientInfo> getOAuth2Clients() throws ThingsboardException { | ||
343 | - try { | ||
344 | - return oauth2Service.getOAuth2Clients(); | ||
345 | - } catch (Exception e) { | ||
346 | - throw handleException(e); | ||
347 | - } | ||
348 | - } | ||
349 | } | 334 | } |
@@ -27,22 +27,7 @@ import org.springframework.beans.factory.annotation.Value; | @@ -27,22 +27,7 @@ import org.springframework.beans.factory.annotation.Value; | ||
27 | import org.springframework.security.core.Authentication; | 27 | import org.springframework.security.core.Authentication; |
28 | import org.springframework.security.core.context.SecurityContextHolder; | 28 | import org.springframework.security.core.context.SecurityContextHolder; |
29 | import org.springframework.web.bind.annotation.ExceptionHandler; | 29 | import org.springframework.web.bind.annotation.ExceptionHandler; |
30 | -import org.thingsboard.server.common.data.Customer; | ||
31 | -import org.thingsboard.server.common.data.Dashboard; | ||
32 | -import org.thingsboard.server.common.data.DashboardInfo; | ||
33 | -import org.thingsboard.server.common.data.DataConstants; | ||
34 | -import org.thingsboard.server.common.data.Device; | ||
35 | -import org.thingsboard.server.common.data.DeviceInfo; | ||
36 | -import org.thingsboard.server.common.data.DeviceProfile; | ||
37 | -import org.thingsboard.server.common.data.EntityType; | ||
38 | -import org.thingsboard.server.common.data.EntityView; | ||
39 | -import org.thingsboard.server.common.data.EntityViewInfo; | ||
40 | -import org.thingsboard.server.common.data.HasName; | ||
41 | -import org.thingsboard.server.common.data.HasTenantId; | ||
42 | -import org.thingsboard.server.common.data.Tenant; | ||
43 | -import org.thingsboard.server.common.data.TenantInfo; | ||
44 | -import org.thingsboard.server.common.data.TenantProfile; | ||
45 | -import org.thingsboard.server.common.data.User; | 30 | +import org.thingsboard.server.common.data.*; |
46 | import org.thingsboard.server.common.data.alarm.Alarm; | 31 | import org.thingsboard.server.common.data.alarm.Alarm; |
47 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 32 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
48 | import org.thingsboard.server.common.data.asset.Asset; | 33 | import org.thingsboard.server.common.data.asset.Asset; |
@@ -50,6 +35,7 @@ import org.thingsboard.server.common.data.asset.AssetInfo; | @@ -50,6 +35,7 @@ import org.thingsboard.server.common.data.asset.AssetInfo; | ||
50 | import org.thingsboard.server.common.data.audit.ActionType; | 35 | import org.thingsboard.server.common.data.audit.ActionType; |
51 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 36 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
52 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 37 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
38 | +import org.thingsboard.server.common.data.id.*; | ||
53 | import org.thingsboard.server.common.data.id.AlarmId; | 39 | import org.thingsboard.server.common.data.id.AlarmId; |
54 | import org.thingsboard.server.common.data.id.AssetId; | 40 | import org.thingsboard.server.common.data.id.AssetId; |
55 | import org.thingsboard.server.common.data.id.CustomerId; | 41 | import org.thingsboard.server.common.data.id.CustomerId; |
@@ -93,6 +79,8 @@ import org.thingsboard.server.dao.entityview.EntityViewService; | @@ -93,6 +79,8 @@ import org.thingsboard.server.dao.entityview.EntityViewService; | ||
93 | import org.thingsboard.server.dao.exception.DataValidationException; | 79 | import org.thingsboard.server.dao.exception.DataValidationException; |
94 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 80 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
95 | import org.thingsboard.server.dao.model.ModelConstants; | 81 | import org.thingsboard.server.dao.model.ModelConstants; |
82 | +import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; | ||
83 | +import org.thingsboard.server.dao.oauth2.OAuth2Service; | ||
96 | import org.thingsboard.server.dao.relation.RelationService; | 84 | import org.thingsboard.server.dao.relation.RelationService; |
97 | import org.thingsboard.server.dao.rule.RuleChainService; | 85 | import org.thingsboard.server.dao.rule.RuleChainService; |
98 | import org.thingsboard.server.dao.tenant.TenantProfileService; | 86 | import org.thingsboard.server.dao.tenant.TenantProfileService; |
@@ -176,6 +164,12 @@ public abstract class BaseController { | @@ -176,6 +164,12 @@ public abstract class BaseController { | ||
176 | protected DashboardService dashboardService; | 164 | protected DashboardService dashboardService; |
177 | 165 | ||
178 | @Autowired | 166 | @Autowired |
167 | + protected OAuth2Service oAuth2Service; | ||
168 | + | ||
169 | + @Autowired | ||
170 | + protected OAuth2ConfigTemplateService oAuth2ConfigTemplateService; | ||
171 | + | ||
172 | + @Autowired | ||
179 | protected ComponentDiscoveryService componentDescriptorService; | 173 | protected ComponentDiscoveryService componentDescriptorService; |
180 | 174 | ||
181 | @Autowired | 175 | @Autowired |
application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.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.controller; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.http.HttpStatus; | ||
20 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
21 | +import org.springframework.web.bind.annotation.*; | ||
22 | +import org.thingsboard.server.common.data.EntityType; | ||
23 | +import org.thingsboard.server.common.data.audit.ActionType; | ||
24 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
25 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; | ||
26 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
27 | +import org.thingsboard.server.queue.util.TbCoreComponent; | ||
28 | +import org.thingsboard.server.service.security.permission.Operation; | ||
29 | +import org.thingsboard.server.service.security.permission.Resource; | ||
30 | + | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +@RestController | ||
34 | +@TbCoreComponent | ||
35 | +@RequestMapping("/api/oauth2/config/template") | ||
36 | +@Slf4j | ||
37 | +public class OAuth2ConfigTemplateController extends BaseController { | ||
38 | + private static final String CLIENT_REGISTRATION_TEMPLATE_ID = "clientRegistrationTemplateId"; | ||
39 | + | ||
40 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") | ||
41 | + @RequestMapping(method = RequestMethod.POST) | ||
42 | + @ResponseStatus(value = HttpStatus.OK) | ||
43 | + public OAuth2ClientRegistrationTemplate saveClientRegistrationTemplate(@RequestBody OAuth2ClientRegistrationTemplate clientRegistrationTemplate) throws ThingsboardException { | ||
44 | + try { | ||
45 | + accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.WRITE); | ||
46 | + return oAuth2ConfigTemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate); | ||
47 | + } catch (Exception e) { | ||
48 | + throw handleException(e); | ||
49 | + } | ||
50 | + } | ||
51 | + | ||
52 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") | ||
53 | + @RequestMapping(value = "/{clientRegistrationTemplateId}", method = RequestMethod.DELETE) | ||
54 | + @ResponseStatus(value = HttpStatus.OK) | ||
55 | + public void deleteClientRegistrationTemplate(@PathVariable(CLIENT_REGISTRATION_TEMPLATE_ID) String strClientRegistrationTemplateId) throws ThingsboardException { | ||
56 | + checkParameter(CLIENT_REGISTRATION_TEMPLATE_ID, strClientRegistrationTemplateId); | ||
57 | + try { | ||
58 | + accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.DELETE); | ||
59 | + OAuth2ClientRegistrationTemplateId clientRegistrationTemplateId = new OAuth2ClientRegistrationTemplateId(toUUID(strClientRegistrationTemplateId)); | ||
60 | + oAuth2ConfigTemplateService.deleteClientRegistrationTemplateById(clientRegistrationTemplateId); | ||
61 | + } catch (Exception e) { | ||
62 | + throw handleException(e); | ||
63 | + } | ||
64 | + } | ||
65 | + | ||
66 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
67 | + @RequestMapping(method = RequestMethod.GET, produces = "application/json") | ||
68 | + @ResponseBody | ||
69 | + public List<OAuth2ClientRegistrationTemplate> getClientRegistrationTemplates() throws ThingsboardException { | ||
70 | + try { | ||
71 | + accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.READ); | ||
72 | + return oAuth2ConfigTemplateService.findAllClientRegistrationTemplates(); | ||
73 | + } catch (Exception e) { | ||
74 | + throw handleException(e); | ||
75 | + } | ||
76 | + } | ||
77 | +} |
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.controller; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.http.HttpStatus; | ||
20 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
21 | +import org.springframework.web.bind.annotation.*; | ||
22 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
23 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; | ||
24 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams; | ||
25 | +import org.thingsboard.server.common.data.oauth2.SchemeType; | ||
26 | +import org.thingsboard.server.queue.util.TbCoreComponent; | ||
27 | +import org.thingsboard.server.service.security.permission.Operation; | ||
28 | +import org.thingsboard.server.service.security.permission.Resource; | ||
29 | +import org.thingsboard.server.utils.MiscUtils; | ||
30 | + | ||
31 | +import javax.servlet.http.HttpServletRequest; | ||
32 | +import java.util.List; | ||
33 | + | ||
34 | +@RestController | ||
35 | +@TbCoreComponent | ||
36 | +@RequestMapping("/api") | ||
37 | +@Slf4j | ||
38 | +public class OAuth2Controller extends BaseController { | ||
39 | + @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) | ||
40 | + @ResponseBody | ||
41 | + public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request) throws ThingsboardException { | ||
42 | + try { | ||
43 | + return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainName(request)); | ||
44 | + } catch (Exception e) { | ||
45 | + throw handleException(e); | ||
46 | + } | ||
47 | + } | ||
48 | + | ||
49 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") | ||
50 | + @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json") | ||
51 | + @ResponseBody | ||
52 | + public OAuth2ClientsParams getCurrentOAuth2Params() throws ThingsboardException { | ||
53 | + try { | ||
54 | + accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ); | ||
55 | + return oAuth2Service.findOAuth2Params(); | ||
56 | + } catch (Exception e) { | ||
57 | + throw handleException(e); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") | ||
62 | + @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST) | ||
63 | + @ResponseStatus(value = HttpStatus.OK) | ||
64 | + public OAuth2ClientsParams saveOAuth2Params(@RequestBody OAuth2ClientsParams oauth2Params) throws ThingsboardException { | ||
65 | + try { | ||
66 | + accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.WRITE); | ||
67 | + oAuth2Service.saveOAuth2Params(oauth2Params); | ||
68 | + return oAuth2Service.findOAuth2Params(); | ||
69 | + } catch (Exception e) { | ||
70 | + throw handleException(e); | ||
71 | + } | ||
72 | + } | ||
73 | +} |
@@ -184,6 +184,7 @@ public class ThingsboardInstallService { | @@ -184,6 +184,7 @@ public class ThingsboardInstallService { | ||
184 | dataUpdateService.updateData("3.1.1"); | 184 | dataUpdateService.updateData("3.1.1"); |
185 | log.info("Updating system data..."); | 185 | log.info("Updating system data..."); |
186 | systemDataLoaderService.updateSystemWidgets(); | 186 | systemDataLoaderService.updateSystemWidgets(); |
187 | + systemDataLoaderService.createOAuth2Templates(); | ||
187 | break; | 188 | break; |
188 | default: | 189 | default: |
189 | throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); | 190 | throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); |
@@ -216,6 +217,7 @@ public class ThingsboardInstallService { | @@ -216,6 +217,7 @@ public class ThingsboardInstallService { | ||
216 | systemDataLoaderService.createDefaultTenantProfiles(); | 217 | systemDataLoaderService.createDefaultTenantProfiles(); |
217 | systemDataLoaderService.createAdminSettings(); | 218 | systemDataLoaderService.createAdminSettings(); |
218 | systemDataLoaderService.loadSystemWidgets(); | 219 | systemDataLoaderService.loadSystemWidgets(); |
220 | + systemDataLoaderService.createOAuth2Templates(); | ||
219 | // systemDataLoaderService.loadSystemPlugins(); | 221 | // systemDataLoaderService.loadSystemPlugins(); |
220 | // systemDataLoaderService.loadSystemRules(); | 222 | // systemDataLoaderService.loadSystemRules(); |
221 | 223 |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -194,6 +194,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -194,6 +194,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
194 | } | 194 | } |
195 | 195 | ||
196 | @Override | 196 | @Override |
197 | + public void createOAuth2Templates() throws Exception { | ||
198 | + installScripts.createOAuth2Templates(); | ||
199 | + } | ||
200 | + | ||
201 | + @Override | ||
197 | public void loadDemoData() throws Exception { | 202 | public void loadDemoData() throws Exception { |
198 | Tenant demoTenant = new Tenant(); | 203 | Tenant demoTenant = new Tenant(); |
199 | demoTenant.setRegion("Global"); | 204 | demoTenant.setRegion("Global"); |
@@ -26,11 +26,13 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -26,11 +26,13 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
26 | import org.thingsboard.server.common.data.id.EntityId; | 26 | import org.thingsboard.server.common.data.id.EntityId; |
27 | import org.thingsboard.server.common.data.id.RuleChainId; | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
29 | import org.thingsboard.server.common.data.rule.RuleChain; | 30 | import org.thingsboard.server.common.data.rule.RuleChain; |
30 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 31 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
31 | import org.thingsboard.server.common.data.widget.WidgetType; | 32 | import org.thingsboard.server.common.data.widget.WidgetType; |
32 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 33 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
33 | import org.thingsboard.server.dao.dashboard.DashboardService; | 34 | import org.thingsboard.server.dao.dashboard.DashboardService; |
35 | +import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; | ||
34 | import org.thingsboard.server.dao.rule.RuleChainService; | 36 | import org.thingsboard.server.dao.rule.RuleChainService; |
35 | import org.thingsboard.server.dao.widget.WidgetTypeService; | 37 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
36 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 38 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
@@ -61,6 +63,7 @@ public class InstallScripts { | @@ -61,6 +63,7 @@ public class InstallScripts { | ||
61 | public static final String DEMO_DIR = "demo"; | 63 | public static final String DEMO_DIR = "demo"; |
62 | public static final String RULE_CHAINS_DIR = "rule_chains"; | 64 | public static final String RULE_CHAINS_DIR = "rule_chains"; |
63 | public static final String WIDGET_BUNDLES_DIR = "widget_bundles"; | 65 | public static final String WIDGET_BUNDLES_DIR = "widget_bundles"; |
66 | + public static final String OAUTH2_CONFIG_TEMPLATES_DIR = "oauth2_config_templates"; | ||
64 | public static final String DASHBOARDS_DIR = "dashboards"; | 67 | public static final String DASHBOARDS_DIR = "dashboards"; |
65 | 68 | ||
66 | public static final String JSON_EXT = ".json"; | 69 | public static final String JSON_EXT = ".json"; |
@@ -80,6 +83,9 @@ public class InstallScripts { | @@ -80,6 +83,9 @@ public class InstallScripts { | ||
80 | @Autowired | 83 | @Autowired |
81 | private WidgetsBundleService widgetsBundleService; | 84 | private WidgetsBundleService widgetsBundleService; |
82 | 85 | ||
86 | + @Autowired | ||
87 | + private OAuth2ConfigTemplateService oAuth2TemplateService; | ||
88 | + | ||
83 | public Path getTenantRuleChainsDir() { | 89 | public Path getTenantRuleChainsDir() { |
84 | return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); | 90 | return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); |
85 | } | 91 | } |
@@ -228,4 +234,22 @@ public class InstallScripts { | @@ -228,4 +234,22 @@ public class InstallScripts { | ||
228 | throw new RuntimeException("Unable to load dashboard from json", e); | 234 | throw new RuntimeException("Unable to load dashboard from json", e); |
229 | } | 235 | } |
230 | } | 236 | } |
237 | + | ||
238 | + public void createOAuth2Templates() throws Exception { | ||
239 | + Path oauth2ConfigTemplatesDir = Paths.get(getDataDir(), JSON_DIR, SYSTEM_DIR, OAUTH2_CONFIG_TEMPLATES_DIR); | ||
240 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(oauth2ConfigTemplatesDir, path -> path.toString().endsWith(JSON_EXT))) { | ||
241 | + dirStream.forEach( | ||
242 | + path -> { | ||
243 | + try { | ||
244 | + JsonNode oauth2ConfigTemplateJson = objectMapper.readTree(path.toFile()); | ||
245 | + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = objectMapper.treeToValue(oauth2ConfigTemplateJson, OAuth2ClientRegistrationTemplate.class); | ||
246 | + oAuth2TemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate); | ||
247 | + } catch (Exception e) { | ||
248 | + log.error("Unable to load oauth2 config templates from json: [{}]", path.toString()); | ||
249 | + throw new RuntimeException("Unable to load oauth2 config templates from json", e); | ||
250 | + } | ||
251 | + } | ||
252 | + ); | ||
253 | + } | ||
254 | + } | ||
231 | } | 255 | } |
@@ -23,6 +23,8 @@ public interface SystemDataLoaderService { | @@ -23,6 +23,8 @@ public interface SystemDataLoaderService { | ||
23 | 23 | ||
24 | void createAdminSettings() throws Exception; | 24 | void createAdminSettings() throws Exception; |
25 | 25 | ||
26 | + void createOAuth2Templates() throws Exception; | ||
27 | + | ||
26 | void loadSystemWidgets() throws Exception; | 28 | void loadSystemWidgets() throws Exception; |
27 | 29 | ||
28 | void updateSystemWidgets() throws Exception; | 30 | void updateSystemWidgets() throws Exception; |
@@ -17,7 +17,6 @@ package org.thingsboard.server.service.security.auth.oauth2; | @@ -17,7 +17,6 @@ package org.thingsboard.server.service.security.auth.oauth2; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | -import com.google.common.base.Strings; | ||
21 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
22 | import org.springframework.beans.factory.annotation.Autowired; | 21 | import org.springframework.beans.factory.annotation.Autowired; |
23 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 22 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
@@ -34,7 +33,6 @@ import org.thingsboard.server.common.data.id.IdBased; | @@ -34,7 +33,6 @@ import org.thingsboard.server.common.data.id.IdBased; | ||
34 | import org.thingsboard.server.common.data.id.TenantId; | 33 | import org.thingsboard.server.common.data.id.TenantId; |
35 | import org.thingsboard.server.common.data.page.PageData; | 34 | import org.thingsboard.server.common.data.page.PageData; |
36 | import org.thingsboard.server.common.data.page.PageLink; | 35 | import org.thingsboard.server.common.data.page.PageLink; |
37 | -import org.thingsboard.server.common.data.page.TimePageLink; | ||
38 | import org.thingsboard.server.common.data.security.Authority; | 36 | import org.thingsboard.server.common.data.security.Authority; |
39 | import org.thingsboard.server.common.data.security.UserCredentials; | 37 | import org.thingsboard.server.common.data.security.UserCredentials; |
40 | import org.thingsboard.server.dao.customer.CustomerService; | 38 | import org.thingsboard.server.dao.customer.CustomerService; |
@@ -49,7 +47,6 @@ import org.thingsboard.server.service.security.model.UserPrincipal; | @@ -49,7 +47,6 @@ import org.thingsboard.server.service.security.model.UserPrincipal; | ||
49 | import java.io.IOException; | 47 | import java.io.IOException; |
50 | import java.util.List; | 48 | import java.util.List; |
51 | import java.util.Optional; | 49 | import java.util.Optional; |
52 | -import java.util.concurrent.ExecutionException; | ||
53 | import java.util.concurrent.locks.Lock; | 50 | import java.util.concurrent.locks.Lock; |
54 | import java.util.concurrent.locks.ReentrantLock; | 51 | import java.util.concurrent.locks.ReentrantLock; |
55 | 52 |
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,11 +16,9 @@ | @@ -16,11 +16,9 @@ | ||
16 | package org.thingsboard.server.service.security.auth.oauth2; | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.apache.commons.lang3.text.StrSubstitutor; | ||
20 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | 19 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
21 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
22 | -import org.springframework.util.StringUtils; | ||
23 | -import org.thingsboard.server.dao.oauth2.OAuth2ClientMapperConfig; | 21 | +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; |
24 | import org.thingsboard.server.dao.oauth2.OAuth2User; | 22 | import org.thingsboard.server.dao.oauth2.OAuth2User; |
25 | import org.thingsboard.server.service.security.model.SecurityUser; | 23 | import org.thingsboard.server.service.security.model.SecurityUser; |
26 | 24 | ||
@@ -30,62 +28,12 @@ import java.util.Map; | @@ -30,62 +28,12 @@ import java.util.Map; | ||
30 | @Slf4j | 28 | @Slf4j |
31 | public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { | 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 | - private static final String EMAIL_TENANT_STRATEGY = "email"; | ||
36 | - private static final String DOMAIN_TENANT_STRATEGY = "domain"; | ||
37 | - private static final String CUSTOM_TENANT_STRATEGY = "custom"; | ||
38 | - | ||
39 | @Override | 31 | @Override |
40 | - public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig config) { | ||
41 | - OAuth2User oauth2User = new OAuth2User(); | 32 | + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2MapperConfig config) { |
42 | Map<String, Object> attributes = token.getPrincipal().getAttributes(); | 33 | Map<String, Object> attributes = token.getPrincipal().getAttributes(); |
43 | - String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | ||
44 | - oauth2User.setEmail(email); | ||
45 | - oauth2User.setTenantName(getTenantName(attributes, config)); | ||
46 | - if (!StringUtils.isEmpty(config.getBasic().getLastNameAttributeKey())) { | ||
47 | - String lastName = getStringAttributeByKey(attributes, config.getBasic().getLastNameAttributeKey()); | ||
48 | - oauth2User.setLastName(lastName); | ||
49 | - } | ||
50 | - if (!StringUtils.isEmpty(config.getBasic().getFirstNameAttributeKey())) { | ||
51 | - String firstName = getStringAttributeByKey(attributes, config.getBasic().getFirstNameAttributeKey()); | ||
52 | - oauth2User.setFirstName(firstName); | ||
53 | - } | ||
54 | - if (!StringUtils.isEmpty(config.getBasic().getCustomerNamePattern())) { | ||
55 | - StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | ||
56 | - String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); | ||
57 | - oauth2User.setCustomerName(customerName); | ||
58 | - } | ||
59 | - oauth2User.setAlwaysFullScreen(config.getBasic().isAlwaysFullScreen()); | ||
60 | - if (!StringUtils.isEmpty(config.getBasic().getDefaultDashboardName())) { | ||
61 | - oauth2User.setDefaultDashboardName(config.getBasic().getDefaultDashboardName()); | ||
62 | - } | 34 | + String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); |
35 | + OAuth2User oauth2User = BasicMapperUtils.getOAuth2User(email, attributes, config); | ||
63 | 36 | ||
64 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); | 37 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); |
65 | } | 38 | } |
66 | - | ||
67 | - private String getTenantName(Map<String, Object> attributes, OAuth2ClientMapperConfig config) { | ||
68 | - switch (config.getBasic().getTenantNameStrategy()) { | ||
69 | - case EMAIL_TENANT_STRATEGY: | ||
70 | - return getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | ||
71 | - case DOMAIN_TENANT_STRATEGY: | ||
72 | - String email = getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); | ||
73 | - return email.substring(email .indexOf("@") + 1); | ||
74 | - case CUSTOM_TENANT_STRATEGY: | ||
75 | - StrSubstitutor sub = new StrSubstitutor(attributes, START_PLACEHOLDER_PREFIX, END_PLACEHOLDER_PREFIX); | ||
76 | - return sub.replace(config.getBasic().getTenantNamePattern()); | ||
77 | - default: | ||
78 | - throw new RuntimeException("Tenant Name Strategy with type " + config.getBasic().getTenantNameStrategy() + " is not supported!"); | ||
79 | - } | ||
80 | - } | ||
81 | - | ||
82 | - private String getStringAttributeByKey(Map<String, Object> attributes, String key) { | ||
83 | - String result = null; | ||
84 | - try { | ||
85 | - result = (String) attributes.get(key); | ||
86 | - } catch (Exception e) { | ||
87 | - log.warn("Can't convert attribute to String by key " + key); | ||
88 | - } | ||
89 | - return result; | ||
90 | - } | ||
91 | } | 39 | } |
@@ -23,28 +23,34 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic | @@ -23,28 +23,34 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic | ||
23 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | import org.springframework.util.StringUtils; | 24 | import org.springframework.util.StringUtils; |
25 | import org.springframework.web.client.RestTemplate; | 25 | import org.springframework.web.client.RestTemplate; |
26 | -import org.thingsboard.server.dao.oauth2.OAuth2ClientMapperConfig; | 26 | +import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; |
27 | +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; | ||
27 | import org.thingsboard.server.dao.oauth2.OAuth2User; | 28 | import org.thingsboard.server.dao.oauth2.OAuth2User; |
28 | import org.thingsboard.server.service.security.model.SecurityUser; | 29 | import org.thingsboard.server.service.security.model.SecurityUser; |
29 | 30 | ||
30 | @Service(value = "customOAuth2ClientMapper") | 31 | @Service(value = "customOAuth2ClientMapper") |
31 | @Slf4j | 32 | @Slf4j |
32 | public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { | 33 | public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { |
34 | + private static final String PROVIDER_ACCESS_TOKEN = "provider-access-token"; | ||
33 | 35 | ||
34 | private static final ObjectMapper json = new ObjectMapper(); | 36 | private static final ObjectMapper json = new ObjectMapper(); |
35 | 37 | ||
36 | private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); | 38 | private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); |
37 | 39 | ||
38 | @Override | 40 | @Override |
39 | - public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig config) { | ||
40 | - OAuth2User oauth2User = getOAuth2User(token, config.getCustom()); | 41 | + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2MapperConfig config) { |
42 | + OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom()); | ||
41 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); | 43 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); |
42 | } | 44 | } |
43 | 45 | ||
44 | - private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig.CustomOAuth2ClientMapperConfig custom) { | 46 | + private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2CustomMapperConfig custom) { |
45 | if (!StringUtils.isEmpty(custom.getUsername()) && !StringUtils.isEmpty(custom.getPassword())) { | 47 | if (!StringUtils.isEmpty(custom.getUsername()) && !StringUtils.isEmpty(custom.getPassword())) { |
46 | restTemplateBuilder = restTemplateBuilder.basicAuthentication(custom.getUsername(), custom.getPassword()); | 48 | restTemplateBuilder = restTemplateBuilder.basicAuthentication(custom.getUsername(), custom.getPassword()); |
47 | } | 49 | } |
50 | + if (custom.isSendToken() && !StringUtils.isEmpty(providerAccessToken)) { | ||
51 | + restTemplateBuilder = restTemplateBuilder.defaultHeader(PROVIDER_ACCESS_TOKEN, providerAccessToken); | ||
52 | + } | ||
53 | + | ||
48 | RestTemplate restTemplate = restTemplateBuilder.build(); | 54 | RestTemplate restTemplate = restTemplateBuilder.build(); |
49 | String request; | 55 | String request; |
50 | try { | 56 | try { |
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 | +} |
@@ -16,9 +16,9 @@ | @@ -16,9 +16,9 @@ | ||
16 | package org.thingsboard.server.service.security.auth.oauth2; | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | ||
18 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | 18 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
19 | -import org.thingsboard.server.dao.oauth2.OAuth2ClientMapperConfig; | 19 | +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; |
20 | import org.thingsboard.server.service.security.model.SecurityUser; | 20 | import org.thingsboard.server.service.security.model.SecurityUser; |
21 | 21 | ||
22 | public interface OAuth2ClientMapper { | 22 | public interface OAuth2ClientMapper { |
23 | - SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig config); | 23 | + SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2MapperConfig config); |
24 | } | 24 | } |
@@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; | ||
19 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.beans.factory.annotation.Qualifier; | 20 | import org.springframework.beans.factory.annotation.Qualifier; |
21 | import org.springframework.stereotype.Component; | 21 | import org.springframework.stereotype.Component; |
22 | +import org.thingsboard.server.common.data.oauth2.MapperType; | ||
22 | 23 | ||
23 | @Component | 24 | @Component |
24 | @Slf4j | 25 | @Slf4j |
@@ -32,14 +33,20 @@ public class OAuth2ClientMapperProvider { | @@ -32,14 +33,20 @@ public class OAuth2ClientMapperProvider { | ||
32 | @Qualifier("customOAuth2ClientMapper") | 33 | @Qualifier("customOAuth2ClientMapper") |
33 | private OAuth2ClientMapper customOAuth2ClientMapper; | 34 | private OAuth2ClientMapper customOAuth2ClientMapper; |
34 | 35 | ||
35 | - public OAuth2ClientMapper getOAuth2ClientMapperByType(String oauth2ClientType) { | ||
36 | - switch (oauth2ClientType) { | ||
37 | - case "custom": | 36 | + @Autowired |
37 | + @Qualifier("githubOAuth2ClientMapper") | ||
38 | + private OAuth2ClientMapper githubOAuth2ClientMapper; | ||
39 | + | ||
40 | + public OAuth2ClientMapper getOAuth2ClientMapperByType(MapperType oauth2MapperType) { | ||
41 | + switch (oauth2MapperType) { | ||
42 | + case CUSTOM: | ||
38 | return customOAuth2ClientMapper; | 43 | return customOAuth2ClientMapper; |
39 | - case "basic": | 44 | + case BASIC: |
40 | return basicOAuth2ClientMapper; | 45 | return basicOAuth2ClientMapper; |
46 | + case GITHUB: | ||
47 | + return githubOAuth2ClientMapper; | ||
41 | default: | 48 | default: |
42 | - throw new RuntimeException("OAuth2ClientMapper with type " + oauth2ClientType + " is not supported!"); | 49 | + throw new RuntimeException("OAuth2ClientRegistrationMapper with type " + oauth2MapperType + " is not supported!"); |
43 | } | 50 | } |
44 | } | 51 | } |
45 | } | 52 | } |
@@ -16,13 +16,14 @@ | @@ -16,13 +16,14 @@ | ||
16 | package org.thingsboard.server.service.security.auth.oauth2; | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | ||
18 | import org.springframework.beans.factory.annotation.Autowired; | 18 | import org.springframework.beans.factory.annotation.Autowired; |
19 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
20 | import org.springframework.security.core.Authentication; | 19 | import org.springframework.security.core.Authentication; |
20 | +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; | ||
21 | +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; | ||
21 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; | 22 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
22 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; | 23 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; |
23 | import org.springframework.stereotype.Component; | 24 | import org.springframework.stereotype.Component; |
24 | -import org.thingsboard.server.dao.oauth2.OAuth2Client; | ||
25 | -import org.thingsboard.server.dao.oauth2.OAuth2Configuration; | 25 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; |
26 | +import org.thingsboard.server.dao.oauth2.OAuth2Service; | ||
26 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | 27 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
27 | import org.thingsboard.server.service.security.model.SecurityUser; | 28 | import org.thingsboard.server.service.security.model.SecurityUser; |
28 | import org.thingsboard.server.service.security.model.token.JwtToken; | 29 | import org.thingsboard.server.service.security.model.token.JwtToken; |
@@ -34,25 +35,28 @@ import javax.servlet.http.HttpServletResponse; | @@ -34,25 +35,28 @@ import javax.servlet.http.HttpServletResponse; | ||
34 | import java.io.IOException; | 35 | import java.io.IOException; |
35 | import java.net.URLEncoder; | 36 | import java.net.URLEncoder; |
36 | import java.nio.charset.StandardCharsets; | 37 | import java.nio.charset.StandardCharsets; |
38 | +import java.util.UUID; | ||
37 | 39 | ||
38 | @Component(value = "oauth2AuthenticationSuccessHandler") | 40 | @Component(value = "oauth2AuthenticationSuccessHandler") |
39 | -@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") | ||
40 | public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { | 41 | public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { |
41 | 42 | ||
42 | private final JwtTokenFactory tokenFactory; | 43 | private final JwtTokenFactory tokenFactory; |
43 | private final RefreshTokenRepository refreshTokenRepository; | 44 | private final RefreshTokenRepository refreshTokenRepository; |
44 | private final OAuth2ClientMapperProvider oauth2ClientMapperProvider; | 45 | private final OAuth2ClientMapperProvider oauth2ClientMapperProvider; |
45 | - private final OAuth2Configuration oauth2Configuration; | 46 | + private final OAuth2Service oAuth2Service; |
47 | + private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService; | ||
46 | 48 | ||
47 | @Autowired | 49 | @Autowired |
48 | public Oauth2AuthenticationSuccessHandler(final JwtTokenFactory tokenFactory, | 50 | public Oauth2AuthenticationSuccessHandler(final JwtTokenFactory tokenFactory, |
49 | final RefreshTokenRepository refreshTokenRepository, | 51 | final RefreshTokenRepository refreshTokenRepository, |
50 | final OAuth2ClientMapperProvider oauth2ClientMapperProvider, | 52 | final OAuth2ClientMapperProvider oauth2ClientMapperProvider, |
51 | - final OAuth2Configuration oauth2Configuration) { | 53 | + final OAuth2Service oAuth2Service, |
54 | + final OAuth2AuthorizedClientService oAuth2AuthorizedClientService) { | ||
52 | this.tokenFactory = tokenFactory; | 55 | this.tokenFactory = tokenFactory; |
53 | this.refreshTokenRepository = refreshTokenRepository; | 56 | this.refreshTokenRepository = refreshTokenRepository; |
54 | this.oauth2ClientMapperProvider = oauth2ClientMapperProvider; | 57 | this.oauth2ClientMapperProvider = oauth2ClientMapperProvider; |
55 | - this.oauth2Configuration = oauth2Configuration; | 58 | + this.oAuth2Service = oAuth2Service; |
59 | + this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService; | ||
56 | } | 60 | } |
57 | 61 | ||
58 | @Override | 62 | @Override |
@@ -64,9 +68,13 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS | @@ -64,9 +68,13 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS | ||
64 | try { | 68 | try { |
65 | OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; | 69 | OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; |
66 | 70 | ||
67 | - OAuth2Client oauth2Client = oauth2Configuration.getClientByRegistrationId(token.getAuthorizedClientRegistrationId()); | ||
68 | - OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(oauth2Client.getMapperConfig().getType()); | ||
69 | - SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oauth2Client.getMapperConfig()); | 71 | + OAuth2ClientRegistrationInfo clientRegistration = oAuth2Service.findClientRegistrationInfo(UUID.fromString(token.getAuthorizedClientRegistrationId())); |
72 | + OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient( | ||
73 | + token.getAuthorizedClientRegistrationId(), | ||
74 | + token.getPrincipal().getName()); | ||
75 | + OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(clientRegistration.getMapperConfig().getType()); | ||
76 | + SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oAuth2AuthorizedClient.getAccessToken().getTokenValue(), | ||
77 | + clientRegistration.getMapperConfig()); | ||
70 | 78 | ||
71 | JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); | 79 | JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); |
72 | JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); | 80 | JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); |
@@ -32,6 +32,8 @@ public enum Resource { | @@ -32,6 +32,8 @@ public enum Resource { | ||
32 | USER(EntityType.USER), | 32 | USER(EntityType.USER), |
33 | WIDGETS_BUNDLE(EntityType.WIDGETS_BUNDLE), | 33 | WIDGETS_BUNDLE(EntityType.WIDGETS_BUNDLE), |
34 | WIDGET_TYPE(EntityType.WIDGET_TYPE), | 34 | WIDGET_TYPE(EntityType.WIDGET_TYPE), |
35 | + OAUTH2_CONFIGURATION_INFO(), | ||
36 | + OAUTH2_CONFIGURATION_TEMPLATE(), | ||
35 | TENANT_PROFILE(EntityType.TENANT_PROFILE), | 37 | TENANT_PROFILE(EntityType.TENANT_PROFILE), |
36 | DEVICE_PROFILE(EntityType.DEVICE_PROFILE); | 38 | DEVICE_PROFILE(EntityType.DEVICE_PROFILE); |
37 | 39 |
@@ -19,14 +19,10 @@ import org.springframework.stereotype.Component; | @@ -19,14 +19,10 @@ import org.springframework.stereotype.Component; | ||
19 | import org.thingsboard.server.common.data.HasTenantId; | 19 | import org.thingsboard.server.common.data.HasTenantId; |
20 | import org.thingsboard.server.common.data.User; | 20 | import org.thingsboard.server.common.data.User; |
21 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | -import org.thingsboard.server.common.data.id.TenantId; | ||
23 | import org.thingsboard.server.common.data.id.UserId; | 22 | import org.thingsboard.server.common.data.id.UserId; |
24 | import org.thingsboard.server.common.data.security.Authority; | 23 | import org.thingsboard.server.common.data.security.Authority; |
25 | import org.thingsboard.server.service.security.model.SecurityUser; | 24 | import org.thingsboard.server.service.security.model.SecurityUser; |
26 | 25 | ||
27 | -import java.util.HashMap; | ||
28 | -import java.util.Optional; | ||
29 | - | ||
30 | @Component(value="sysAdminPermissions") | 26 | @Component(value="sysAdminPermissions") |
31 | public class SysAdminPermissions extends AbstractPermissions { | 27 | public class SysAdminPermissions extends AbstractPermissions { |
32 | 28 | ||
@@ -39,6 +35,8 @@ public class SysAdminPermissions extends AbstractPermissions { | @@ -39,6 +35,8 @@ public class SysAdminPermissions extends AbstractPermissions { | ||
39 | put(Resource.USER, userPermissionChecker); | 35 | put(Resource.USER, userPermissionChecker); |
40 | put(Resource.WIDGETS_BUNDLE, systemEntityPermissionChecker); | 36 | put(Resource.WIDGETS_BUNDLE, systemEntityPermissionChecker); |
41 | put(Resource.WIDGET_TYPE, systemEntityPermissionChecker); | 37 | put(Resource.WIDGET_TYPE, systemEntityPermissionChecker); |
38 | + put(Resource.OAUTH2_CONFIGURATION_INFO, PermissionChecker.allowAllPermissionChecker); | ||
39 | + put(Resource.OAUTH2_CONFIGURATION_TEMPLATE, PermissionChecker.allowAllPermissionChecker); | ||
42 | put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker); | 40 | put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker); |
43 | } | 41 | } |
44 | 42 |
@@ -19,13 +19,10 @@ import org.springframework.stereotype.Component; | @@ -19,13 +19,10 @@ import org.springframework.stereotype.Component; | ||
19 | import org.thingsboard.server.common.data.HasTenantId; | 19 | import org.thingsboard.server.common.data.HasTenantId; |
20 | import org.thingsboard.server.common.data.User; | 20 | import org.thingsboard.server.common.data.User; |
21 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | -import org.thingsboard.server.common.data.id.TenantId; | ||
23 | import org.thingsboard.server.common.data.id.UserId; | 22 | import org.thingsboard.server.common.data.id.UserId; |
24 | import org.thingsboard.server.common.data.security.Authority; | 23 | import org.thingsboard.server.common.data.security.Authority; |
25 | import org.thingsboard.server.service.security.model.SecurityUser; | 24 | import org.thingsboard.server.service.security.model.SecurityUser; |
26 | 25 | ||
27 | -import java.util.HashMap; | ||
28 | - | ||
29 | @Component(value="tenantAdminPermissions") | 26 | @Component(value="tenantAdminPermissions") |
30 | public class TenantAdminPermissions extends AbstractPermissions { | 27 | public class TenantAdminPermissions extends AbstractPermissions { |
31 | 28 |
@@ -49,12 +49,27 @@ public class MiscUtils { | @@ -49,12 +49,27 @@ public class MiscUtils { | ||
49 | } | 49 | } |
50 | 50 | ||
51 | public static String constructBaseUrl(HttpServletRequest request) { | 51 | public static String constructBaseUrl(HttpServletRequest request) { |
52 | - String scheme = request.getScheme(); | 52 | + return String.format("%s://%s:%d", |
53 | + getScheme(request), | ||
54 | + getDomainName(request), | ||
55 | + getPort(request)); | ||
56 | + } | ||
53 | 57 | ||
58 | + public static String getScheme(HttpServletRequest request){ | ||
59 | + String scheme = request.getScheme(); | ||
54 | String forwardedProto = request.getHeader("x-forwarded-proto"); | 60 | String forwardedProto = request.getHeader("x-forwarded-proto"); |
55 | if (forwardedProto != null) { | 61 | if (forwardedProto != null) { |
56 | scheme = forwardedProto; | 62 | scheme = forwardedProto; |
57 | } | 63 | } |
64 | + return scheme; | ||
65 | + } | ||
66 | + | ||
67 | + public static String getDomainName(HttpServletRequest request){ | ||
68 | + return request.getServerName(); | ||
69 | + } | ||
70 | + | ||
71 | + public static int getPort(HttpServletRequest request){ | ||
72 | + String forwardedProto = request.getHeader("x-forwarded-proto"); | ||
58 | 73 | ||
59 | int serverPort = request.getServerPort(); | 74 | int serverPort = request.getServerPort(); |
60 | if (request.getHeader("x-forwarded-port") != null) { | 75 | if (request.getHeader("x-forwarded-port") != null) { |
@@ -72,11 +87,6 @@ public class MiscUtils { | @@ -72,11 +87,6 @@ public class MiscUtils { | ||
72 | break; | 87 | break; |
73 | } | 88 | } |
74 | } | 89 | } |
75 | - | ||
76 | - String baseUrl = String.format("%s://%s:%d", | ||
77 | - scheme, | ||
78 | - request.getServerName(), | ||
79 | - serverPort); | ||
80 | - return baseUrl; | 90 | + return serverPort; |
81 | } | 91 | } |
82 | } | 92 | } |
@@ -113,62 +113,10 @@ security: | @@ -113,62 +113,10 @@ security: | ||
113 | basic: | 113 | basic: |
114 | enabled: "${SECURITY_BASIC_ENABLED:false}" | 114 | enabled: "${SECURITY_BASIC_ENABLED:false}" |
115 | oauth2: | 115 | oauth2: |
116 | - # Enable/disable OAuth 2 login functionality | ||
117 | - # For details please refer to https://thingsboard.io/docs/user-guide/oauth-2-support/ | ||
118 | - enabled: "${SECURITY_OAUTH2_ENABLED:false}" | ||
119 | # Redirect URL where access code from external user management system will be processed | 116 | # Redirect URL where access code from external user management system will be processed |
120 | loginProcessingUrl: "${SECURITY_OAUTH2_LOGIN_PROCESSING_URL:/login/oauth2/code/}" | 117 | loginProcessingUrl: "${SECURITY_OAUTH2_LOGIN_PROCESSING_URL:/login/oauth2/code/}" |
121 | - # List of SSO clients | ||
122 | - clients: | ||
123 | - default: | ||
124 | - # Label that going to be show on login button - 'Login with {loginButtonLabel}' | ||
125 | - loginButtonLabel: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_LABEL:Default}" | ||
126 | - # Icon that going to be show on login button. Material design icon ID (https://material.angularjs.org/latest/api/directive/mdIcon) | ||
127 | - loginButtonIcon: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_ICON:}" | ||
128 | - clientName: "${SECURITY_OAUTH2_DEFAULT_CLIENT_NAME:ClientName}" | ||
129 | - clientId: "${SECURITY_OAUTH2_DEFAULT_CLIENT_ID:}" | ||
130 | - clientSecret: "${SECURITY_OAUTH2_DEFAULT_CLIENT_SECRET:}" | ||
131 | - accessTokenUri: "${SECURITY_OAUTH2_DEFAULT_ACCESS_TOKEN_URI:}" | ||
132 | - authorizationUri: "${SECURITY_OAUTH2_DEFAULT_AUTHORIZATION_URI:}" | ||
133 | - scope: "${SECURITY_OAUTH2_DEFAULT_SCOPE:}" | ||
134 | - # Redirect URL that must be in sync with 'security.oauth2.loginProcessingUrl', but domain name added | ||
135 | - redirectUriTemplate: "${SECURITY_OAUTH2_DEFAULT_REDIRECT_URI_TEMPLATE:http://localhost:8080/login/oauth2/code/}" | ||
136 | - jwkSetUri: "${SECURITY_OAUTH2_DEFAULT_JWK_SET_URI:}" | ||
137 | - # 'authorization_code', 'implicit', 'refresh_token' or 'client_credentials' | ||
138 | - authorizationGrantType: "${SECURITY_OAUTH2_DEFAULT_AUTHORIZATION_GRANT_TYPE:authorization_code}" | ||
139 | - clientAuthenticationMethod: "${SECURITY_OAUTH2_DEFAULT_CLIENT_AUTHENTICATION_METHOD:post}" # basic or post | ||
140 | - userInfoUri: "${SECURITY_OAUTH2_DEFAULT_USER_INFO_URI:}" | ||
141 | - userNameAttributeName: "${SECURITY_OAUTH2_DEFAULT_USER_NAME_ATTRIBUTE_NAME:email}" | ||
142 | - mapperConfig: | ||
143 | - # Allows to create user if it not exists | ||
144 | - allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ALLOW_USER_CREATION:true}" | ||
145 | - # Allows user to setup ThingsBoard internal password and login over default Login window | ||
146 | - activateUser: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ACTIVATE_USER:false}" | ||
147 | - # Mapper type of converter from external user into internal - 'basic' or 'custom' | ||
148 | - type: "${SECURITY_OAUTH2_DEFAULT_MAPPER_TYPE:basic}" | ||
149 | - basic: | ||
150 | - # Key from attributes of external user object to use as email | ||
151 | - emailAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_EMAIL_ATTRIBUTE_KEY:email}" | ||
152 | - firstNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_FIRST_NAME_ATTRIBUTE_KEY:}" | ||
153 | - lastNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_LAST_NAME_ATTRIBUTE_KEY:}" | ||
154 | - # Strategy for generating Tenant from external user object - 'domain', 'email' or 'custom' | ||
155 | - # 'domain' - name of the Tenant will be extracted as domain from the email of the user | ||
156 | - # 'email' - name of the Tenant will email of the user | ||
157 | - # 'custom' - please configure 'tenantNamePattern' for custom mapping | ||
158 | - tenantNameStrategy: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_STRATEGY:domain}" | ||
159 | - # %{attribute_key} as placeholder for attribute value of attributes of external user object | ||
160 | - tenantNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_PATTERN:}" | ||
161 | - # If this field is not empty, user will be created as a user under defined Customer | ||
162 | - # %{attribute_key} as placeholder for attribute value of attributes of external user object | ||
163 | - customerNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_CUSTOMER_NAME_PATTERN:}" | ||
164 | - # If this field is not empty, user will be created with default defined Dashboard | ||
165 | - defaultDashboardName: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_DEFAULT_DASHBOARD_NAME:}" | ||
166 | - # If this field is set 'true' along with non-empty 'defaultDashboardName', user will start from the defined Dashboard in fullscreen mode | ||
167 | - alwaysFullScreen: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALWAYS_FULL_SCREEN:false}" | ||
168 | - custom: | ||
169 | - url: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_URL:}" | ||
170 | - username: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_USERNAME:}" | ||
171 | - password: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_PASSWORD:}" | 118 | + githubMapper: |
119 | + emailUrl: "${SECURITY_OAUTH2_GITHUB_MAPPER_EMAIL_URL_KEY:https://api.github.com/user/emails}" | ||
172 | 120 | ||
173 | # Dashboard parameters | 121 | # Dashboard parameters |
174 | dashboard: | 122 | dashboard: |
common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ConfigTemplateService.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.dao.oauth2; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; | ||
19 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
20 | + | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +public interface OAuth2ConfigTemplateService { | ||
24 | + OAuth2ClientRegistrationTemplate saveClientRegistrationTemplate(OAuth2ClientRegistrationTemplate clientRegistrationTemplate); | ||
25 | + | ||
26 | + OAuth2ClientRegistrationTemplate findClientRegistrationTemplateById(OAuth2ClientRegistrationTemplateId templateId); | ||
27 | + | ||
28 | + List<OAuth2ClientRegistrationTemplate> findAllClientRegistrationTemplates(); | ||
29 | + | ||
30 | + void deleteClientRegistrationTemplateById(OAuth2ClientRegistrationTemplateId templateId); | ||
31 | +} |
@@ -16,10 +16,20 @@ | @@ -16,10 +16,20 @@ | ||
16 | package org.thingsboard.server.dao.oauth2; | 16 | package org.thingsboard.server.dao.oauth2; |
17 | 17 | ||
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.OAuth2ClientRegistrationInfo; | ||
20 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams; | ||
19 | 21 | ||
20 | import java.util.List; | 22 | import java.util.List; |
23 | +import java.util.UUID; | ||
21 | 24 | ||
22 | public interface OAuth2Service { | 25 | public interface OAuth2Service { |
26 | + List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName); | ||
23 | 27 | ||
24 | - List<OAuth2ClientInfo> getOAuth2Clients(); | 28 | + void saveOAuth2Params(OAuth2ClientsParams oauth2Params); |
29 | + | ||
30 | + OAuth2ClientsParams findOAuth2Params(); | ||
31 | + | ||
32 | + OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id); | ||
33 | + | ||
34 | + List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos(); | ||
25 | } | 35 | } |
@@ -24,7 +24,7 @@ public interface AdminSettingsService { | @@ -24,7 +24,7 @@ public interface AdminSettingsService { | ||
24 | AdminSettings findAdminSettingsById(TenantId tenantId, AdminSettingsId adminSettingsId); | 24 | AdminSettings findAdminSettingsById(TenantId tenantId, AdminSettingsId adminSettingsId); |
25 | 25 | ||
26 | AdminSettings findAdminSettingsByKey(TenantId tenantId, String key); | 26 | AdminSettings findAdminSettingsByKey(TenantId tenantId, String key); |
27 | - | 27 | + |
28 | AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings); | 28 | AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings); |
29 | - | 29 | + |
30 | } | 30 | } |
common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationId.java
renamed from
common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2IntegrationId.java
@@ -20,16 +20,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; | @@ -20,16 +20,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | 20 | ||
21 | import java.util.UUID; | 21 | import java.util.UUID; |
22 | 22 | ||
23 | -public class OAuth2IntegrationId extends UUIDBased { | ||
24 | - | ||
25 | - private static final long serialVersionUID = 1L; | 23 | +public class OAuth2ClientRegistrationId extends UUIDBased { |
26 | 24 | ||
27 | @JsonCreator | 25 | @JsonCreator |
28 | - public OAuth2IntegrationId(@JsonProperty("id") UUID id) { | 26 | + public OAuth2ClientRegistrationId(@JsonProperty("id") UUID id) { |
29 | super(id); | 27 | super(id); |
30 | } | 28 | } |
31 | 29 | ||
32 | - public static OAuth2IntegrationId fromString(String oauth2IntegrationId) { | ||
33 | - return new OAuth2IntegrationId(UUID.fromString(oauth2IntegrationId)); | 30 | + public static OAuth2ClientRegistrationId fromString(String clientRegistrationId) { |
31 | + return new OAuth2ClientRegistrationId(UUID.fromString(clientRegistrationId)); | ||
34 | } | 32 | } |
35 | } | 33 | } |
common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationInfoId.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.common.data.id; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonCreator; | ||
19 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | + | ||
21 | +import java.util.UUID; | ||
22 | + | ||
23 | +public class OAuth2ClientRegistrationInfoId extends UUIDBased { | ||
24 | + | ||
25 | + @JsonCreator | ||
26 | + public OAuth2ClientRegistrationInfoId(@JsonProperty("id") UUID id) { | ||
27 | + super(id); | ||
28 | + } | ||
29 | + | ||
30 | + public static OAuth2ClientRegistrationInfoId fromString(String clientRegistrationInfoId) { | ||
31 | + return new OAuth2ClientRegistrationInfoId(UUID.fromString(clientRegistrationInfoId)); | ||
32 | + } | ||
33 | +} |
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.common.data.id; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonCreator; | ||
19 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | + | ||
21 | +import java.util.UUID; | ||
22 | + | ||
23 | +public class OAuth2ClientRegistrationTemplateId extends UUIDBased { | ||
24 | + | ||
25 | + @JsonCreator | ||
26 | + public OAuth2ClientRegistrationTemplateId(@JsonProperty("id") UUID id) { | ||
27 | + super(id); | ||
28 | + } | ||
29 | + | ||
30 | + public static OAuth2ClientRegistrationTemplateId fromString(String clientRegistrationTemplateId) { | ||
31 | + return new OAuth2ClientRegistrationTemplateId(UUID.fromString(clientRegistrationTemplateId)); | ||
32 | + } | ||
33 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ClientRegistrationDto.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Client.java
@@ -13,27 +13,32 @@ | @@ -13,27 +13,32 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.dao.oauth2; | 16 | +package org.thingsboard.server.common.data.oauth2; |
17 | 17 | ||
18 | -import lombok.Data; | 18 | +import com.fasterxml.jackson.databind.JsonNode; |
19 | +import lombok.*; | ||
20 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
19 | 21 | ||
20 | -@Data | ||
21 | -public class OAuth2Client { | 22 | +import java.util.List; |
22 | 23 | ||
23 | - private String loginButtonLabel; | ||
24 | - private String loginButtonIcon; | ||
25 | - private String clientName; | 24 | +@EqualsAndHashCode |
25 | +@Data | ||
26 | +@ToString(exclude = {"clientSecret"}) | ||
27 | +@NoArgsConstructor | ||
28 | +@AllArgsConstructor | ||
29 | +@Builder | ||
30 | +public class ClientRegistrationDto { | ||
31 | + private OAuth2MapperConfig mapperConfig; | ||
26 | private String clientId; | 32 | private String clientId; |
27 | private String clientSecret; | 33 | private String clientSecret; |
28 | - private String accessTokenUri; | ||
29 | private String authorizationUri; | 34 | private String authorizationUri; |
30 | - private String scope; | ||
31 | - private String redirectUriTemplate; | ||
32 | - private String jwkSetUri; | ||
33 | - private String authorizationGrantType; | ||
34 | - private String clientAuthenticationMethod; | 35 | + private String accessTokenUri; |
36 | + private List<String> scope; | ||
35 | private String userInfoUri; | 37 | private String userInfoUri; |
36 | private String userNameAttributeName; | 38 | private String userNameAttributeName; |
37 | - private OAuth2ClientMapperConfig mapperConfig; | ||
38 | - | 39 | + private String jwkSetUri; |
40 | + private String clientAuthenticationMethod; | ||
41 | + private String loginButtonLabel; | ||
42 | + private String loginButtonIcon; | ||
43 | + private JsonNode additionalInfo; | ||
39 | } | 44 | } |
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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.*; | ||
19 | + | ||
20 | +@EqualsAndHashCode | ||
21 | +@Data | ||
22 | +@ToString | ||
23 | +@NoArgsConstructor | ||
24 | +@AllArgsConstructor | ||
25 | +@Builder | ||
26 | +public class DomainInfo { | ||
27 | + private SchemeType scheme; | ||
28 | + private String name; | ||
29 | +} |
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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | + | ||
21 | +@EqualsAndHashCode(callSuper = true) | ||
22 | +@Data | ||
23 | +public class ExtendedOAuth2ClientRegistrationInfo extends OAuth2ClientRegistrationInfo { | ||
24 | + | ||
25 | + private String domainName; | ||
26 | + private SchemeType domainScheme; | ||
27 | + | ||
28 | + public ExtendedOAuth2ClientRegistrationInfo() { | ||
29 | + super(); | ||
30 | + } | ||
31 | + | ||
32 | + public ExtendedOAuth2ClientRegistrationInfo(OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo, | ||
33 | + SchemeType domainScheme, | ||
34 | + String domainName) { | ||
35 | + super(oAuth2ClientRegistrationInfo); | ||
36 | + this.domainScheme = domainScheme; | ||
37 | + this.domainName = domainName; | ||
38 | + } | ||
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.common.data.oauth2; | ||
17 | + | ||
18 | +public enum MapperType { | ||
19 | + BASIC, CUSTOM, GITHUB; | ||
20 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2BasicMapperConfig.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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.*; | ||
19 | + | ||
20 | +@Builder(toBuilder = true) | ||
21 | +@EqualsAndHashCode | ||
22 | +@Data | ||
23 | +@ToString | ||
24 | +public class OAuth2BasicMapperConfig { | ||
25 | + private final String emailAttributeKey; | ||
26 | + private final String firstNameAttributeKey; | ||
27 | + private final String lastNameAttributeKey; | ||
28 | + private final TenantNameStrategyType tenantNameStrategy; | ||
29 | + private final String tenantNamePattern; | ||
30 | + private final String customerNamePattern; | ||
31 | + private final String defaultDashboardName; | ||
32 | + private final boolean alwaysFullScreen; | ||
33 | +} |
@@ -17,27 +17,20 @@ package org.thingsboard.server.common.data.oauth2; | @@ -17,27 +17,20 @@ package org.thingsboard.server.common.data.oauth2; | ||
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | import lombok.EqualsAndHashCode; | 19 | import lombok.EqualsAndHashCode; |
20 | -import org.thingsboard.server.common.data.BaseData; | ||
21 | -import org.thingsboard.server.common.data.id.OAuth2IntegrationId; | 20 | +import lombok.NoArgsConstructor; |
21 | +import lombok.AllArgsConstructor; | ||
22 | 22 | ||
23 | -@EqualsAndHashCode(callSuper = true) | 23 | +@EqualsAndHashCode |
24 | @Data | 24 | @Data |
25 | -public class OAuth2ClientInfo extends BaseData<OAuth2IntegrationId> { | 25 | +@NoArgsConstructor |
26 | +@AllArgsConstructor | ||
27 | +public class OAuth2ClientInfo { | ||
26 | 28 | ||
27 | private String name; | 29 | private String name; |
28 | private String icon; | 30 | private String icon; |
29 | private String url; | 31 | private String url; |
30 | 32 | ||
31 | - public OAuth2ClientInfo() { | ||
32 | - super(); | ||
33 | - } | ||
34 | - | ||
35 | - public OAuth2ClientInfo(OAuth2IntegrationId id) { | ||
36 | - super(id); | ||
37 | - } | ||
38 | - | ||
39 | public OAuth2ClientInfo(OAuth2ClientInfo oauth2ClientInfo) { | 33 | public OAuth2ClientInfo(OAuth2ClientInfo oauth2ClientInfo) { |
40 | - super(oauth2ClientInfo); | ||
41 | this.name = oauth2ClientInfo.getName(); | 34 | this.name = oauth2ClientInfo.getName(); |
42 | this.icon = oauth2ClientInfo.getIcon(); | 35 | this.icon = oauth2ClientInfo.getIcon(); |
43 | this.url = oauth2ClientInfo.getUrl(); | 36 | this.url = oauth2ClientInfo.getUrl(); |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistration.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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import lombok.NoArgsConstructor; | ||
21 | +import lombok.ToString; | ||
22 | +import org.thingsboard.server.common.data.BaseData; | ||
23 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId; | ||
24 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
25 | + | ||
26 | +@EqualsAndHashCode(callSuper = true) | ||
27 | +@Data | ||
28 | +@ToString | ||
29 | +@NoArgsConstructor | ||
30 | +public class OAuth2ClientRegistration extends BaseData<OAuth2ClientRegistrationId> { | ||
31 | + | ||
32 | + private OAuth2ClientRegistrationInfoId clientRegistrationId; | ||
33 | + private String domainName; | ||
34 | + private SchemeType domainScheme; | ||
35 | + | ||
36 | + public OAuth2ClientRegistration(OAuth2ClientRegistration clientRegistration) { | ||
37 | + super(clientRegistration); | ||
38 | + this.clientRegistrationId = clientRegistration.clientRegistrationId; | ||
39 | + this.domainName = clientRegistration.domainName; | ||
40 | + this.domainScheme = clientRegistration.domainScheme; | ||
41 | + } | ||
42 | +} |
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.common.data.oauth2; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.EqualsAndHashCode; | ||
21 | +import lombok.NoArgsConstructor; | ||
22 | +import lombok.ToString; | ||
23 | +import org.thingsboard.server.common.data.HasName; | ||
24 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | ||
25 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
26 | + | ||
27 | +import java.util.List; | ||
28 | + | ||
29 | +@EqualsAndHashCode(callSuper = true) | ||
30 | +@Data | ||
31 | +@ToString(exclude = {"clientSecret"}) | ||
32 | +@NoArgsConstructor | ||
33 | +public class OAuth2ClientRegistrationInfo extends SearchTextBasedWithAdditionalInfo<OAuth2ClientRegistrationInfoId> implements HasName { | ||
34 | + | ||
35 | + private boolean enabled; | ||
36 | + private OAuth2MapperConfig mapperConfig; | ||
37 | + private String clientId; | ||
38 | + private String clientSecret; | ||
39 | + private String authorizationUri; | ||
40 | + private String accessTokenUri; | ||
41 | + private List<String> scope; | ||
42 | + private String userInfoUri; | ||
43 | + private String userNameAttributeName; | ||
44 | + private String jwkSetUri; | ||
45 | + private String clientAuthenticationMethod; | ||
46 | + private String loginButtonLabel; | ||
47 | + private String loginButtonIcon; | ||
48 | + | ||
49 | + public OAuth2ClientRegistrationInfo(OAuth2ClientRegistrationInfo clientRegistration) { | ||
50 | + super(clientRegistration); | ||
51 | + this.enabled = clientRegistration.enabled; | ||
52 | + this.mapperConfig = clientRegistration.mapperConfig; | ||
53 | + this.clientId = clientRegistration.clientId; | ||
54 | + this.clientSecret = clientRegistration.clientSecret; | ||
55 | + this.authorizationUri = clientRegistration.authorizationUri; | ||
56 | + this.accessTokenUri = clientRegistration.accessTokenUri; | ||
57 | + this.scope = clientRegistration.scope; | ||
58 | + this.userInfoUri = clientRegistration.userInfoUri; | ||
59 | + this.userNameAttributeName = clientRegistration.userNameAttributeName; | ||
60 | + this.jwkSetUri = clientRegistration.jwkSetUri; | ||
61 | + this.clientAuthenticationMethod = clientRegistration.clientAuthenticationMethod; | ||
62 | + this.loginButtonLabel = clientRegistration.loginButtonLabel; | ||
63 | + this.loginButtonIcon = clientRegistration.loginButtonIcon; | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + @JsonProperty(access = JsonProperty.Access.READ_ONLY) | ||
68 | + public String getName() { | ||
69 | + return loginButtonLabel; | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public String getSearchText() { | ||
74 | + return getName(); | ||
75 | + } | ||
76 | +} |
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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import lombok.NoArgsConstructor; | ||
21 | +import lombok.ToString; | ||
22 | +import org.thingsboard.server.common.data.HasName; | ||
23 | +import org.thingsboard.server.common.data.HasTenantId; | ||
24 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | ||
25 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; | ||
26 | +import org.thingsboard.server.common.data.id.TenantId; | ||
27 | + | ||
28 | +import java.util.List; | ||
29 | + | ||
30 | +@EqualsAndHashCode(callSuper = true) | ||
31 | +@Data | ||
32 | +@ToString | ||
33 | +@NoArgsConstructor | ||
34 | +public class OAuth2ClientRegistrationTemplate extends SearchTextBasedWithAdditionalInfo<OAuth2ClientRegistrationTemplateId> implements HasName { | ||
35 | + | ||
36 | + private String providerId; | ||
37 | + private MapperType mapperType; | ||
38 | + private OAuth2BasicMapperConfig basic; | ||
39 | + private String authorizationUri; | ||
40 | + private String accessTokenUri; | ||
41 | + private List<String> scope; | ||
42 | + private String userInfoUri; | ||
43 | + private String userNameAttributeName; | ||
44 | + private String jwkSetUri; | ||
45 | + private String clientAuthenticationMethod; | ||
46 | + private String comment; | ||
47 | + private String loginButtonIcon; | ||
48 | + private String loginButtonLabel; | ||
49 | + private String helpLink; | ||
50 | + | ||
51 | + public OAuth2ClientRegistrationTemplate(OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
52 | + super(clientRegistrationTemplate); | ||
53 | + this.providerId = clientRegistrationTemplate.providerId; | ||
54 | + this.mapperType = clientRegistrationTemplate.mapperType; | ||
55 | + this.basic = clientRegistrationTemplate.basic; | ||
56 | + this.authorizationUri = clientRegistrationTemplate.authorizationUri; | ||
57 | + this.accessTokenUri = clientRegistrationTemplate.accessTokenUri; | ||
58 | + this.scope = clientRegistrationTemplate.scope; | ||
59 | + this.userInfoUri = clientRegistrationTemplate.userInfoUri; | ||
60 | + this.userNameAttributeName = clientRegistrationTemplate.userNameAttributeName; | ||
61 | + this.jwkSetUri = clientRegistrationTemplate.jwkSetUri; | ||
62 | + this.clientAuthenticationMethod = clientRegistrationTemplate.clientAuthenticationMethod; | ||
63 | + this.comment = clientRegistrationTemplate.comment; | ||
64 | + this.loginButtonIcon = clientRegistrationTemplate.loginButtonIcon; | ||
65 | + this.loginButtonLabel = clientRegistrationTemplate.loginButtonLabel; | ||
66 | + this.helpLink = clientRegistrationTemplate.helpLink; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public String getName() { | ||
71 | + return providerId; | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public String getSearchText() { | ||
76 | + return getName(); | ||
77 | + } | ||
78 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsDomainParams.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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.*; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | +import java.util.Set; | ||
22 | + | ||
23 | +@EqualsAndHashCode | ||
24 | +@Data | ||
25 | +@ToString | ||
26 | +@Builder(toBuilder = true) | ||
27 | +@NoArgsConstructor | ||
28 | +@AllArgsConstructor | ||
29 | +public class OAuth2ClientsDomainParams { | ||
30 | + private Set<DomainInfo> domainInfos; | ||
31 | + private Set<ClientRegistrationDto> clientRegistrations; | ||
32 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsParams.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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.*; | ||
19 | +import java.util.Set; | ||
20 | + | ||
21 | +@EqualsAndHashCode | ||
22 | +@Data | ||
23 | +@ToString | ||
24 | +@Builder(toBuilder = true) | ||
25 | +@NoArgsConstructor | ||
26 | +@AllArgsConstructor | ||
27 | +public class OAuth2ClientsParams { | ||
28 | + private boolean enabled; | ||
29 | + private Set<OAuth2ClientsDomainParams> domainsParams; | ||
30 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2CustomMapperConfig.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.common.data.oauth2; | ||
17 | + | ||
18 | +import lombok.*; | ||
19 | + | ||
20 | +@Builder(toBuilder = true) | ||
21 | +@EqualsAndHashCode | ||
22 | +@Data | ||
23 | +@ToString(exclude = {"password"}) | ||
24 | +public class OAuth2CustomMapperConfig { | ||
25 | + private final String url; | ||
26 | + private final String username; | ||
27 | + private final String password; | ||
28 | + private final boolean sendToken; | ||
29 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientMapperConfig.java
@@ -13,35 +13,21 @@ | @@ -13,35 +13,21 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.dao.oauth2; | 16 | +package org.thingsboard.server.common.data.oauth2; |
17 | 17 | ||
18 | +import lombok.Builder; | ||
18 | import lombok.Data; | 19 | import lombok.Data; |
20 | +import lombok.EqualsAndHashCode; | ||
21 | +import lombok.ToString; | ||
19 | 22 | ||
23 | +@Builder(toBuilder = true) | ||
24 | +@EqualsAndHashCode | ||
20 | @Data | 25 | @Data |
21 | -public class OAuth2ClientMapperConfig { | ||
22 | - | 26 | +@ToString |
27 | +public class OAuth2MapperConfig { | ||
23 | private boolean allowUserCreation; | 28 | private boolean allowUserCreation; |
24 | private boolean activateUser; | 29 | private boolean activateUser; |
25 | - private String type; | ||
26 | - private BasicOAuth2ClientMapperConfig basic; | ||
27 | - private CustomOAuth2ClientMapperConfig custom; | ||
28 | - | ||
29 | - @Data | ||
30 | - public static class BasicOAuth2ClientMapperConfig { | ||
31 | - private String emailAttributeKey; | ||
32 | - private String firstNameAttributeKey; | ||
33 | - private String lastNameAttributeKey; | ||
34 | - private String tenantNameStrategy; | ||
35 | - private String tenantNamePattern; | ||
36 | - private String customerNamePattern; | ||
37 | - private boolean alwaysFullScreen; | ||
38 | - private String defaultDashboardName; | ||
39 | - } | ||
40 | - | ||
41 | - @Data | ||
42 | - public static class CustomOAuth2ClientMapperConfig { | ||
43 | - private String url; | ||
44 | - private String username; | ||
45 | - private String password; | ||
46 | - } | 30 | + private MapperType type; |
31 | + private OAuth2BasicMapperConfig basic; | ||
32 | + private OAuth2CustomMapperConfig custom; | ||
47 | } | 33 | } |
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.common.data.oauth2; | ||
17 | + | ||
18 | +public enum SchemeType { | ||
19 | + HTTP, HTTPS, MIXED; | ||
20 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/TenantNameStrategyType.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.common.data.oauth2; | ||
17 | + | ||
18 | +public enum TenantNameStrategyType { | ||
19 | + DOMAIN, EMAIL, CUSTOM; | ||
20 | +} |
@@ -390,6 +390,53 @@ public class ModelConstants { | @@ -390,6 +390,53 @@ public class ModelConstants { | ||
390 | public static final String RULE_NODE_STATE_DATA_PROPERTY = "state_data"; | 390 | public static final String RULE_NODE_STATE_DATA_PROPERTY = "state_data"; |
391 | 391 | ||
392 | /** | 392 | /** |
393 | + * OAuth2 client registration constants. | ||
394 | + */ | ||
395 | + public static final String OAUTH2_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; | ||
396 | + public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info"; | ||
397 | + public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration"; | ||
398 | + public static final String OAUTH2_CLIENT_REGISTRATION_TO_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_client_registration_to_domain"; | ||
399 | + public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template"; | ||
400 | + public static final String OAUTH2_ENABLED_PROPERTY = "enabled"; | ||
401 | + public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id"; | ||
402 | + public static final String OAUTH2_CLIENT_REGISTRATION_INFO_ID_PROPERTY = "client_registration_info_id"; | ||
403 | + public static final String OAUTH2_DOMAIN_NAME_PROPERTY = "domain_name"; | ||
404 | + public static final String OAUTH2_DOMAIN_SCHEME_PROPERTY = "domain_scheme"; | ||
405 | + public static final String OAUTH2_CLIENT_ID_PROPERTY = "client_id"; | ||
406 | + public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret"; | ||
407 | + public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri"; | ||
408 | + public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri"; | ||
409 | + public static final String OAUTH2_REDIRECT_URI_TEMPLATE_PROPERTY = "redirect_uri_template"; | ||
410 | + public static final String OAUTH2_SCOPE_PROPERTY = "scope"; | ||
411 | + public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri"; | ||
412 | + public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name"; | ||
413 | + public static final String OAUTH2_JWK_SET_URI_PROPERTY = "jwk_set_uri"; | ||
414 | + public static final String OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY = "client_authentication_method"; | ||
415 | + public static final String OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY = "login_button_label"; | ||
416 | + public static final String OAUTH2_LOGIN_BUTTON_ICON_PROPERTY = "login_button_icon"; | ||
417 | + public static final String OAUTH2_ALLOW_USER_CREATION_PROPERTY = "allow_user_creation"; | ||
418 | + public static final String OAUTH2_ACTIVATE_USER_PROPERTY = "activate_user"; | ||
419 | + public static final String OAUTH2_MAPPER_TYPE_PROPERTY = "type"; | ||
420 | + public static final String OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY = "basic_email_attribute_key"; | ||
421 | + public static final String OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY = "basic_first_name_attribute_key"; | ||
422 | + public static final String OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY = "basic_last_name_attribute_key"; | ||
423 | + public static final String OAUTH2_TENANT_NAME_STRATEGY_PROPERTY = "basic_tenant_name_strategy"; | ||
424 | + public static final String OAUTH2_TENANT_NAME_PATTERN_PROPERTY = "basic_tenant_name_pattern"; | ||
425 | + public static final String OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY = "basic_customer_name_pattern"; | ||
426 | + public static final String OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY = "basic_default_dashboard_name"; | ||
427 | + public static final String OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY = "basic_always_full_screen"; | ||
428 | + public static final String OAUTH2_MAPPER_URL_PROPERTY = "custom_url"; | ||
429 | + public static final String OAUTH2_MAPPER_USERNAME_PROPERTY = "custom_username"; | ||
430 | + public static final String OAUTH2_MAPPER_PASSWORD_PROPERTY = "custom_password"; | ||
431 | + public static final String OAUTH2_MAPPER_SEND_TOKEN_PROPERTY = "custom_send_token"; | ||
432 | + public static final String OAUTH2_TEMPLATE_COMMENT_PROPERTY = "comment"; | ||
433 | + public static final String OAUTH2_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; | ||
434 | + public static final String OAUTH2_TEMPLATE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; | ||
435 | + public static final String OAUTH2_TEMPLATE_LOGIN_BUTTON_ICON_PROPERTY = OAUTH2_LOGIN_BUTTON_ICON_PROPERTY; | ||
436 | + public static final String OAUTH2_TEMPLATE_LOGIN_BUTTON_LABEL_PROPERTY = OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY; | ||
437 | + public static final String OAUTH2_TEMPLATE_HELP_LINK_PROPERTY = "help_link"; | ||
438 | + | ||
439 | + /** | ||
393 | * Cassandra attributes and timeseries constants. | 440 | * Cassandra attributes and timeseries constants. |
394 | */ | 441 | */ |
395 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; | 442 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; |
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.dao.model.sql; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.EqualsAndHashCode; | ||
21 | +import org.hibernate.annotations.Type; | ||
22 | +import org.hibernate.annotations.TypeDef; | ||
23 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
24 | +import org.thingsboard.server.common.data.oauth2.*; | ||
25 | +import org.thingsboard.server.dao.model.BaseSqlEntity; | ||
26 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
27 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | ||
28 | + | ||
29 | +import javax.persistence.*; | ||
30 | +import java.util.Arrays; | ||
31 | + | ||
32 | +@Data | ||
33 | +@EqualsAndHashCode(callSuper = true) | ||
34 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | ||
35 | +@MappedSuperclass | ||
36 | +public abstract class AbstractOAuth2ClientRegistrationInfoEntity<T extends OAuth2ClientRegistrationInfo> extends BaseSqlEntity<T> { | ||
37 | + | ||
38 | + @Column(name = ModelConstants.OAUTH2_ENABLED_PROPERTY) | ||
39 | + private Boolean enabled; | ||
40 | + @Column(name = ModelConstants.OAUTH2_CLIENT_ID_PROPERTY) | ||
41 | + private String clientId; | ||
42 | + @Column(name = ModelConstants.OAUTH2_CLIENT_SECRET_PROPERTY) | ||
43 | + private String clientSecret; | ||
44 | + @Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY) | ||
45 | + private String authorizationUri; | ||
46 | + @Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY) | ||
47 | + private String tokenUri; | ||
48 | + @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY) | ||
49 | + private String scope; | ||
50 | + @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY) | ||
51 | + private String userInfoUri; | ||
52 | + @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY) | ||
53 | + private String userNameAttributeName; | ||
54 | + @Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY) | ||
55 | + private String jwkSetUri; | ||
56 | + @Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY) | ||
57 | + private String clientAuthenticationMethod; | ||
58 | + @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY) | ||
59 | + private String loginButtonLabel; | ||
60 | + @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_ICON_PROPERTY) | ||
61 | + private String loginButtonIcon; | ||
62 | + @Column(name = ModelConstants.OAUTH2_ALLOW_USER_CREATION_PROPERTY) | ||
63 | + private Boolean allowUserCreation; | ||
64 | + @Column(name = ModelConstants.OAUTH2_ACTIVATE_USER_PROPERTY) | ||
65 | + private Boolean activateUser; | ||
66 | + @Enumerated(EnumType.STRING) | ||
67 | + @Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY) | ||
68 | + private MapperType type; | ||
69 | + @Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY) | ||
70 | + private String emailAttributeKey; | ||
71 | + @Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY) | ||
72 | + private String firstNameAttributeKey; | ||
73 | + @Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY) | ||
74 | + private String lastNameAttributeKey; | ||
75 | + @Enumerated(EnumType.STRING) | ||
76 | + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY) | ||
77 | + private TenantNameStrategyType tenantNameStrategy; | ||
78 | + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY) | ||
79 | + private String tenantNamePattern; | ||
80 | + @Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY) | ||
81 | + private String customerNamePattern; | ||
82 | + @Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY) | ||
83 | + private String defaultDashboardName; | ||
84 | + @Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY) | ||
85 | + private Boolean alwaysFullScreen; | ||
86 | + @Column(name = ModelConstants.OAUTH2_MAPPER_URL_PROPERTY) | ||
87 | + private String url; | ||
88 | + @Column(name = ModelConstants.OAUTH2_MAPPER_USERNAME_PROPERTY) | ||
89 | + private String username; | ||
90 | + @Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY) | ||
91 | + private String password; | ||
92 | + @Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY) | ||
93 | + private Boolean sendToken; | ||
94 | + | ||
95 | + @Type(type = "json") | ||
96 | + @Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY) | ||
97 | + private JsonNode additionalInfo; | ||
98 | + | ||
99 | + public AbstractOAuth2ClientRegistrationInfoEntity() { | ||
100 | + super(); | ||
101 | + } | ||
102 | + | ||
103 | + public AbstractOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfo clientRegistrationInfo) { | ||
104 | + if (clientRegistrationInfo.getId() != null) { | ||
105 | + this.setUuid(clientRegistrationInfo.getId().getId()); | ||
106 | + } | ||
107 | + this.createdTime = clientRegistrationInfo.getCreatedTime(); | ||
108 | + this.enabled = clientRegistrationInfo.isEnabled(); | ||
109 | + this.clientId = clientRegistrationInfo.getClientId(); | ||
110 | + this.clientSecret = clientRegistrationInfo.getClientSecret(); | ||
111 | + this.authorizationUri = clientRegistrationInfo.getAuthorizationUri(); | ||
112 | + this.tokenUri = clientRegistrationInfo.getAccessTokenUri(); | ||
113 | + this.scope = clientRegistrationInfo.getScope().stream().reduce((result, element) -> result + "," + element).orElse(""); | ||
114 | + this.userInfoUri = clientRegistrationInfo.getUserInfoUri(); | ||
115 | + this.userNameAttributeName = clientRegistrationInfo.getUserNameAttributeName(); | ||
116 | + this.jwkSetUri = clientRegistrationInfo.getJwkSetUri(); | ||
117 | + this.clientAuthenticationMethod = clientRegistrationInfo.getClientAuthenticationMethod(); | ||
118 | + this.loginButtonLabel = clientRegistrationInfo.getLoginButtonLabel(); | ||
119 | + this.loginButtonIcon = clientRegistrationInfo.getLoginButtonIcon(); | ||
120 | + this.additionalInfo = clientRegistrationInfo.getAdditionalInfo(); | ||
121 | + OAuth2MapperConfig mapperConfig = clientRegistrationInfo.getMapperConfig(); | ||
122 | + if (mapperConfig != null) { | ||
123 | + this.allowUserCreation = mapperConfig.isAllowUserCreation(); | ||
124 | + this.activateUser = mapperConfig.isActivateUser(); | ||
125 | + this.type = mapperConfig.getType(); | ||
126 | + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic(); | ||
127 | + if (basicConfig != null) { | ||
128 | + this.emailAttributeKey = basicConfig.getEmailAttributeKey(); | ||
129 | + this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey(); | ||
130 | + this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey(); | ||
131 | + this.tenantNameStrategy = basicConfig.getTenantNameStrategy(); | ||
132 | + this.tenantNamePattern = basicConfig.getTenantNamePattern(); | ||
133 | + this.customerNamePattern = basicConfig.getCustomerNamePattern(); | ||
134 | + this.defaultDashboardName = basicConfig.getDefaultDashboardName(); | ||
135 | + this.alwaysFullScreen = basicConfig.isAlwaysFullScreen(); | ||
136 | + } | ||
137 | + OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom(); | ||
138 | + if (customConfig != null) { | ||
139 | + this.url = customConfig.getUrl(); | ||
140 | + this.username = customConfig.getUsername(); | ||
141 | + this.password = customConfig.getPassword(); | ||
142 | + this.sendToken = customConfig.isSendToken(); | ||
143 | + } | ||
144 | + } | ||
145 | + } | ||
146 | + | ||
147 | + public AbstractOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity) { | ||
148 | + this.setId(oAuth2ClientRegistrationInfoEntity.getId()); | ||
149 | + this.setCreatedTime(oAuth2ClientRegistrationInfoEntity.getCreatedTime()); | ||
150 | + this.enabled = oAuth2ClientRegistrationInfoEntity.getEnabled(); | ||
151 | + this.clientId = oAuth2ClientRegistrationInfoEntity.getClientId(); | ||
152 | + this.clientSecret = oAuth2ClientRegistrationInfoEntity.getClientSecret(); | ||
153 | + this.authorizationUri = oAuth2ClientRegistrationInfoEntity.getAuthorizationUri(); | ||
154 | + this.tokenUri = oAuth2ClientRegistrationInfoEntity.getTokenUri(); | ||
155 | + this.scope = oAuth2ClientRegistrationInfoEntity.getScope(); | ||
156 | + this.userInfoUri = oAuth2ClientRegistrationInfoEntity.getUserInfoUri(); | ||
157 | + this.userNameAttributeName = oAuth2ClientRegistrationInfoEntity.getUserNameAttributeName(); | ||
158 | + this.jwkSetUri = oAuth2ClientRegistrationInfoEntity.getJwkSetUri(); | ||
159 | + this.clientAuthenticationMethod = oAuth2ClientRegistrationInfoEntity.getClientAuthenticationMethod(); | ||
160 | + this.loginButtonLabel = oAuth2ClientRegistrationInfoEntity.getLoginButtonLabel(); | ||
161 | + this.loginButtonIcon = oAuth2ClientRegistrationInfoEntity.getLoginButtonIcon(); | ||
162 | + this.additionalInfo = oAuth2ClientRegistrationInfoEntity.getAdditionalInfo(); | ||
163 | + this.allowUserCreation = oAuth2ClientRegistrationInfoEntity.getAllowUserCreation(); | ||
164 | + this.activateUser = oAuth2ClientRegistrationInfoEntity.getActivateUser(); | ||
165 | + this.type = oAuth2ClientRegistrationInfoEntity.getType(); | ||
166 | + this.emailAttributeKey = oAuth2ClientRegistrationInfoEntity.getEmailAttributeKey(); | ||
167 | + this.firstNameAttributeKey = oAuth2ClientRegistrationInfoEntity.getFirstNameAttributeKey(); | ||
168 | + this.lastNameAttributeKey = oAuth2ClientRegistrationInfoEntity.getLastNameAttributeKey(); | ||
169 | + this.tenantNameStrategy = oAuth2ClientRegistrationInfoEntity.getTenantNameStrategy(); | ||
170 | + this.tenantNamePattern = oAuth2ClientRegistrationInfoEntity.getTenantNamePattern(); | ||
171 | + this.customerNamePattern = oAuth2ClientRegistrationInfoEntity.getCustomerNamePattern(); | ||
172 | + this.defaultDashboardName = oAuth2ClientRegistrationInfoEntity.getDefaultDashboardName(); | ||
173 | + this.alwaysFullScreen = oAuth2ClientRegistrationInfoEntity.getAlwaysFullScreen(); | ||
174 | + this.url = oAuth2ClientRegistrationInfoEntity.getUrl(); | ||
175 | + this.username = oAuth2ClientRegistrationInfoEntity.getUsername(); | ||
176 | + this.password = oAuth2ClientRegistrationInfoEntity.getPassword(); | ||
177 | + this.sendToken = oAuth2ClientRegistrationInfoEntity.getSendToken(); | ||
178 | + } | ||
179 | + | ||
180 | + | ||
181 | + protected OAuth2ClientRegistrationInfo toOAuth2ClientRegistrationInfo() { | ||
182 | + OAuth2ClientRegistrationInfo clientRegistrationInfo = new OAuth2ClientRegistrationInfo(); | ||
183 | + clientRegistrationInfo.setId(new OAuth2ClientRegistrationInfoId(id)); | ||
184 | + clientRegistrationInfo.setEnabled(enabled); | ||
185 | + clientRegistrationInfo.setCreatedTime(createdTime); | ||
186 | + clientRegistrationInfo.setAdditionalInfo(additionalInfo); | ||
187 | + clientRegistrationInfo.setMapperConfig( | ||
188 | + OAuth2MapperConfig.builder() | ||
189 | + .allowUserCreation(allowUserCreation) | ||
190 | + .activateUser(activateUser) | ||
191 | + .type(type) | ||
192 | + .basic( | ||
193 | + (type == MapperType.BASIC || type == MapperType.GITHUB) ? | ||
194 | + OAuth2BasicMapperConfig.builder() | ||
195 | + .emailAttributeKey(emailAttributeKey) | ||
196 | + .firstNameAttributeKey(firstNameAttributeKey) | ||
197 | + .lastNameAttributeKey(lastNameAttributeKey) | ||
198 | + .tenantNameStrategy(tenantNameStrategy) | ||
199 | + .tenantNamePattern(tenantNamePattern) | ||
200 | + .customerNamePattern(customerNamePattern) | ||
201 | + .defaultDashboardName(defaultDashboardName) | ||
202 | + .alwaysFullScreen(alwaysFullScreen) | ||
203 | + .build() | ||
204 | + : null | ||
205 | + ) | ||
206 | + .custom( | ||
207 | + type == MapperType.CUSTOM ? | ||
208 | + OAuth2CustomMapperConfig.builder() | ||
209 | + .url(url) | ||
210 | + .username(username) | ||
211 | + .password(password) | ||
212 | + .sendToken(sendToken) | ||
213 | + .build() | ||
214 | + : null | ||
215 | + ) | ||
216 | + .build() | ||
217 | + ); | ||
218 | + clientRegistrationInfo.setClientId(clientId); | ||
219 | + clientRegistrationInfo.setClientSecret(clientSecret); | ||
220 | + clientRegistrationInfo.setAuthorizationUri(authorizationUri); | ||
221 | + clientRegistrationInfo.setAccessTokenUri(tokenUri); | ||
222 | + clientRegistrationInfo.setScope(Arrays.asList(scope.split(","))); | ||
223 | + clientRegistrationInfo.setUserInfoUri(userInfoUri); | ||
224 | + clientRegistrationInfo.setUserNameAttributeName(userNameAttributeName); | ||
225 | + clientRegistrationInfo.setJwkSetUri(jwkSetUri); | ||
226 | + clientRegistrationInfo.setClientAuthenticationMethod(clientAuthenticationMethod); | ||
227 | + clientRegistrationInfo.setLoginButtonLabel(loginButtonLabel); | ||
228 | + clientRegistrationInfo.setLoginButtonIcon(loginButtonIcon); | ||
229 | + return clientRegistrationInfo; | ||
230 | + } | ||
231 | +} |
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.dao.model.sql; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo; | ||
21 | +import org.thingsboard.server.common.data.oauth2.SchemeType; | ||
22 | + | ||
23 | +@Data | ||
24 | +@EqualsAndHashCode(callSuper = true) | ||
25 | +public class ExtendedOAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<ExtendedOAuth2ClientRegistrationInfo> { | ||
26 | + | ||
27 | + private String domainName; | ||
28 | + private SchemeType domainScheme; | ||
29 | + | ||
30 | + public ExtendedOAuth2ClientRegistrationInfoEntity() { | ||
31 | + super(); | ||
32 | + } | ||
33 | + | ||
34 | + public ExtendedOAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity, | ||
35 | + String domainName, | ||
36 | + SchemeType domainScheme) { | ||
37 | + super(oAuth2ClientRegistrationInfoEntity); | ||
38 | + this.domainName = domainName; | ||
39 | + this.domainScheme = domainScheme; | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + public ExtendedOAuth2ClientRegistrationInfo toData() { | ||
44 | + return new ExtendedOAuth2ClientRegistrationInfo(super.toOAuth2ClientRegistrationInfo(), | ||
45 | + domainScheme, | ||
46 | + domainName); | ||
47 | + } | ||
48 | +} |
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.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.dao.model.sql; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import org.hibernate.annotations.TypeDef; | ||
21 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId; | ||
22 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
23 | +import org.thingsboard.server.common.data.oauth2.*; | ||
24 | +import org.thingsboard.server.dao.model.BaseSqlEntity; | ||
25 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
26 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | ||
27 | + | ||
28 | +import javax.persistence.*; | ||
29 | +import java.util.Arrays; | ||
30 | +import java.util.UUID; | ||
31 | + | ||
32 | +@Data | ||
33 | +@EqualsAndHashCode(callSuper = true) | ||
34 | +@Entity | ||
35 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | ||
36 | +@Table(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME) | ||
37 | +public class OAuth2ClientRegistrationEntity extends BaseSqlEntity<OAuth2ClientRegistration> { | ||
38 | + | ||
39 | + @Column(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_INFO_ID_PROPERTY, columnDefinition = "uuid") | ||
40 | + private UUID clientRegistrationInfoId; | ||
41 | + | ||
42 | + @Column(name = ModelConstants.OAUTH2_DOMAIN_NAME_PROPERTY) | ||
43 | + private String domainName; | ||
44 | + | ||
45 | + @Enumerated(EnumType.STRING) | ||
46 | + @Column(name = ModelConstants.OAUTH2_DOMAIN_SCHEME_PROPERTY) | ||
47 | + private SchemeType domainScheme; | ||
48 | + | ||
49 | + public OAuth2ClientRegistrationEntity() { | ||
50 | + super(); | ||
51 | + } | ||
52 | + | ||
53 | + public OAuth2ClientRegistrationEntity(OAuth2ClientRegistration clientRegistration) { | ||
54 | + if (clientRegistration.getId() != null) { | ||
55 | + this.setUuid(clientRegistration.getId().getId()); | ||
56 | + } | ||
57 | + if (clientRegistration.getClientRegistrationId() != null){ | ||
58 | + this.clientRegistrationInfoId = clientRegistration.getClientRegistrationId().getId(); | ||
59 | + } | ||
60 | + this.createdTime = clientRegistration.getCreatedTime(); | ||
61 | + this.domainName = clientRegistration.getDomainName(); | ||
62 | + this.domainScheme = clientRegistration.getDomainScheme(); | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public OAuth2ClientRegistration toData() { | ||
67 | + OAuth2ClientRegistration clientRegistration = new OAuth2ClientRegistration(); | ||
68 | + clientRegistration.setId(new OAuth2ClientRegistrationId(id)); | ||
69 | + clientRegistration.setClientRegistrationId(new OAuth2ClientRegistrationInfoId(clientRegistrationInfoId)); | ||
70 | + clientRegistration.setCreatedTime(createdTime); | ||
71 | + clientRegistration.setDomainName(domainName); | ||
72 | + clientRegistration.setDomainScheme(domainScheme); | ||
73 | + return clientRegistration; | ||
74 | + } | ||
75 | +} |
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.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.dao.model.sql; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.EqualsAndHashCode; | ||
20 | +import org.hibernate.annotations.TypeDef; | ||
21 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; | ||
22 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
23 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | ||
24 | + | ||
25 | +import javax.persistence.Entity; | ||
26 | +import javax.persistence.Table; | ||
27 | + | ||
28 | +@Data | ||
29 | +@EqualsAndHashCode(callSuper = true) | ||
30 | +@Entity | ||
31 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | ||
32 | +@Table(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME) | ||
33 | +public class OAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<OAuth2ClientRegistrationInfo> { | ||
34 | + | ||
35 | + public OAuth2ClientRegistrationInfoEntity() { | ||
36 | + super(); | ||
37 | + } | ||
38 | + | ||
39 | + public OAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfo clientRegistration) { | ||
40 | + super(clientRegistration); | ||
41 | + } | ||
42 | + | ||
43 | + public OAuth2ClientRegistrationInfoEntity(OAuth2ClientRegistrationInfoEntity oAuth2ClientRegistrationInfoEntity) { | ||
44 | + super(oAuth2ClientRegistrationInfoEntity); | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public OAuth2ClientRegistrationInfo toData() { | ||
49 | + return super.toOAuth2ClientRegistrationInfo(); | ||
50 | + } | ||
51 | +} |
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationTemplateEntity.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.dao.model.sql; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.EqualsAndHashCode; | ||
21 | +import org.hibernate.annotations.Type; | ||
22 | +import org.hibernate.annotations.TypeDef; | ||
23 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.common.data.oauth2.*; | ||
26 | +import org.thingsboard.server.dao.model.BaseSqlEntity; | ||
27 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
28 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | ||
29 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
30 | + | ||
31 | +import javax.persistence.*; | ||
32 | +import java.util.Arrays; | ||
33 | +import java.util.UUID; | ||
34 | + | ||
35 | +@Data | ||
36 | +@EqualsAndHashCode(callSuper = true) | ||
37 | +@Entity | ||
38 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | ||
39 | +@Table(name = ModelConstants.OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME) | ||
40 | +public class OAuth2ClientRegistrationTemplateEntity extends BaseSqlEntity<OAuth2ClientRegistrationTemplate> { | ||
41 | + | ||
42 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY) | ||
43 | + private String providerId; | ||
44 | + @Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY) | ||
45 | + private String authorizationUri; | ||
46 | + @Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY) | ||
47 | + private String tokenUri; | ||
48 | + @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY) | ||
49 | + private String scope; | ||
50 | + @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY) | ||
51 | + private String userInfoUri; | ||
52 | + @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY) | ||
53 | + private String userNameAttributeName; | ||
54 | + @Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY) | ||
55 | + private String jwkSetUri; | ||
56 | + @Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY) | ||
57 | + private String clientAuthenticationMethod; | ||
58 | + @Enumerated(EnumType.STRING) | ||
59 | + @Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY) | ||
60 | + private MapperType type; | ||
61 | + @Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY) | ||
62 | + private String emailAttributeKey; | ||
63 | + @Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY) | ||
64 | + private String firstNameAttributeKey; | ||
65 | + @Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY) | ||
66 | + private String lastNameAttributeKey; | ||
67 | + @Enumerated(EnumType.STRING) | ||
68 | + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY) | ||
69 | + private TenantNameStrategyType tenantNameStrategy; | ||
70 | + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY) | ||
71 | + private String tenantNamePattern; | ||
72 | + @Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY) | ||
73 | + private String customerNamePattern; | ||
74 | + @Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY) | ||
75 | + private String defaultDashboardName; | ||
76 | + @Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY) | ||
77 | + private Boolean alwaysFullScreen; | ||
78 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_COMMENT_PROPERTY) | ||
79 | + private String comment; | ||
80 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_LOGIN_BUTTON_ICON_PROPERTY) | ||
81 | + private String loginButtonIcon; | ||
82 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_LOGIN_BUTTON_LABEL_PROPERTY) | ||
83 | + private String loginButtonLabel; | ||
84 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_HELP_LINK_PROPERTY) | ||
85 | + private String helpLink; | ||
86 | + | ||
87 | + @Type(type = "json") | ||
88 | + @Column(name = ModelConstants.OAUTH2_TEMPLATE_ADDITIONAL_INFO_PROPERTY) | ||
89 | + private JsonNode additionalInfo; | ||
90 | + | ||
91 | + public OAuth2ClientRegistrationTemplateEntity() { | ||
92 | + } | ||
93 | + | ||
94 | + public OAuth2ClientRegistrationTemplateEntity(OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
95 | + if (clientRegistrationTemplate.getId() != null) { | ||
96 | + this.setUuid(clientRegistrationTemplate.getId().getId()); | ||
97 | + } | ||
98 | + this.createdTime = clientRegistrationTemplate.getCreatedTime(); | ||
99 | + this.providerId = clientRegistrationTemplate.getProviderId(); | ||
100 | + this.authorizationUri = clientRegistrationTemplate.getAuthorizationUri(); | ||
101 | + this.tokenUri = clientRegistrationTemplate.getAccessTokenUri(); | ||
102 | + this.scope = clientRegistrationTemplate.getScope().stream().reduce((result, element) -> result + "," + element).orElse(""); | ||
103 | + this.userInfoUri = clientRegistrationTemplate.getUserInfoUri(); | ||
104 | + this.userNameAttributeName = clientRegistrationTemplate.getUserNameAttributeName(); | ||
105 | + this.jwkSetUri = clientRegistrationTemplate.getJwkSetUri(); | ||
106 | + this.clientAuthenticationMethod = clientRegistrationTemplate.getClientAuthenticationMethod(); | ||
107 | + this.comment = clientRegistrationTemplate.getComment(); | ||
108 | + this.loginButtonIcon = clientRegistrationTemplate.getLoginButtonIcon(); | ||
109 | + this.loginButtonLabel = clientRegistrationTemplate.getLoginButtonLabel(); | ||
110 | + this.helpLink = clientRegistrationTemplate.getHelpLink(); | ||
111 | + this.additionalInfo = clientRegistrationTemplate.getAdditionalInfo(); | ||
112 | + this.type = clientRegistrationTemplate.getMapperType(); | ||
113 | + OAuth2BasicMapperConfig basicConfig = clientRegistrationTemplate.getBasic(); | ||
114 | + if (basicConfig != null) { | ||
115 | + this.emailAttributeKey = basicConfig.getEmailAttributeKey(); | ||
116 | + this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey(); | ||
117 | + this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey(); | ||
118 | + this.tenantNameStrategy = basicConfig.getTenantNameStrategy(); | ||
119 | + this.tenantNamePattern = basicConfig.getTenantNamePattern(); | ||
120 | + this.customerNamePattern = basicConfig.getCustomerNamePattern(); | ||
121 | + this.defaultDashboardName = basicConfig.getDefaultDashboardName(); | ||
122 | + this.alwaysFullScreen = basicConfig.isAlwaysFullScreen(); | ||
123 | + } | ||
124 | + } | ||
125 | + | ||
126 | + @Override | ||
127 | + public OAuth2ClientRegistrationTemplate toData() { | ||
128 | + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = new OAuth2ClientRegistrationTemplate(); | ||
129 | + clientRegistrationTemplate.setId(new OAuth2ClientRegistrationTemplateId(id)); | ||
130 | + clientRegistrationTemplate.setCreatedTime(createdTime); | ||
131 | + clientRegistrationTemplate.setAdditionalInfo(additionalInfo); | ||
132 | + | ||
133 | + clientRegistrationTemplate.setMapperType(type); | ||
134 | + clientRegistrationTemplate.setProviderId(providerId); | ||
135 | + clientRegistrationTemplate.setBasic( | ||
136 | + OAuth2BasicMapperConfig.builder() | ||
137 | + .emailAttributeKey(emailAttributeKey) | ||
138 | + .firstNameAttributeKey(firstNameAttributeKey) | ||
139 | + .lastNameAttributeKey(lastNameAttributeKey) | ||
140 | + .tenantNameStrategy(tenantNameStrategy) | ||
141 | + .tenantNamePattern(tenantNamePattern) | ||
142 | + .customerNamePattern(customerNamePattern) | ||
143 | + .defaultDashboardName(defaultDashboardName) | ||
144 | + .alwaysFullScreen(alwaysFullScreen) | ||
145 | + .build() | ||
146 | + ); | ||
147 | + clientRegistrationTemplate.setAuthorizationUri(authorizationUri); | ||
148 | + clientRegistrationTemplate.setAccessTokenUri(tokenUri); | ||
149 | + clientRegistrationTemplate.setScope(Arrays.asList(scope.split(","))); | ||
150 | + clientRegistrationTemplate.setUserInfoUri(userInfoUri); | ||
151 | + clientRegistrationTemplate.setUserNameAttributeName(userNameAttributeName); | ||
152 | + clientRegistrationTemplate.setJwkSetUri(jwkSetUri); | ||
153 | + clientRegistrationTemplate.setClientAuthenticationMethod(clientAuthenticationMethod); | ||
154 | + clientRegistrationTemplate.setComment(comment); | ||
155 | + clientRegistrationTemplate.setLoginButtonIcon(loginButtonIcon); | ||
156 | + clientRegistrationTemplate.setLoginButtonLabel(loginButtonLabel); | ||
157 | + clientRegistrationTemplate.setHelpLink(helpLink); | ||
158 | + return clientRegistrationTemplate; | ||
159 | + } | ||
160 | +} |
dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.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.dao.oauth2; | ||
17 | + | ||
18 | +import org.springframework.beans.factory.annotation.Autowired; | ||
19 | +import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||
20 | +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||
21 | +import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||
22 | +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||
23 | +import org.springframework.stereotype.Component; | ||
24 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; | ||
25 | + | ||
26 | +import java.util.UUID; | ||
27 | + | ||
28 | +@Component | ||
29 | +public class HybridClientRegistrationRepository implements ClientRegistrationRepository { | ||
30 | + private static final String defaultRedirectUriTemplate = "{baseUrl}/login/oauth2/code/{registrationId}"; | ||
31 | + | ||
32 | + @Autowired | ||
33 | + private OAuth2Service oAuth2Service; | ||
34 | + | ||
35 | + @Override | ||
36 | + public ClientRegistration findByRegistrationId(String registrationId) { | ||
37 | + OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(UUID.fromString(registrationId)); | ||
38 | + return oAuth2ClientRegistrationInfo == null ? | ||
39 | + null : toSpringClientRegistration(oAuth2ClientRegistrationInfo); | ||
40 | + } | ||
41 | + | ||
42 | + private ClientRegistration toSpringClientRegistration(OAuth2ClientRegistrationInfo localClientRegistration){ | ||
43 | + String registrationId = localClientRegistration.getUuidId().toString(); | ||
44 | + return ClientRegistration.withRegistrationId(registrationId) | ||
45 | + .clientName(localClientRegistration.getName()) | ||
46 | + .clientId(localClientRegistration.getClientId()) | ||
47 | + .authorizationUri(localClientRegistration.getAuthorizationUri()) | ||
48 | + .clientSecret(localClientRegistration.getClientSecret()) | ||
49 | + .tokenUri(localClientRegistration.getAccessTokenUri()) | ||
50 | + .scope(localClientRegistration.getScope()) | ||
51 | + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) | ||
52 | + .userInfoUri(localClientRegistration.getUserInfoUri()) | ||
53 | + .userNameAttributeName(localClientRegistration.getUserNameAttributeName()) | ||
54 | + .jwkSetUri(localClientRegistration.getJwkSetUri()) | ||
55 | + .clientAuthenticationMethod(new ClientAuthenticationMethod(localClientRegistration.getClientAuthenticationMethod())) | ||
56 | + .redirectUriTemplate(defaultRedirectUriTemplate) | ||
57 | + .build(); | ||
58 | + } | ||
59 | +} |
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.dao.oauth2; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration; | ||
19 | +import org.thingsboard.server.dao.Dao; | ||
20 | + | ||
21 | +public interface OAuth2ClientRegistrationDao extends Dao<OAuth2ClientRegistration> { | ||
22 | + void deleteAll(); | ||
23 | +} |
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.dao.oauth2; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo; | ||
19 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; | ||
20 | +import org.thingsboard.server.common.data.oauth2.SchemeType; | ||
21 | +import org.thingsboard.server.dao.Dao; | ||
22 | + | ||
23 | +import java.util.List; | ||
24 | +import java.util.Set; | ||
25 | + | ||
26 | +public interface OAuth2ClientRegistrationInfoDao extends Dao<OAuth2ClientRegistrationInfo> { | ||
27 | + List<OAuth2ClientRegistrationInfo> findAll(); | ||
28 | + | ||
29 | + List<ExtendedOAuth2ClientRegistrationInfo> findAllExtended(); | ||
30 | + | ||
31 | + List<OAuth2ClientRegistrationInfo> findByDomainSchemesAndDomainName(List<SchemeType> domainSchemes, String domainName); | ||
32 | + | ||
33 | + void deleteAll(); | ||
34 | +} |
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationTemplateDao.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.dao.oauth2; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
19 | +import org.thingsboard.server.dao.Dao; | ||
20 | + | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +public interface OAuth2ClientRegistrationTemplateDao extends Dao<OAuth2ClientRegistrationTemplate> { | ||
24 | + List<OAuth2ClientRegistrationTemplate> findAll(); | ||
25 | +} |
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.dao.oauth2; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.hibernate.exception.ConstraintViolationException; | ||
20 | +import org.springframework.beans.factory.annotation.Autowired; | ||
21 | +import org.springframework.stereotype.Service; | ||
22 | +import org.springframework.util.StringUtils; | ||
23 | +import org.thingsboard.server.common.data.Tenant; | ||
24 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; | ||
25 | +import org.thingsboard.server.common.data.id.TenantId; | ||
26 | +import org.thingsboard.server.common.data.oauth2.*; | ||
27 | +import org.thingsboard.server.dao.entity.AbstractEntityService; | ||
28 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
29 | +import org.thingsboard.server.dao.service.DataValidator; | ||
30 | + | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +import static org.thingsboard.server.dao.service.Validator.validateId; | ||
34 | +import static org.thingsboard.server.dao.service.Validator.validateString; | ||
35 | + | ||
36 | +@Slf4j | ||
37 | +@Service | ||
38 | +public class OAuth2ConfigTemplateServiceImpl extends AbstractEntityService implements OAuth2ConfigTemplateService { | ||
39 | + public static final String INCORRECT_CLIENT_REGISTRATION_TEMPLATE_ID = "Incorrect clientRegistrationTemplateId "; | ||
40 | + | ||
41 | + @Autowired | ||
42 | + private OAuth2ClientRegistrationTemplateDao clientRegistrationTemplateDao; | ||
43 | + | ||
44 | + @Override | ||
45 | + public OAuth2ClientRegistrationTemplate saveClientRegistrationTemplate(OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
46 | + log.trace("Executing saveClientRegistrationTemplate [{}]", clientRegistrationTemplate); | ||
47 | + clientRegistrationTemplateValidator.validate(clientRegistrationTemplate, o -> TenantId.SYS_TENANT_ID); | ||
48 | + OAuth2ClientRegistrationTemplate savedClientRegistrationTemplate; | ||
49 | + try { | ||
50 | + savedClientRegistrationTemplate = clientRegistrationTemplateDao.save(TenantId.SYS_TENANT_ID, clientRegistrationTemplate); | ||
51 | + } catch (Exception t) { | ||
52 | + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); | ||
53 | + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("oauth2_template_provider_id_unq_key")) { | ||
54 | + throw new DataValidationException("Client registration template with such providerId already exists!"); | ||
55 | + } else { | ||
56 | + throw t; | ||
57 | + } | ||
58 | + } | ||
59 | + return savedClientRegistrationTemplate; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public OAuth2ClientRegistrationTemplate findClientRegistrationTemplateById(OAuth2ClientRegistrationTemplateId templateId) { | ||
64 | + log.trace("Executing findClientRegistrationTemplateById [{}]", templateId); | ||
65 | + validateId(templateId, INCORRECT_CLIENT_REGISTRATION_TEMPLATE_ID + templateId); | ||
66 | + return clientRegistrationTemplateDao.findById(TenantId.SYS_TENANT_ID, templateId.getId()); | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public List<OAuth2ClientRegistrationTemplate> findAllClientRegistrationTemplates() { | ||
71 | + log.trace("Executing findAllClientRegistrationTemplates"); | ||
72 | + return clientRegistrationTemplateDao.findAll(); | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public void deleteClientRegistrationTemplateById(OAuth2ClientRegistrationTemplateId templateId) { | ||
77 | + log.trace("Executing deleteClientRegistrationTemplateById [{}]", templateId); | ||
78 | + validateId(templateId, INCORRECT_CLIENT_REGISTRATION_TEMPLATE_ID + templateId); | ||
79 | + clientRegistrationTemplateDao.removeById(TenantId.SYS_TENANT_ID, templateId.getId()); | ||
80 | + } | ||
81 | + | ||
82 | + private final DataValidator<OAuth2ClientRegistrationTemplate> clientRegistrationTemplateValidator = | ||
83 | + new DataValidator<OAuth2ClientRegistrationTemplate>() { | ||
84 | + | ||
85 | + @Override | ||
86 | + protected void validateCreate(TenantId tenantId, OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
87 | + } | ||
88 | + | ||
89 | + @Override | ||
90 | + protected void validateUpdate(TenantId tenantId, OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + protected void validateDataImpl(TenantId tenantId, OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { | ||
95 | + if (StringUtils.isEmpty(clientRegistrationTemplate.getProviderId())) { | ||
96 | + throw new DataValidationException("Provider ID should be specified!"); | ||
97 | + } | ||
98 | + if (clientRegistrationTemplate.getBasic() == null) { | ||
99 | + throw new DataValidationException("Basic mapper config should be specified!"); | ||
100 | + } | ||
101 | + } | ||
102 | + }; | ||
103 | +} |
@@ -17,66 +17,15 @@ package org.thingsboard.server.dao.oauth2; | @@ -17,66 +17,15 @@ package org.thingsboard.server.dao.oauth2; | ||
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
21 | import org.springframework.boot.context.properties.ConfigurationProperties; | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; |
22 | -import org.springframework.context.annotation.Bean; | ||
23 | import org.springframework.context.annotation.Configuration; | 21 | import org.springframework.context.annotation.Configuration; |
24 | -import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||
25 | -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||
26 | -import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; | ||
27 | -import org.springframework.security.oauth2.core.AuthorizationGrantType; | ||
28 | -import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | ||
29 | 22 | ||
30 | -import java.util.ArrayList; | ||
31 | -import java.util.HashMap; | ||
32 | -import java.util.List; | ||
33 | import java.util.Map; | 23 | import java.util.Map; |
34 | 24 | ||
35 | @Configuration | 25 | @Configuration |
36 | -@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") | ||
37 | @ConfigurationProperties(prefix = "security.oauth2") | 26 | @ConfigurationProperties(prefix = "security.oauth2") |
38 | @Data | 27 | @Data |
39 | -@Slf4j | ||
40 | public class OAuth2Configuration { | 28 | public class OAuth2Configuration { |
41 | - | ||
42 | - private boolean enabled; | ||
43 | private String loginProcessingUrl; | 29 | private String loginProcessingUrl; |
44 | - private Map<String, OAuth2Client> clients = new HashMap<>(); | ||
45 | - | ||
46 | - @Bean | ||
47 | - public ClientRegistrationRepository clientRegistrationRepository() { | ||
48 | - List<ClientRegistration> result = new ArrayList<>(); | ||
49 | - for (Map.Entry<String, OAuth2Client> entry : clients.entrySet()) { | ||
50 | - OAuth2Client client = entry.getValue(); | ||
51 | - ClientRegistration registration = ClientRegistration.withRegistrationId(entry.getKey()) | ||
52 | - .clientId(client.getClientId()) | ||
53 | - .authorizationUri(client.getAuthorizationUri()) | ||
54 | - .clientSecret(client.getClientSecret()) | ||
55 | - .tokenUri(client.getAccessTokenUri()) | ||
56 | - .redirectUriTemplate(client.getRedirectUriTemplate()) | ||
57 | - .scope(client.getScope().split(",")) | ||
58 | - .clientName(client.getClientName()) | ||
59 | - .authorizationGrantType(new AuthorizationGrantType(client.getAuthorizationGrantType())) | ||
60 | - .userInfoUri(client.getUserInfoUri()) | ||
61 | - .userNameAttributeName(client.getUserNameAttributeName()) | ||
62 | - .jwkSetUri(client.getJwkSetUri()) | ||
63 | - .clientAuthenticationMethod(new ClientAuthenticationMethod(client.getClientAuthenticationMethod())) | ||
64 | - .build(); | ||
65 | - result.add(registration); | ||
66 | - } | ||
67 | - return new InMemoryClientRegistrationRepository(result); | ||
68 | - } | ||
69 | - | ||
70 | - public OAuth2Client getClientByRegistrationId(String registrationId) { | ||
71 | - OAuth2Client result = null; | ||
72 | - if (clients != null && !clients.isEmpty()) { | ||
73 | - for (String key : clients.keySet()) { | ||
74 | - if (key.equals(registrationId)) { | ||
75 | - result = clients.get(key); | ||
76 | - break; | ||
77 | - } | ||
78 | - } | ||
79 | - } | ||
80 | - return result; | ||
81 | - } | 30 | + private Map<String, String> githubMapper; |
82 | } | 31 | } |
@@ -18,33 +18,198 @@ package org.thingsboard.server.dao.oauth2; | @@ -18,33 +18,198 @@ package org.thingsboard.server.dao.oauth2; | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
21 | -import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; | 21 | +import org.springframework.util.StringUtils; |
22 | +import org.thingsboard.server.common.data.id.TenantId; | ||
23 | +import org.thingsboard.server.common.data.oauth2.*; | ||
24 | +import org.thingsboard.server.dao.entity.AbstractEntityService; | ||
25 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
26 | +import org.thingsboard.server.dao.exception.IncorrectParameterException; | ||
22 | 27 | ||
23 | -import java.util.ArrayList; | ||
24 | -import java.util.Collections; | ||
25 | -import java.util.List; | ||
26 | -import java.util.Map; | 28 | +import javax.transaction.Transactional; |
29 | +import java.util.*; | ||
30 | +import java.util.function.Consumer; | ||
31 | +import java.util.stream.Collectors; | ||
32 | + | ||
33 | +import static org.thingsboard.server.dao.service.Validator.validateId; | ||
34 | +import static org.thingsboard.server.dao.service.Validator.validateString; | ||
27 | 35 | ||
28 | @Slf4j | 36 | @Slf4j |
29 | @Service | 37 | @Service |
30 | -public class OAuth2ServiceImpl implements OAuth2Service { | 38 | +public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Service { |
39 | + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | ||
40 | + public static final String INCORRECT_CLIENT_REGISTRATION_ID = "Incorrect clientRegistrationId "; | ||
41 | + public static final String INCORRECT_DOMAIN_NAME = "Incorrect domainName "; | ||
42 | + public static final String INCORRECT_DOMAIN_SCHEME = "Incorrect domainScheme "; | ||
31 | 43 | ||
32 | - @Autowired(required = false) | ||
33 | - OAuth2Configuration oauth2Configuration; | 44 | + @Autowired |
45 | + private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao; | ||
46 | + @Autowired | ||
47 | + private OAuth2ClientRegistrationDao clientRegistrationDao; | ||
34 | 48 | ||
35 | @Override | 49 | @Override |
36 | - public List<OAuth2ClientInfo> getOAuth2Clients() { | ||
37 | - if (oauth2Configuration == null || !oauth2Configuration.isEnabled()) { | ||
38 | - return Collections.emptyList(); | 50 | + public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName) { |
51 | + log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName); | ||
52 | + if (domainSchemeStr == null) { | ||
53 | + throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); | ||
39 | } | 54 | } |
40 | - List<OAuth2ClientInfo> result = new ArrayList<>(); | ||
41 | - for (Map.Entry<String, OAuth2Client> entry : oauth2Configuration.getClients().entrySet()) { | ||
42 | - OAuth2ClientInfo client = new OAuth2ClientInfo(); | ||
43 | - client.setName(entry.getValue().getLoginButtonLabel()); | ||
44 | - client.setUrl(String.format("/oauth2/authorization/%s", entry.getKey())); | ||
45 | - client.setIcon(entry.getValue().getLoginButtonIcon()); | ||
46 | - result.add(client); | 55 | + SchemeType domainScheme; |
56 | + try { | ||
57 | + domainScheme = SchemeType.valueOf(domainSchemeStr.toUpperCase()); | ||
58 | + } catch (IllegalArgumentException e){ | ||
59 | + throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); | ||
47 | } | 60 | } |
48 | - return result; | 61 | + validateString(domainName, INCORRECT_DOMAIN_NAME + domainName); |
62 | + return clientRegistrationInfoDao.findByDomainSchemesAndDomainName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName).stream() | ||
63 | + .filter(OAuth2ClientRegistrationInfo::isEnabled) | ||
64 | + .map(OAuth2Utils::toClientInfo) | ||
65 | + .collect(Collectors.toList()); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + @Transactional | ||
70 | + public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) { | ||
71 | + log.trace("Executing saveOAuth2Params [{}]", oauth2Params); | ||
72 | + clientParamsValidator.accept(oauth2Params); | ||
73 | + clientRegistrationDao.deleteAll(); | ||
74 | + clientRegistrationInfoDao.deleteAll(); | ||
75 | + oauth2Params.getDomainsParams().forEach(domainParams -> { | ||
76 | + domainParams.getClientRegistrations().forEach(clientRegistrationDto -> { | ||
77 | + OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = OAuth2Utils.toClientRegistrationInfo(oauth2Params.isEnabled(), clientRegistrationDto); | ||
78 | + OAuth2ClientRegistrationInfo savedClientRegistrationInfo = clientRegistrationInfoDao.save(TenantId.SYS_TENANT_ID, oAuth2ClientRegistrationInfo); | ||
79 | + domainParams.getDomainInfos().forEach(domainInfo -> { | ||
80 | + OAuth2ClientRegistration oAuth2ClientRegistration = OAuth2Utils.toClientRegistration(savedClientRegistrationInfo.getId(), | ||
81 | + domainInfo.getScheme(), domainInfo.getName()); | ||
82 | + clientRegistrationDao.save(TenantId.SYS_TENANT_ID, oAuth2ClientRegistration); | ||
83 | + }); | ||
84 | + }); | ||
85 | + }); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public OAuth2ClientsParams findOAuth2Params() { | ||
90 | + log.trace("Executing findOAuth2Params"); | ||
91 | + List<ExtendedOAuth2ClientRegistrationInfo> extendedInfos = clientRegistrationInfoDao.findAllExtended(); | ||
92 | + return OAuth2Utils.toOAuth2Params(extendedInfos); | ||
93 | + } | ||
94 | + | ||
95 | + @Override | ||
96 | + public OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id) { | ||
97 | + log.trace("Executing findClientRegistrationInfo [{}]", id); | ||
98 | + validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id); | ||
99 | + return clientRegistrationInfoDao.findById(null, id); | ||
100 | + } | ||
101 | + | ||
102 | + @Override | ||
103 | + public List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos() { | ||
104 | + log.trace("Executing findAllClientRegistrationInfos"); | ||
105 | + return clientRegistrationInfoDao.findAll(); | ||
49 | } | 106 | } |
107 | + | ||
108 | + private final Consumer<OAuth2ClientsParams> clientParamsValidator = oauth2Params -> { | ||
109 | + if (oauth2Params == null | ||
110 | + || oauth2Params.getDomainsParams() == null) { | ||
111 | + throw new DataValidationException("Domain params should be specified!"); | ||
112 | + } | ||
113 | + for (OAuth2ClientsDomainParams domainParams : oauth2Params.getDomainsParams()) { | ||
114 | + if (domainParams.getDomainInfos() == null | ||
115 | + || domainParams.getDomainInfos().isEmpty()) { | ||
116 | + throw new DataValidationException("List of domain configuration should be specified!"); | ||
117 | + } | ||
118 | + for (DomainInfo domainInfo : domainParams.getDomainInfos()) { | ||
119 | + if (StringUtils.isEmpty(domainInfo.getName())) { | ||
120 | + throw new DataValidationException("Domain name should be specified!"); | ||
121 | + } | ||
122 | + if (domainInfo.getScheme() == null) { | ||
123 | + throw new DataValidationException("Domain scheme should be specified!"); | ||
124 | + } | ||
125 | + } | ||
126 | + domainParams.getDomainInfos().stream() | ||
127 | + .collect(Collectors.groupingBy(DomainInfo::getName)) | ||
128 | + .forEach((domainName, domainInfos) -> { | ||
129 | + if (domainInfos.size() > 1 && domainInfos.stream().anyMatch(domainInfo -> domainInfo.getScheme() == SchemeType.MIXED)) { | ||
130 | + throw new DataValidationException("MIXED scheme type shouldn't be combined with another scheme type!"); | ||
131 | + } | ||
132 | + }); | ||
133 | + if (domainParams.getClientRegistrations() == null || domainParams.getClientRegistrations().isEmpty()) { | ||
134 | + throw new DataValidationException("Client registrations should be specified!"); | ||
135 | + } | ||
136 | + for (ClientRegistrationDto clientRegistration : domainParams.getClientRegistrations()) { | ||
137 | + if (StringUtils.isEmpty(clientRegistration.getClientId())) { | ||
138 | + throw new DataValidationException("Client ID should be specified!"); | ||
139 | + } | ||
140 | + if (StringUtils.isEmpty(clientRegistration.getClientSecret())) { | ||
141 | + throw new DataValidationException("Client secret should be specified!"); | ||
142 | + } | ||
143 | + if (StringUtils.isEmpty(clientRegistration.getAuthorizationUri())) { | ||
144 | + throw new DataValidationException("Authorization uri should be specified!"); | ||
145 | + } | ||
146 | + if (StringUtils.isEmpty(clientRegistration.getAccessTokenUri())) { | ||
147 | + throw new DataValidationException("Token uri should be specified!"); | ||
148 | + } | ||
149 | + if (StringUtils.isEmpty(clientRegistration.getScope())) { | ||
150 | + throw new DataValidationException("Scope should be specified!"); | ||
151 | + } | ||
152 | + if (StringUtils.isEmpty(clientRegistration.getUserInfoUri())) { | ||
153 | + throw new DataValidationException("User info uri should be specified!"); | ||
154 | + } | ||
155 | + if (StringUtils.isEmpty(clientRegistration.getUserNameAttributeName())) { | ||
156 | + throw new DataValidationException("User name attribute name should be specified!"); | ||
157 | + } | ||
158 | + if (StringUtils.isEmpty(clientRegistration.getClientAuthenticationMethod())) { | ||
159 | + throw new DataValidationException("Client authentication method should be specified!"); | ||
160 | + } | ||
161 | + if (StringUtils.isEmpty(clientRegistration.getLoginButtonLabel())) { | ||
162 | + throw new DataValidationException("Login button label should be specified!"); | ||
163 | + } | ||
164 | + OAuth2MapperConfig mapperConfig = clientRegistration.getMapperConfig(); | ||
165 | + if (mapperConfig == null) { | ||
166 | + throw new DataValidationException("Mapper config should be specified!"); | ||
167 | + } | ||
168 | + if (mapperConfig.getType() == null) { | ||
169 | + throw new DataValidationException("Mapper config type should be specified!"); | ||
170 | + } | ||
171 | + if (mapperConfig.getType() == MapperType.BASIC) { | ||
172 | + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic(); | ||
173 | + if (basicConfig == null) { | ||
174 | + throw new DataValidationException("Basic config should be specified!"); | ||
175 | + } | ||
176 | + if (StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) { | ||
177 | + throw new DataValidationException("Email attribute key should be specified!"); | ||
178 | + } | ||
179 | + if (basicConfig.getTenantNameStrategy() == null) { | ||
180 | + throw new DataValidationException("Tenant name strategy should be specified!"); | ||
181 | + } | ||
182 | + if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM | ||
183 | + && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) { | ||
184 | + throw new DataValidationException("Tenant name pattern should be specified!"); | ||
185 | + } | ||
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 | + } | ||
203 | + if (mapperConfig.getType() == MapperType.CUSTOM) { | ||
204 | + OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom(); | ||
205 | + if (customConfig == null) { | ||
206 | + throw new DataValidationException("Custom config should be specified!"); | ||
207 | + } | ||
208 | + if (StringUtils.isEmpty(customConfig.getUrl())) { | ||
209 | + throw new DataValidationException("Custom mapper URL should be specified!"); | ||
210 | + } | ||
211 | + } | ||
212 | + } | ||
213 | + } | ||
214 | + }; | ||
50 | } | 215 | } |
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.dao.oauth2; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; | ||
19 | +import org.thingsboard.server.common.data.oauth2.*; | ||
20 | + | ||
21 | +import java.util.*; | ||
22 | + | ||
23 | +public class OAuth2Utils { | ||
24 | + public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s"; | ||
25 | + | ||
26 | + public static OAuth2ClientInfo toClientInfo(OAuth2ClientRegistrationInfo clientRegistrationInfo) { | ||
27 | + OAuth2ClientInfo client = new OAuth2ClientInfo(); | ||
28 | + client.setName(clientRegistrationInfo.getLoginButtonLabel()); | ||
29 | + client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, clientRegistrationInfo.getUuidId().toString())); | ||
30 | + client.setIcon(clientRegistrationInfo.getLoginButtonIcon()); | ||
31 | + return client; | ||
32 | + } | ||
33 | + | ||
34 | + public static OAuth2ClientsParams toOAuth2Params(List<ExtendedOAuth2ClientRegistrationInfo> extendedOAuth2ClientRegistrationInfos) { | ||
35 | + Map<OAuth2ClientRegistrationInfoId, Set<DomainInfo>> domainsByInfoId = new HashMap<>(); | ||
36 | + Map<OAuth2ClientRegistrationInfoId, OAuth2ClientRegistrationInfo> infoById = new HashMap<>(); | ||
37 | + for (ExtendedOAuth2ClientRegistrationInfo extendedClientRegistrationInfo : extendedOAuth2ClientRegistrationInfos) { | ||
38 | + String domainName = extendedClientRegistrationInfo.getDomainName(); | ||
39 | + SchemeType domainScheme = extendedClientRegistrationInfo.getDomainScheme(); | ||
40 | + domainsByInfoId.computeIfAbsent(extendedClientRegistrationInfo.getId(), key -> new HashSet<>()) | ||
41 | + .add(new DomainInfo(domainScheme, domainName)); | ||
42 | + infoById.put(extendedClientRegistrationInfo.getId(), extendedClientRegistrationInfo); | ||
43 | + } | ||
44 | + Map<Set<DomainInfo>, OAuth2ClientsDomainParams> domainParamsMap = new HashMap<>(); | ||
45 | + domainsByInfoId.forEach((clientRegistrationInfoId, domainInfos) -> { | ||
46 | + domainParamsMap.computeIfAbsent(domainInfos, | ||
47 | + key -> new OAuth2ClientsDomainParams(key, new HashSet<>()) | ||
48 | + ) | ||
49 | + .getClientRegistrations() | ||
50 | + .add(toClientRegistrationDto(infoById.get(clientRegistrationInfoId))); | ||
51 | + }); | ||
52 | + boolean enabled = extendedOAuth2ClientRegistrationInfos.stream() | ||
53 | + .map(OAuth2ClientRegistrationInfo::isEnabled) | ||
54 | + .findFirst().orElse(false); | ||
55 | + return new OAuth2ClientsParams(enabled, new HashSet<>(domainParamsMap.values())); | ||
56 | + } | ||
57 | + | ||
58 | + public static ClientRegistrationDto toClientRegistrationDto(OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo) { | ||
59 | + return ClientRegistrationDto.builder() | ||
60 | + .mapperConfig(oAuth2ClientRegistrationInfo.getMapperConfig()) | ||
61 | + .clientId(oAuth2ClientRegistrationInfo.getClientId()) | ||
62 | + .clientSecret(oAuth2ClientRegistrationInfo.getClientSecret()) | ||
63 | + .authorizationUri(oAuth2ClientRegistrationInfo.getAuthorizationUri()) | ||
64 | + .accessTokenUri(oAuth2ClientRegistrationInfo.getAccessTokenUri()) | ||
65 | + .scope(oAuth2ClientRegistrationInfo.getScope()) | ||
66 | + .userInfoUri(oAuth2ClientRegistrationInfo.getUserInfoUri()) | ||
67 | + .userNameAttributeName(oAuth2ClientRegistrationInfo.getUserNameAttributeName()) | ||
68 | + .jwkSetUri(oAuth2ClientRegistrationInfo.getJwkSetUri()) | ||
69 | + .clientAuthenticationMethod(oAuth2ClientRegistrationInfo.getClientAuthenticationMethod()) | ||
70 | + .loginButtonLabel(oAuth2ClientRegistrationInfo.getLoginButtonLabel()) | ||
71 | + .loginButtonIcon(oAuth2ClientRegistrationInfo.getLoginButtonIcon()) | ||
72 | + .additionalInfo(oAuth2ClientRegistrationInfo.getAdditionalInfo()) | ||
73 | + .build(); | ||
74 | + } | ||
75 | + | ||
76 | + public static OAuth2ClientRegistrationInfo toClientRegistrationInfo(boolean enabled, ClientRegistrationDto clientRegistrationDto) { | ||
77 | + OAuth2ClientRegistrationInfo clientRegistrationInfo = new OAuth2ClientRegistrationInfo(); | ||
78 | + clientRegistrationInfo.setEnabled(enabled); | ||
79 | + clientRegistrationInfo.setMapperConfig(clientRegistrationDto.getMapperConfig()); | ||
80 | + clientRegistrationInfo.setClientId(clientRegistrationDto.getClientId()); | ||
81 | + clientRegistrationInfo.setClientSecret(clientRegistrationDto.getClientSecret()); | ||
82 | + clientRegistrationInfo.setAuthorizationUri(clientRegistrationDto.getAuthorizationUri()); | ||
83 | + clientRegistrationInfo.setAccessTokenUri(clientRegistrationDto.getAccessTokenUri()); | ||
84 | + clientRegistrationInfo.setScope(clientRegistrationDto.getScope()); | ||
85 | + clientRegistrationInfo.setUserInfoUri(clientRegistrationDto.getUserInfoUri()); | ||
86 | + clientRegistrationInfo.setUserNameAttributeName(clientRegistrationDto.getUserNameAttributeName()); | ||
87 | + clientRegistrationInfo.setJwkSetUri(clientRegistrationDto.getJwkSetUri()); | ||
88 | + clientRegistrationInfo.setClientAuthenticationMethod(clientRegistrationDto.getClientAuthenticationMethod()); | ||
89 | + clientRegistrationInfo.setLoginButtonLabel(clientRegistrationDto.getLoginButtonLabel()); | ||
90 | + clientRegistrationInfo.setLoginButtonIcon(clientRegistrationDto.getLoginButtonIcon()); | ||
91 | + clientRegistrationInfo.setAdditionalInfo(clientRegistrationDto.getAdditionalInfo()); | ||
92 | + return clientRegistrationInfo; | ||
93 | + } | ||
94 | + | ||
95 | + public static OAuth2ClientRegistration toClientRegistration(OAuth2ClientRegistrationInfoId clientRegistrationInfoId, SchemeType domainScheme, String domainName) { | ||
96 | + OAuth2ClientRegistration clientRegistration = new OAuth2ClientRegistration(); | ||
97 | + clientRegistration.setClientRegistrationId(clientRegistrationInfoId); | ||
98 | + clientRegistration.setDomainName(domainName); | ||
99 | + clientRegistration.setDomainScheme(domainScheme); | ||
100 | + return clientRegistration; | ||
101 | + } | ||
102 | +} |
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.springframework.data.repository.CrudRepository; | ||
21 | +import org.springframework.stereotype.Component; | ||
22 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration; | ||
23 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity; | ||
24 | +import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationDao; | ||
25 | +import org.thingsboard.server.dao.sql.JpaAbstractDao; | ||
26 | + | ||
27 | +import java.util.UUID; | ||
28 | + | ||
29 | +@Component | ||
30 | +@RequiredArgsConstructor | ||
31 | +public class JpaOAuth2ClientRegistrationDao extends JpaAbstractDao<OAuth2ClientRegistrationEntity, OAuth2ClientRegistration> implements OAuth2ClientRegistrationDao { | ||
32 | + private final OAuth2ClientRegistrationRepository repository; | ||
33 | + | ||
34 | + @Override | ||
35 | + protected Class<OAuth2ClientRegistrationEntity> getEntityClass() { | ||
36 | + return OAuth2ClientRegistrationEntity.class; | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + protected CrudRepository<OAuth2ClientRegistrationEntity, UUID> getCrudRepository() { | ||
41 | + return repository; | ||
42 | + } | ||
43 | + | ||
44 | + @Override | ||
45 | + public void deleteAll() { | ||
46 | + repository.deleteAll(); | ||
47 | + } | ||
48 | +} |
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.springframework.data.repository.CrudRepository; | ||
20 | +import org.springframework.stereotype.Component; | ||
21 | +import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo; | ||
22 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; | ||
23 | +import org.thingsboard.server.common.data.oauth2.SchemeType; | ||
24 | +import org.thingsboard.server.dao.DaoUtil; | ||
25 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity; | ||
26 | +import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationInfoDao; | ||
27 | +import org.thingsboard.server.dao.sql.JpaAbstractDao; | ||
28 | + | ||
29 | +import java.util.ArrayList; | ||
30 | +import java.util.List; | ||
31 | +import java.util.UUID; | ||
32 | +import java.util.stream.Collectors; | ||
33 | + | ||
34 | +@Component | ||
35 | +@RequiredArgsConstructor | ||
36 | +public class JpaOAuth2ClientRegistrationInfoDao extends JpaAbstractDao<OAuth2ClientRegistrationInfoEntity, OAuth2ClientRegistrationInfo> implements OAuth2ClientRegistrationInfoDao { | ||
37 | + private final OAuth2ClientRegistrationInfoRepository repository; | ||
38 | + | ||
39 | + @Override | ||
40 | + protected Class<OAuth2ClientRegistrationInfoEntity> getEntityClass() { | ||
41 | + return OAuth2ClientRegistrationInfoEntity.class; | ||
42 | + } | ||
43 | + | ||
44 | + @Override | ||
45 | + protected CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> getCrudRepository() { | ||
46 | + return repository; | ||
47 | + } | ||
48 | + | ||
49 | + @Override | ||
50 | + public List<OAuth2ClientRegistrationInfo> findAll() { | ||
51 | + Iterable<OAuth2ClientRegistrationInfoEntity> entities = repository.findAll(); | ||
52 | + List<OAuth2ClientRegistrationInfo> result = new ArrayList<>(); | ||
53 | + entities.forEach(entity -> { | ||
54 | + result.add(DaoUtil.getData(entity)); | ||
55 | + }); | ||
56 | + return result; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public List<ExtendedOAuth2ClientRegistrationInfo> findAllExtended() { | ||
61 | + return repository.findAllExtended().stream() | ||
62 | + .map(DaoUtil::getData) | ||
63 | + .collect(Collectors.toList()); | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + public List<OAuth2ClientRegistrationInfo> findByDomainSchemesAndDomainName(List<SchemeType> domainSchemes, String domainName) { | ||
68 | + List<OAuth2ClientRegistrationInfoEntity> entities = repository.findAllByDomainSchemesAndName(domainSchemes, domainName); | ||
69 | + return entities.stream().map(DaoUtil::getData).collect(Collectors.toList()); | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public void deleteAll() { | ||
74 | + repository.deleteAll(); | ||
75 | + } | ||
76 | +} |
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationTemplateDao.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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.springframework.data.repository.CrudRepository; | ||
20 | +import org.springframework.stereotype.Component; | ||
21 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
22 | +import org.thingsboard.server.dao.DaoUtil; | ||
23 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationTemplateEntity; | ||
24 | +import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationTemplateDao; | ||
25 | +import org.thingsboard.server.dao.sql.JpaAbstractDao; | ||
26 | + | ||
27 | +import java.util.ArrayList; | ||
28 | +import java.util.List; | ||
29 | +import java.util.UUID; | ||
30 | + | ||
31 | +@Component | ||
32 | +@RequiredArgsConstructor | ||
33 | +public class JpaOAuth2ClientRegistrationTemplateDao extends JpaAbstractDao<OAuth2ClientRegistrationTemplateEntity, OAuth2ClientRegistrationTemplate> implements OAuth2ClientRegistrationTemplateDao { | ||
34 | + private final OAuth2ClientRegistrationTemplateRepository repository; | ||
35 | + | ||
36 | + @Override | ||
37 | + protected Class<OAuth2ClientRegistrationTemplateEntity> getEntityClass() { | ||
38 | + return OAuth2ClientRegistrationTemplateEntity.class; | ||
39 | + } | ||
40 | + | ||
41 | + @Override | ||
42 | + protected CrudRepository<OAuth2ClientRegistrationTemplateEntity, UUID> getCrudRepository() { | ||
43 | + return repository; | ||
44 | + } | ||
45 | + | ||
46 | + @Override | ||
47 | + public List<OAuth2ClientRegistrationTemplate> findAll() { | ||
48 | + Iterable<OAuth2ClientRegistrationTemplateEntity> entities = repository.findAll(); | ||
49 | + List<OAuth2ClientRegistrationTemplate> result = new ArrayList<>(); | ||
50 | + entities.forEach(entity -> result.add(DaoUtil.getData(entity))); | ||
51 | + return result; | ||
52 | + } | ||
53 | +} |
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import org.springframework.data.jpa.repository.Query; | ||
19 | +import org.springframework.data.repository.CrudRepository; | ||
20 | +import org.springframework.data.repository.query.Param; | ||
21 | +import org.thingsboard.server.common.data.oauth2.SchemeType; | ||
22 | +import org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity; | ||
23 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity; | ||
24 | + | ||
25 | +import java.util.List; | ||
26 | +import java.util.UUID; | ||
27 | + | ||
28 | +public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> { | ||
29 | + @Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " + | ||
30 | + "FROM OAuth2ClientRegistrationInfoEntity cr_info " + | ||
31 | + "LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId " + | ||
32 | + "WHERE cr.domainName = :domainName " + | ||
33 | + "AND cr.domainScheme IN (:domainSchemes)") | ||
34 | + List<OAuth2ClientRegistrationInfoEntity> findAllByDomainSchemesAndName(@Param("domainSchemes") List<SchemeType> domainSchemes, | ||
35 | + @Param("domainName") String domainName); | ||
36 | + | ||
37 | + @Query("SELECT new org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " + | ||
38 | + "FROM OAuth2ClientRegistrationInfoEntity cr_info " + | ||
39 | + "LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ") | ||
40 | + List<ExtendedOAuth2ClientRegistrationInfoEntity> findAllExtended(); | ||
41 | +} |
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import org.springframework.data.repository.CrudRepository; | ||
19 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity; | ||
20 | + | ||
21 | +import java.util.UUID; | ||
22 | + | ||
23 | +public interface OAuth2ClientRegistrationRepository extends CrudRepository<OAuth2ClientRegistrationEntity, UUID> { | ||
24 | +} |
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.dao.sql.oauth2; | ||
17 | + | ||
18 | +import org.springframework.data.repository.CrudRepository; | ||
19 | +import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationTemplateEntity; | ||
20 | + | ||
21 | +import java.util.UUID; | ||
22 | + | ||
23 | +public interface OAuth2ClientRegistrationTemplateRepository extends CrudRepository<OAuth2ClientRegistrationTemplateEntity, UUID> { | ||
24 | +} |
@@ -331,3 +331,73 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary ( | @@ -331,3 +331,73 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary ( | ||
331 | key_id int GENERATED BY DEFAULT AS IDENTITY(start with 0 increment by 1) UNIQUE, | 331 | key_id int GENERATED BY DEFAULT AS IDENTITY(start with 0 increment by 1) UNIQUE, |
332 | CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) | 332 | CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) |
333 | ); | 333 | ); |
334 | + | ||
335 | + | ||
336 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( | ||
337 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, | ||
338 | + enabled boolean, | ||
339 | + created_time bigint NOT NULL, | ||
340 | + additional_info varchar, | ||
341 | + client_id varchar(255), | ||
342 | + client_secret varchar(255), | ||
343 | + authorization_uri varchar(255), | ||
344 | + token_uri varchar(255), | ||
345 | + scope varchar(255), | ||
346 | + user_info_uri varchar(255), | ||
347 | + user_name_attribute_name varchar(255), | ||
348 | + jwk_set_uri varchar(255), | ||
349 | + client_authentication_method varchar(255), | ||
350 | + login_button_label varchar(255), | ||
351 | + login_button_icon varchar(255), | ||
352 | + allow_user_creation boolean, | ||
353 | + activate_user boolean, | ||
354 | + type varchar(31), | ||
355 | + basic_email_attribute_key varchar(31), | ||
356 | + basic_first_name_attribute_key varchar(31), | ||
357 | + basic_last_name_attribute_key varchar(31), | ||
358 | + basic_tenant_name_strategy varchar(31), | ||
359 | + basic_tenant_name_pattern varchar(255), | ||
360 | + basic_customer_name_pattern varchar(255), | ||
361 | + basic_default_dashboard_name varchar(255), | ||
362 | + basic_always_full_screen boolean, | ||
363 | + custom_url varchar(255), | ||
364 | + custom_username varchar(255), | ||
365 | + custom_password varchar(255), | ||
366 | + custom_send_token boolean | ||
367 | +); | ||
368 | + | ||
369 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration ( | ||
370 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, | ||
371 | + created_time bigint NOT NULL, | ||
372 | + domain_name varchar(255), | ||
373 | + domain_scheme varchar(31), | ||
374 | + client_registration_info_id uuid | ||
375 | +); | ||
376 | + | ||
377 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | ||
378 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY, | ||
379 | + created_time bigint NOT NULL, | ||
380 | + additional_info varchar, | ||
381 | + provider_id varchar(255), | ||
382 | + authorization_uri varchar(255), | ||
383 | + token_uri varchar(255), | ||
384 | + scope varchar(255), | ||
385 | + user_info_uri varchar(255), | ||
386 | + user_name_attribute_name varchar(255), | ||
387 | + jwk_set_uri varchar(255), | ||
388 | + client_authentication_method varchar(255), | ||
389 | + type varchar(31), | ||
390 | + basic_email_attribute_key varchar(31), | ||
391 | + basic_first_name_attribute_key varchar(31), | ||
392 | + basic_last_name_attribute_key varchar(31), | ||
393 | + basic_tenant_name_strategy varchar(31), | ||
394 | + basic_tenant_name_pattern varchar(255), | ||
395 | + basic_customer_name_pattern varchar(255), | ||
396 | + basic_default_dashboard_name varchar(255), | ||
397 | + basic_always_full_screen boolean, | ||
398 | + comment varchar, | ||
399 | + login_button_icon varchar(255), | ||
400 | + login_button_label varchar(255), | ||
401 | + help_link varchar(255), | ||
402 | + CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) | ||
403 | +); |
@@ -359,6 +359,75 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary | @@ -359,6 +359,75 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary | ||
359 | CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) | 359 | CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) |
360 | ); | 360 | ); |
361 | 361 | ||
362 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( | ||
363 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, | ||
364 | + enabled boolean, | ||
365 | + created_time bigint NOT NULL, | ||
366 | + additional_info varchar, | ||
367 | + client_id varchar(255), | ||
368 | + client_secret varchar(255), | ||
369 | + authorization_uri varchar(255), | ||
370 | + token_uri varchar(255), | ||
371 | + scope varchar(255), | ||
372 | + user_info_uri varchar(255), | ||
373 | + user_name_attribute_name varchar(255), | ||
374 | + jwk_set_uri varchar(255), | ||
375 | + client_authentication_method varchar(255), | ||
376 | + login_button_label varchar(255), | ||
377 | + login_button_icon varchar(255), | ||
378 | + allow_user_creation boolean, | ||
379 | + activate_user boolean, | ||
380 | + type varchar(31), | ||
381 | + basic_email_attribute_key varchar(31), | ||
382 | + basic_first_name_attribute_key varchar(31), | ||
383 | + basic_last_name_attribute_key varchar(31), | ||
384 | + basic_tenant_name_strategy varchar(31), | ||
385 | + basic_tenant_name_pattern varchar(255), | ||
386 | + basic_customer_name_pattern varchar(255), | ||
387 | + basic_default_dashboard_name varchar(255), | ||
388 | + basic_always_full_screen boolean, | ||
389 | + custom_url varchar(255), | ||
390 | + custom_username varchar(255), | ||
391 | + custom_password varchar(255), | ||
392 | + custom_send_token boolean | ||
393 | +); | ||
394 | + | ||
395 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration ( | ||
396 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, | ||
397 | + created_time bigint NOT NULL, | ||
398 | + domain_name varchar(255), | ||
399 | + domain_scheme varchar(31), | ||
400 | + client_registration_info_id uuid | ||
401 | +); | ||
402 | + | ||
403 | +CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | ||
404 | + id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY, | ||
405 | + created_time bigint NOT NULL, | ||
406 | + additional_info varchar, | ||
407 | + provider_id varchar(255), | ||
408 | + authorization_uri varchar(255), | ||
409 | + token_uri varchar(255), | ||
410 | + scope varchar(255), | ||
411 | + user_info_uri varchar(255), | ||
412 | + user_name_attribute_name varchar(255), | ||
413 | + jwk_set_uri varchar(255), | ||
414 | + client_authentication_method varchar(255), | ||
415 | + type varchar(31), | ||
416 | + basic_email_attribute_key varchar(31), | ||
417 | + basic_first_name_attribute_key varchar(31), | ||
418 | + basic_last_name_attribute_key varchar(31), | ||
419 | + basic_tenant_name_strategy varchar(31), | ||
420 | + basic_tenant_name_pattern varchar(255), | ||
421 | + basic_customer_name_pattern varchar(255), | ||
422 | + basic_default_dashboard_name varchar(255), | ||
423 | + basic_always_full_screen boolean, | ||
424 | + comment varchar, | ||
425 | + login_button_icon varchar(255), | ||
426 | + login_button_label varchar(255), | ||
427 | + help_link varchar(255), | ||
428 | + CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) | ||
429 | +); | ||
430 | + | ||
362 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) | 431 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) |
363 | LANGUAGE plpgsql AS | 432 | LANGUAGE plpgsql AS |
364 | $$ | 433 | $$ |
dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ConfigTemplateServiceTest.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.dao.service; | ||
17 | + | ||
18 | +import org.junit.After; | ||
19 | +import org.junit.Assert; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.springframework.beans.factory.annotation.Autowired; | ||
23 | +import org.thingsboard.server.common.data.id.TenantId; | ||
24 | +import org.thingsboard.server.common.data.oauth2.MapperType; | ||
25 | +import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig; | ||
26 | +import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | ||
27 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
28 | +import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; | ||
29 | + | ||
30 | +import java.util.Arrays; | ||
31 | +import java.util.UUID; | ||
32 | + | ||
33 | +public class BaseOAuth2ConfigTemplateServiceTest extends AbstractServiceTest { | ||
34 | + | ||
35 | + @Autowired | ||
36 | + protected OAuth2ConfigTemplateService oAuth2ConfigTemplateService; | ||
37 | + | ||
38 | + @Before | ||
39 | + public void beforeRun() throws Exception { | ||
40 | + Assert.assertTrue(oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().isEmpty()); | ||
41 | + } | ||
42 | + | ||
43 | + @After | ||
44 | + public void after() throws Exception { | ||
45 | + oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().forEach(clientRegistrationTemplate -> { | ||
46 | + oAuth2ConfigTemplateService.deleteClientRegistrationTemplateById(clientRegistrationTemplate.getId()); | ||
47 | + }); | ||
48 | + | ||
49 | + Assert.assertTrue(oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().isEmpty()); | ||
50 | + } | ||
51 | + | ||
52 | + | ||
53 | + @Test(expected = DataValidationException.class) | ||
54 | + public void testSaveDuplicateProviderId() { | ||
55 | + OAuth2ClientRegistrationTemplate first = validClientRegistrationTemplate("providerId"); | ||
56 | + OAuth2ClientRegistrationTemplate second = validClientRegistrationTemplate("providerId"); | ||
57 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(first); | ||
58 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(second); | ||
59 | + } | ||
60 | + | ||
61 | + @Test | ||
62 | + public void testCreateNewTemplate() { | ||
63 | + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = validClientRegistrationTemplate(UUID.randomUUID().toString()); | ||
64 | + OAuth2ClientRegistrationTemplate savedClientRegistrationTemplate = oAuth2ConfigTemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate); | ||
65 | + | ||
66 | + Assert.assertNotNull(savedClientRegistrationTemplate); | ||
67 | + Assert.assertNotNull(savedClientRegistrationTemplate.getId()); | ||
68 | + clientRegistrationTemplate.setId(savedClientRegistrationTemplate.getId()); | ||
69 | + clientRegistrationTemplate.setCreatedTime(savedClientRegistrationTemplate.getCreatedTime()); | ||
70 | + Assert.assertEquals(clientRegistrationTemplate, savedClientRegistrationTemplate); | ||
71 | + } | ||
72 | + | ||
73 | + @Test | ||
74 | + public void testFindTemplate() { | ||
75 | + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = validClientRegistrationTemplate(UUID.randomUUID().toString()); | ||
76 | + OAuth2ClientRegistrationTemplate savedClientRegistrationTemplate = oAuth2ConfigTemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate); | ||
77 | + | ||
78 | + OAuth2ClientRegistrationTemplate foundClientRegistrationTemplate = oAuth2ConfigTemplateService.findClientRegistrationTemplateById(savedClientRegistrationTemplate.getId()); | ||
79 | + Assert.assertEquals(savedClientRegistrationTemplate, foundClientRegistrationTemplate); | ||
80 | + } | ||
81 | + | ||
82 | + @Test | ||
83 | + public void testFindAll() { | ||
84 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(validClientRegistrationTemplate(UUID.randomUUID().toString())); | ||
85 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(validClientRegistrationTemplate(UUID.randomUUID().toString())); | ||
86 | + | ||
87 | + Assert.assertEquals(2, oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().size()); | ||
88 | + } | ||
89 | + | ||
90 | + @Test | ||
91 | + public void testDeleteTemplate() { | ||
92 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(validClientRegistrationTemplate(UUID.randomUUID().toString())); | ||
93 | + oAuth2ConfigTemplateService.saveClientRegistrationTemplate(validClientRegistrationTemplate(UUID.randomUUID().toString())); | ||
94 | + OAuth2ClientRegistrationTemplate saved = oAuth2ConfigTemplateService.saveClientRegistrationTemplate(validClientRegistrationTemplate(UUID.randomUUID().toString())); | ||
95 | + | ||
96 | + Assert.assertEquals(3, oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().size()); | ||
97 | + Assert.assertNotNull(oAuth2ConfigTemplateService.findClientRegistrationTemplateById(saved.getId())); | ||
98 | + | ||
99 | + oAuth2ConfigTemplateService.deleteClientRegistrationTemplateById(saved.getId()); | ||
100 | + | ||
101 | + Assert.assertEquals(2, oAuth2ConfigTemplateService.findAllClientRegistrationTemplates().size()); | ||
102 | + Assert.assertNull(oAuth2ConfigTemplateService.findClientRegistrationTemplateById(saved.getId())); | ||
103 | + } | ||
104 | + | ||
105 | + private OAuth2ClientRegistrationTemplate validClientRegistrationTemplate(String providerId) { | ||
106 | + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = new OAuth2ClientRegistrationTemplate(); | ||
107 | + clientRegistrationTemplate.setProviderId(providerId); | ||
108 | + clientRegistrationTemplate.setAdditionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString())); | ||
109 | + clientRegistrationTemplate.setMapperType(MapperType.BASIC); | ||
110 | + clientRegistrationTemplate.setBasic( | ||
111 | + OAuth2BasicMapperConfig.builder() | ||
112 | + .firstNameAttributeKey("firstName") | ||
113 | + .lastNameAttributeKey("lastName") | ||
114 | + .emailAttributeKey("email") | ||
115 | + .tenantNamePattern("tenant") | ||
116 | + .defaultDashboardName("Test") | ||
117 | + .alwaysFullScreen(true) | ||
118 | + .build() | ||
119 | + ); | ||
120 | + clientRegistrationTemplate.setAuthorizationUri("authorizationUri"); | ||
121 | + clientRegistrationTemplate.setAccessTokenUri("tokenUri"); | ||
122 | + clientRegistrationTemplate.setScope(Arrays.asList("scope1", "scope2")); | ||
123 | + clientRegistrationTemplate.setUserInfoUri("userInfoUri"); | ||
124 | + clientRegistrationTemplate.setUserNameAttributeName("userNameAttributeName"); | ||
125 | + clientRegistrationTemplate.setJwkSetUri("jwkSetUri"); | ||
126 | + clientRegistrationTemplate.setClientAuthenticationMethod("clientAuthenticationMethod"); | ||
127 | + clientRegistrationTemplate.setComment("comment"); | ||
128 | + clientRegistrationTemplate.setLoginButtonIcon("icon"); | ||
129 | + clientRegistrationTemplate.setLoginButtonLabel("label"); | ||
130 | + clientRegistrationTemplate.setHelpLink("helpLink"); | ||
131 | + return clientRegistrationTemplate; | ||
132 | + } | ||
133 | +} |
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.dao.service; | ||
17 | + | ||
18 | +import com.google.common.collect.Sets; | ||
19 | +import org.junit.After; | ||
20 | +import org.junit.Assert; | ||
21 | +import org.junit.Before; | ||
22 | +import org.junit.Test; | ||
23 | +import org.springframework.beans.factory.annotation.Autowired; | ||
24 | +import org.thingsboard.server.common.data.oauth2.*; | ||
25 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
26 | +import org.thingsboard.server.dao.oauth2.OAuth2Service; | ||
27 | + | ||
28 | +import java.util.*; | ||
29 | +import java.util.stream.Collectors; | ||
30 | + | ||
31 | +public class BaseOAuth2ServiceTest extends AbstractServiceTest { | ||
32 | + private static final OAuth2ClientsParams EMPTY_PARAMS = new OAuth2ClientsParams(false, new HashSet<>()); | ||
33 | + | ||
34 | + @Autowired | ||
35 | + protected OAuth2Service oAuth2Service; | ||
36 | + | ||
37 | + @Before | ||
38 | + public void beforeRun() { | ||
39 | + Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty()); | ||
40 | + } | ||
41 | + | ||
42 | + @After | ||
43 | + public void after() { | ||
44 | + oAuth2Service.saveOAuth2Params(EMPTY_PARAMS); | ||
45 | + Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty()); | ||
46 | + Assert.assertTrue(oAuth2Service.findOAuth2Params().getDomainsParams().isEmpty()); | ||
47 | + } | ||
48 | + | ||
49 | + @Test(expected = DataValidationException.class) | ||
50 | + public void testSaveHttpAndMixedDomainsTogether() { | ||
51 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
52 | + OAuth2ClientsDomainParams.builder() | ||
53 | + .domainInfos(Sets.newHashSet( | ||
54 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
55 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(), | ||
56 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
57 | + )) | ||
58 | + .clientRegistrations(Sets.newHashSet( | ||
59 | + validClientRegistrationDto(), | ||
60 | + validClientRegistrationDto(), | ||
61 | + validClientRegistrationDto() | ||
62 | + )) | ||
63 | + .build() | ||
64 | + )); | ||
65 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
66 | + } | ||
67 | + | ||
68 | + @Test(expected = DataValidationException.class) | ||
69 | + public void testSaveHttpsAndMixedDomainsTogether() { | ||
70 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
71 | + OAuth2ClientsDomainParams.builder() | ||
72 | + .domainInfos(Sets.newHashSet( | ||
73 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(), | ||
74 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(), | ||
75 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
76 | + )) | ||
77 | + .clientRegistrations(Sets.newHashSet( | ||
78 | + validClientRegistrationDto(), | ||
79 | + validClientRegistrationDto(), | ||
80 | + validClientRegistrationDto() | ||
81 | + )) | ||
82 | + .build() | ||
83 | + )); | ||
84 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
85 | + } | ||
86 | + | ||
87 | + @Test | ||
88 | + public void testCreateAndFindParams() { | ||
89 | + OAuth2ClientsParams clientsParams = createDefaultClientsParams(); | ||
90 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
91 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
92 | + Assert.assertNotNull(foundClientsParams); | ||
93 | + // TODO ask if it's safe to check equality on AdditionalProperties | ||
94 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
95 | + } | ||
96 | + | ||
97 | + @Test | ||
98 | + public void testDisableParams() { | ||
99 | + OAuth2ClientsParams clientsParams = createDefaultClientsParams(); | ||
100 | + clientsParams.setEnabled(true); | ||
101 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
102 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
103 | + Assert.assertNotNull(foundClientsParams); | ||
104 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
105 | + | ||
106 | + clientsParams.setEnabled(false); | ||
107 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
108 | + OAuth2ClientsParams foundDisabledClientsParams = oAuth2Service.findOAuth2Params(); | ||
109 | + Assert.assertEquals(clientsParams, foundDisabledClientsParams); | ||
110 | + } | ||
111 | + | ||
112 | + @Test | ||
113 | + public void testClearDomainParams() { | ||
114 | + OAuth2ClientsParams clientsParams = createDefaultClientsParams(); | ||
115 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
116 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
117 | + Assert.assertNotNull(foundClientsParams); | ||
118 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
119 | + | ||
120 | + oAuth2Service.saveOAuth2Params(EMPTY_PARAMS); | ||
121 | + OAuth2ClientsParams foundAfterClearClientsParams = oAuth2Service.findOAuth2Params(); | ||
122 | + Assert.assertNotNull(foundAfterClearClientsParams); | ||
123 | + Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams); | ||
124 | + } | ||
125 | + | ||
126 | + @Test | ||
127 | + public void testUpdateClientsParams() { | ||
128 | + OAuth2ClientsParams clientsParams = createDefaultClientsParams(); | ||
129 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
130 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
131 | + Assert.assertNotNull(foundClientsParams); | ||
132 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
133 | + | ||
134 | + OAuth2ClientsParams newClientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
135 | + OAuth2ClientsDomainParams.builder() | ||
136 | + .domainInfos(Sets.newHashSet( | ||
137 | + DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build() | ||
138 | + )) | ||
139 | + .clientRegistrations(Sets.newHashSet( | ||
140 | + validClientRegistrationDto() | ||
141 | + )) | ||
142 | + .build(), | ||
143 | + OAuth2ClientsDomainParams.builder() | ||
144 | + .domainInfos(Sets.newHashSet( | ||
145 | + DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build() | ||
146 | + )) | ||
147 | + .clientRegistrations(Sets.newHashSet( | ||
148 | + validClientRegistrationDto() | ||
149 | + )) | ||
150 | + .build() | ||
151 | + )); | ||
152 | + oAuth2Service.saveOAuth2Params(newClientsParams); | ||
153 | + OAuth2ClientsParams foundAfterUpdateClientsParams = oAuth2Service.findOAuth2Params(); | ||
154 | + Assert.assertNotNull(foundAfterUpdateClientsParams); | ||
155 | + Assert.assertEquals(newClientsParams, foundAfterUpdateClientsParams); | ||
156 | + } | ||
157 | + | ||
158 | + @Test | ||
159 | + public void testGetOAuth2Clients() { | ||
160 | + Set<ClientRegistrationDto> firstGroup = Sets.newHashSet( | ||
161 | + validClientRegistrationDto(), | ||
162 | + validClientRegistrationDto(), | ||
163 | + validClientRegistrationDto(), | ||
164 | + validClientRegistrationDto() | ||
165 | + ); | ||
166 | + Set<ClientRegistrationDto> secondGroup = Sets.newHashSet( | ||
167 | + validClientRegistrationDto(), | ||
168 | + validClientRegistrationDto() | ||
169 | + ); | ||
170 | + Set<ClientRegistrationDto> thirdGroup = Sets.newHashSet( | ||
171 | + validClientRegistrationDto() | ||
172 | + ); | ||
173 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
174 | + OAuth2ClientsDomainParams.builder() | ||
175 | + .domainInfos(Sets.newHashSet( | ||
176 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
177 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
178 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
179 | + )) | ||
180 | + .clientRegistrations(firstGroup) | ||
181 | + .build(), | ||
182 | + OAuth2ClientsDomainParams.builder() | ||
183 | + .domainInfos(Sets.newHashSet( | ||
184 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(), | ||
185 | + DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | ||
186 | + )) | ||
187 | + .clientRegistrations(secondGroup) | ||
188 | + .build(), | ||
189 | + OAuth2ClientsDomainParams.builder() | ||
190 | + .domainInfos(Sets.newHashSet( | ||
191 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(), | ||
192 | + DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() | ||
193 | + )) | ||
194 | + .clientRegistrations(thirdGroup) | ||
195 | + .build() | ||
196 | + )); | ||
197 | + | ||
198 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
199 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
200 | + Assert.assertNotNull(foundClientsParams); | ||
201 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
202 | + | ||
203 | + List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream() | ||
204 | + .map(clientRegistrationDto -> new OAuth2ClientInfo( | ||
205 | + clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) | ||
206 | + .collect(Collectors.toList()); | ||
207 | + List<OAuth2ClientInfo> secondGroupClientInfos = secondGroup.stream() | ||
208 | + .map(clientRegistrationDto -> new OAuth2ClientInfo( | ||
209 | + clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) | ||
210 | + .collect(Collectors.toList()); | ||
211 | + List<OAuth2ClientInfo> thirdGroupClientInfos = thirdGroup.stream() | ||
212 | + .map(clientRegistrationDto -> new OAuth2ClientInfo( | ||
213 | + clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) | ||
214 | + .collect(Collectors.toList()); | ||
215 | + | ||
216 | + List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain"); | ||
217 | + Assert.assertTrue(nonExistentDomainClients.isEmpty()); | ||
218 | + | ||
219 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain"); | ||
220 | + Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); | ||
221 | + firstGroupClientInfos.forEach(firstGroupClientInfo -> { | ||
222 | + Assert.assertTrue( | ||
223 | + firstDomainHttpClients.stream().anyMatch(clientInfo -> | ||
224 | + clientInfo.getIcon().equals(firstGroupClientInfo.getIcon()) | ||
225 | + && clientInfo.getName().equals(firstGroupClientInfo.getName())) | ||
226 | + ); | ||
227 | + }); | ||
228 | + | ||
229 | + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain"); | ||
230 | + Assert.assertTrue(firstDomainHttpsClients.isEmpty()); | ||
231 | + | ||
232 | + List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain"); | ||
233 | + Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size()); | ||
234 | + secondGroupClientInfos.forEach(secondGroupClientInfo -> { | ||
235 | + Assert.assertTrue( | ||
236 | + fourthDomainHttpClients.stream().anyMatch(clientInfo -> | ||
237 | + clientInfo.getIcon().equals(secondGroupClientInfo.getIcon()) | ||
238 | + && clientInfo.getName().equals(secondGroupClientInfo.getName())) | ||
239 | + ); | ||
240 | + }); | ||
241 | + List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain"); | ||
242 | + Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size()); | ||
243 | + secondGroupClientInfos.forEach(secondGroupClientInfo -> { | ||
244 | + Assert.assertTrue( | ||
245 | + fourthDomainHttpsClients.stream().anyMatch(clientInfo -> | ||
246 | + clientInfo.getIcon().equals(secondGroupClientInfo.getIcon()) | ||
247 | + && clientInfo.getName().equals(secondGroupClientInfo.getName())) | ||
248 | + ); | ||
249 | + }); | ||
250 | + | ||
251 | + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); | ||
252 | + Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size()); | ||
253 | + firstGroupClientInfos.forEach(firstGroupClientInfo -> { | ||
254 | + Assert.assertTrue( | ||
255 | + secondDomainHttpClients.stream().anyMatch(clientInfo -> | ||
256 | + clientInfo.getIcon().equals(firstGroupClientInfo.getIcon()) | ||
257 | + && clientInfo.getName().equals(firstGroupClientInfo.getName())) | ||
258 | + ); | ||
259 | + }); | ||
260 | + secondGroupClientInfos.forEach(secondGroupClientInfo -> { | ||
261 | + Assert.assertTrue( | ||
262 | + secondDomainHttpClients.stream().anyMatch(clientInfo -> | ||
263 | + clientInfo.getIcon().equals(secondGroupClientInfo.getIcon()) | ||
264 | + && clientInfo.getName().equals(secondGroupClientInfo.getName())) | ||
265 | + ); | ||
266 | + }); | ||
267 | + | ||
268 | + List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain"); | ||
269 | + Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size()); | ||
270 | + firstGroupClientInfos.forEach(firstGroupClientInfo -> { | ||
271 | + Assert.assertTrue( | ||
272 | + secondDomainHttpsClients.stream().anyMatch(clientInfo -> | ||
273 | + clientInfo.getIcon().equals(firstGroupClientInfo.getIcon()) | ||
274 | + && clientInfo.getName().equals(firstGroupClientInfo.getName())) | ||
275 | + ); | ||
276 | + }); | ||
277 | + thirdGroupClientInfos.forEach(thirdGroupClientInfo -> { | ||
278 | + Assert.assertTrue( | ||
279 | + secondDomainHttpsClients.stream().anyMatch(clientInfo -> | ||
280 | + clientInfo.getIcon().equals(thirdGroupClientInfo.getIcon()) | ||
281 | + && clientInfo.getName().equals(thirdGroupClientInfo.getName())) | ||
282 | + ); | ||
283 | + }); | ||
284 | + } | ||
285 | + | ||
286 | + @Test | ||
287 | + public void testGetOAuth2ClientsForHttpAndHttps() { | ||
288 | + Set<ClientRegistrationDto> firstGroup = Sets.newHashSet( | ||
289 | + validClientRegistrationDto(), | ||
290 | + validClientRegistrationDto(), | ||
291 | + validClientRegistrationDto(), | ||
292 | + validClientRegistrationDto() | ||
293 | + ); | ||
294 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
295 | + OAuth2ClientsDomainParams.builder() | ||
296 | + .domainInfos(Sets.newHashSet( | ||
297 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
298 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
299 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build() | ||
300 | + )) | ||
301 | + .clientRegistrations(firstGroup) | ||
302 | + .build() | ||
303 | + )); | ||
304 | + | ||
305 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
306 | + OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params(); | ||
307 | + Assert.assertNotNull(foundClientsParams); | ||
308 | + Assert.assertEquals(clientsParams, foundClientsParams); | ||
309 | + | ||
310 | + List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream() | ||
311 | + .map(clientRegistrationDto -> new OAuth2ClientInfo( | ||
312 | + clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) | ||
313 | + .collect(Collectors.toList()); | ||
314 | + | ||
315 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain"); | ||
316 | + Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); | ||
317 | + firstGroupClientInfos.forEach(firstGroupClientInfo -> { | ||
318 | + Assert.assertTrue( | ||
319 | + firstDomainHttpClients.stream().anyMatch(clientInfo -> | ||
320 | + clientInfo.getIcon().equals(firstGroupClientInfo.getIcon()) | ||
321 | + && clientInfo.getName().equals(firstGroupClientInfo.getName())) | ||
322 | + ); | ||
323 | + }); | ||
324 | + | ||
325 | + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain"); | ||
326 | + Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size()); | ||
327 | + firstGroupClientInfos.forEach(firstGroupClientInfo -> { | ||
328 | + Assert.assertTrue( | ||
329 | + firstDomainHttpsClients.stream().anyMatch(clientInfo -> | ||
330 | + clientInfo.getIcon().equals(firstGroupClientInfo.getIcon()) | ||
331 | + && clientInfo.getName().equals(firstGroupClientInfo.getName())) | ||
332 | + ); | ||
333 | + }); | ||
334 | + } | ||
335 | + | ||
336 | + @Test | ||
337 | + public void testGetDisabledOAuth2Clients() { | ||
338 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
339 | + OAuth2ClientsDomainParams.builder() | ||
340 | + .domainInfos(Sets.newHashSet( | ||
341 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
342 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
343 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
344 | + )) | ||
345 | + .clientRegistrations(Sets.newHashSet( | ||
346 | + validClientRegistrationDto(), | ||
347 | + validClientRegistrationDto(), | ||
348 | + validClientRegistrationDto() | ||
349 | + )) | ||
350 | + .build(), | ||
351 | + OAuth2ClientsDomainParams.builder() | ||
352 | + .domainInfos(Sets.newHashSet( | ||
353 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(), | ||
354 | + DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | ||
355 | + )) | ||
356 | + .clientRegistrations(Sets.newHashSet( | ||
357 | + validClientRegistrationDto(), | ||
358 | + validClientRegistrationDto() | ||
359 | + )) | ||
360 | + .build() | ||
361 | + )); | ||
362 | + | ||
363 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
364 | + | ||
365 | + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); | ||
366 | + Assert.assertEquals(5, secondDomainHttpClients.size()); | ||
367 | + | ||
368 | + clientsParams.setEnabled(false); | ||
369 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
370 | + | ||
371 | + List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); | ||
372 | + Assert.assertEquals(0, secondDomainHttpDisabledClients.size()); | ||
373 | + } | ||
374 | + | ||
375 | + @Test | ||
376 | + public void testFindAllClientRegistrationInfos() { | ||
377 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
378 | + OAuth2ClientsDomainParams.builder() | ||
379 | + .domainInfos(Sets.newHashSet( | ||
380 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
381 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
382 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
383 | + )) | ||
384 | + .clientRegistrations(Sets.newHashSet( | ||
385 | + validClientRegistrationDto(), | ||
386 | + validClientRegistrationDto(), | ||
387 | + validClientRegistrationDto() | ||
388 | + )) | ||
389 | + .build(), | ||
390 | + OAuth2ClientsDomainParams.builder() | ||
391 | + .domainInfos(Sets.newHashSet( | ||
392 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(), | ||
393 | + DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | ||
394 | + )) | ||
395 | + .clientRegistrations(Sets.newHashSet( | ||
396 | + validClientRegistrationDto(), | ||
397 | + validClientRegistrationDto() | ||
398 | + )) | ||
399 | + .build(), | ||
400 | + OAuth2ClientsDomainParams.builder() | ||
401 | + .domainInfos(Sets.newHashSet( | ||
402 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(), | ||
403 | + DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() | ||
404 | + )) | ||
405 | + .clientRegistrations(Sets.newHashSet( | ||
406 | + validClientRegistrationDto() | ||
407 | + )) | ||
408 | + .build() | ||
409 | + )); | ||
410 | + | ||
411 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
412 | + List<OAuth2ClientRegistrationInfo> foundClientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos(); | ||
413 | + Assert.assertEquals(6, foundClientRegistrationInfos.size()); | ||
414 | + clientsParams.getDomainsParams().stream() | ||
415 | + .flatMap(domainParams -> domainParams.getClientRegistrations().stream()) | ||
416 | + .forEach(clientRegistrationDto -> | ||
417 | + Assert.assertTrue( | ||
418 | + foundClientRegistrationInfos.stream() | ||
419 | + .anyMatch(clientRegistrationInfo -> clientRegistrationInfo.getClientId().equals(clientRegistrationDto.getClientId())) | ||
420 | + ) | ||
421 | + ); | ||
422 | + } | ||
423 | + | ||
424 | + @Test | ||
425 | + public void testFindClientRegistrationById() { | ||
426 | + OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Sets.newHashSet( | ||
427 | + OAuth2ClientsDomainParams.builder() | ||
428 | + .domainInfos(Sets.newHashSet( | ||
429 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
430 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
431 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
432 | + )) | ||
433 | + .clientRegistrations(Sets.newHashSet( | ||
434 | + validClientRegistrationDto(), | ||
435 | + validClientRegistrationDto(), | ||
436 | + validClientRegistrationDto() | ||
437 | + )) | ||
438 | + .build(), | ||
439 | + OAuth2ClientsDomainParams.builder() | ||
440 | + .domainInfos(Sets.newHashSet( | ||
441 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(), | ||
442 | + DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | ||
443 | + )) | ||
444 | + .clientRegistrations(Sets.newHashSet( | ||
445 | + validClientRegistrationDto(), | ||
446 | + validClientRegistrationDto() | ||
447 | + )) | ||
448 | + .build(), | ||
449 | + OAuth2ClientsDomainParams.builder() | ||
450 | + .domainInfos(Sets.newHashSet( | ||
451 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(), | ||
452 | + DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() | ||
453 | + )) | ||
454 | + .clientRegistrations(Sets.newHashSet( | ||
455 | + validClientRegistrationDto() | ||
456 | + )) | ||
457 | + .build() | ||
458 | + )); | ||
459 | + | ||
460 | + oAuth2Service.saveOAuth2Params(clientsParams); | ||
461 | + List<OAuth2ClientRegistrationInfo> clientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos(); | ||
462 | + clientRegistrationInfos.forEach(clientRegistrationInfo -> { | ||
463 | + OAuth2ClientRegistrationInfo foundClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(clientRegistrationInfo.getUuidId()); | ||
464 | + Assert.assertEquals(clientRegistrationInfo, foundClientRegistrationInfo); | ||
465 | + }); | ||
466 | + } | ||
467 | + | ||
468 | + private OAuth2ClientsParams createDefaultClientsParams() { | ||
469 | + return new OAuth2ClientsParams(true, Sets.newHashSet( | ||
470 | + OAuth2ClientsDomainParams.builder() | ||
471 | + .domainInfos(Sets.newHashSet( | ||
472 | + DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | ||
473 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
474 | + DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | ||
475 | + )) | ||
476 | + .clientRegistrations(Sets.newHashSet( | ||
477 | + validClientRegistrationDto(), | ||
478 | + validClientRegistrationDto(), | ||
479 | + validClientRegistrationDto(), | ||
480 | + validClientRegistrationDto() | ||
481 | + )) | ||
482 | + .build(), | ||
483 | + OAuth2ClientsDomainParams.builder() | ||
484 | + .domainInfos(Sets.newHashSet( | ||
485 | + DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | ||
486 | + DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | ||
487 | + )) | ||
488 | + .clientRegistrations(Sets.newHashSet( | ||
489 | + validClientRegistrationDto(), | ||
490 | + validClientRegistrationDto() | ||
491 | + )) | ||
492 | + .build() | ||
493 | + )); | ||
494 | + } | ||
495 | + | ||
496 | + private ClientRegistrationDto validClientRegistrationDto() { | ||
497 | + return ClientRegistrationDto.builder() | ||
498 | + .clientId(UUID.randomUUID().toString()) | ||
499 | + .clientSecret(UUID.randomUUID().toString()) | ||
500 | + .authorizationUri(UUID.randomUUID().toString()) | ||
501 | + .accessTokenUri(UUID.randomUUID().toString()) | ||
502 | + .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString())) | ||
503 | + .userInfoUri(UUID.randomUUID().toString()) | ||
504 | + .userNameAttributeName(UUID.randomUUID().toString()) | ||
505 | + .jwkSetUri(UUID.randomUUID().toString()) | ||
506 | + .clientAuthenticationMethod(UUID.randomUUID().toString()) | ||
507 | + .loginButtonLabel(UUID.randomUUID().toString()) | ||
508 | + .loginButtonIcon(UUID.randomUUID().toString()) | ||
509 | + .additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString())) | ||
510 | + .mapperConfig( | ||
511 | + OAuth2MapperConfig.builder() | ||
512 | + .allowUserCreation(true) | ||
513 | + .activateUser(true) | ||
514 | + .type(MapperType.CUSTOM) | ||
515 | + .custom( | ||
516 | + OAuth2CustomMapperConfig.builder() | ||
517 | + .url(UUID.randomUUID().toString()) | ||
518 | + .build() | ||
519 | + ) | ||
520 | + .build() | ||
521 | + ) | ||
522 | + .build(); | ||
523 | + } | ||
524 | +} |
dao/src/test/java/org/thingsboard/server/dao/service/sql/OAuth2ConfigTemplateServiceSqlTest.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.dao.service.sql; | ||
17 | + | ||
18 | +import org.thingsboard.server.dao.service.BaseOAuth2ConfigTemplateServiceTest; | ||
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | ||
20 | + | ||
21 | +@DaoSqlTest | ||
22 | +public class OAuth2ConfigTemplateServiceSqlTest extends BaseOAuth2ConfigTemplateServiceTest { | ||
23 | +} |
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.dao.service.sql; | ||
17 | + | ||
18 | +import org.thingsboard.server.dao.service.BaseOAuth2ServiceTest; | ||
19 | +import org.thingsboard.server.dao.service.DaoSqlTest; | ||
20 | + | ||
21 | +@DaoSqlTest | ||
22 | +public class OAuth2ServiceSqlTest extends BaseOAuth2ServiceTest { | ||
23 | +} |
@@ -24,4 +24,7 @@ DROP TABLE IF EXISTS tenant_profile; | @@ -24,4 +24,7 @@ DROP TABLE IF EXISTS tenant_profile; | ||
24 | DROP TABLE IF EXISTS rule_node_state; | 24 | DROP TABLE IF EXISTS rule_node_state; |
25 | DROP TABLE IF EXISTS rule_node; | 25 | DROP TABLE IF EXISTS rule_node; |
26 | DROP TABLE IF EXISTS rule_chain; | 26 | DROP TABLE IF EXISTS rule_chain; |
27 | +DROP TABLE IF EXISTS oauth2_client_registration; | ||
28 | +DROP TABLE IF EXISTS oauth2_client_registration_info; | ||
29 | +DROP TABLE IF EXISTS oauth2_client_registration_template; | ||
27 | DROP FUNCTION IF EXISTS to_uuid; | 30 | DROP FUNCTION IF EXISTS to_uuid; |
@@ -25,3 +25,6 @@ DROP TABLE IF EXISTS rule_node_state; | @@ -25,3 +25,6 @@ DROP TABLE IF EXISTS rule_node_state; | ||
25 | DROP TABLE IF EXISTS rule_node; | 25 | DROP TABLE IF EXISTS rule_node; |
26 | DROP TABLE IF EXISTS rule_chain; | 26 | DROP TABLE IF EXISTS rule_chain; |
27 | DROP TABLE IF EXISTS tb_schema_settings; | 27 | DROP TABLE IF EXISTS tb_schema_settings; |
28 | +DROP TABLE IF EXISTS oauth2_client_registration; | ||
29 | +DROP TABLE IF EXISTS oauth2_client_registration_info; | ||
30 | +DROP TABLE IF EXISTS oauth2_client_registration_template; |
@@ -25,3 +25,6 @@ DROP TABLE IF EXISTS entity_view; | @@ -25,3 +25,6 @@ DROP TABLE IF EXISTS entity_view; | ||
25 | DROP TABLE IF EXISTS device_profile; | 25 | DROP TABLE IF EXISTS device_profile; |
26 | DROP TABLE IF EXISTS tenant_profile; | 26 | DROP TABLE IF EXISTS tenant_profile; |
27 | DROP TABLE IF EXISTS tb_schema_settings; | 27 | DROP TABLE IF EXISTS tb_schema_settings; |
28 | +DROP TABLE IF EXISTS oauth2_client_registration; | ||
29 | +DROP TABLE IF EXISTS oauth2_client_registration_info; | ||
30 | +DROP TABLE IF EXISTS oauth2_client_registration_template; |
@@ -18,7 +18,7 @@ import { Injectable, NgZone } from '@angular/core'; | @@ -18,7 +18,7 @@ import { Injectable, NgZone } from '@angular/core'; | ||
18 | import { JwtHelperService } from '@auth0/angular-jwt'; | 18 | import { JwtHelperService } from '@auth0/angular-jwt'; |
19 | import { HttpClient } from '@angular/common/http'; | 19 | import { HttpClient } from '@angular/common/http'; |
20 | 20 | ||
21 | -import { forkJoin, Observable, of, throwError, ReplaySubject } from 'rxjs'; | 21 | +import { forkJoin, Observable, of, ReplaySubject, throwError } from 'rxjs'; |
22 | import { catchError, map, mergeMap, tap } from 'rxjs/operators'; | 22 | import { catchError, map, mergeMap, tap } from 'rxjs/operators'; |
23 | 23 | ||
24 | import { LoginRequest, LoginResponse, OAuth2Client, PublicLoginRequest } from '@shared/models/login.models'; | 24 | import { LoginRequest, LoginResponse, OAuth2Client, PublicLoginRequest } from '@shared/models/login.models'; |
@@ -18,7 +18,14 @@ import { Injectable } from '@angular/core'; | @@ -18,7 +18,14 @@ import { Injectable } from '@angular/core'; | ||
18 | import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; | 18 | import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; |
19 | import { Observable } from 'rxjs'; | 19 | import { Observable } from 'rxjs'; |
20 | import { HttpClient } from '@angular/common/http'; | 20 | import { HttpClient } from '@angular/common/http'; |
21 | -import { AdminSettings, MailServerSettings, SecuritySettings, UpdateMessage } from '@shared/models/settings.models'; | 21 | +import { |
22 | + AdminSettings, | ||
23 | + ClientProviderTemplated, | ||
24 | + MailServerSettings, | ||
25 | + OAuth2Settings, | ||
26 | + SecuritySettings, | ||
27 | + UpdateMessage | ||
28 | +} from '@shared/models/settings.models'; | ||
22 | 29 | ||
23 | @Injectable({ | 30 | @Injectable({ |
24 | providedIn: 'root' | 31 | providedIn: 'root' |
@@ -53,6 +60,19 @@ export class AdminService { | @@ -53,6 +60,19 @@ export class AdminService { | ||
53 | defaultHttpOptionsFromConfig(config)); | 60 | defaultHttpOptionsFromConfig(config)); |
54 | } | 61 | } |
55 | 62 | ||
63 | + public getOAuth2Settings(config?: RequestConfig): Observable<OAuth2Settings> { | ||
64 | + return this.http.get<OAuth2Settings>(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config)); | ||
65 | + } | ||
66 | + | ||
67 | + public getOAuth2Template(config?: RequestConfig): Observable<Array<ClientProviderTemplated>> { | ||
68 | + return this.http.get<Array<ClientProviderTemplated>>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config)); | ||
69 | + } | ||
70 | + | ||
71 | + public saveOAuth2Settings(OAuth2Setting: OAuth2Settings, config?: RequestConfig): Observable<OAuth2Settings> { | ||
72 | + return this.http.post<OAuth2Settings>('/api/oauth2/config', OAuth2Setting, | ||
73 | + defaultHttpOptionsFromConfig(config)); | ||
74 | + } | ||
75 | + | ||
56 | public checkUpdates(config?: RequestConfig): Observable<UpdateMessage> { | 76 | public checkUpdates(config?: RequestConfig): Observable<UpdateMessage> { |
57 | return this.http.get<UpdateMessage>(`/api/admin/updates`, defaultHttpOptionsFromConfig(config)); | 77 | return this.http.get<UpdateMessage>(`/api/admin/updates`, defaultHttpOptionsFromConfig(config)); |
58 | } | 78 | } |
@@ -108,7 +108,7 @@ export class MenuService { | @@ -108,7 +108,7 @@ export class MenuService { | ||
108 | name: 'admin.system-settings', | 108 | name: 'admin.system-settings', |
109 | type: 'toggle', | 109 | type: 'toggle', |
110 | path: '/settings', | 110 | path: '/settings', |
111 | - height: '120px', | 111 | + height: '160px', |
112 | icon: 'settings', | 112 | icon: 'settings', |
113 | pages: [ | 113 | pages: [ |
114 | { | 114 | { |
@@ -131,6 +131,13 @@ export class MenuService { | @@ -131,6 +131,13 @@ export class MenuService { | ||
131 | type: 'link', | 131 | type: 'link', |
132 | path: '/settings/security-settings', | 132 | path: '/settings/security-settings', |
133 | icon: 'security' | 133 | icon: 'security' |
134 | + }, | ||
135 | + { | ||
136 | + id: guid(), | ||
137 | + name: 'admin.oauth2.oauth2', | ||
138 | + type: 'link', | ||
139 | + path: '/settings/oauth2', | ||
140 | + icon: 'security' | ||
134 | } | 141 | } |
135 | ] | 142 | ] |
136 | } | 143 | } |
@@ -22,6 +22,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; | @@ -22,6 +22,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; | ||
22 | import { Authority } from '@shared/models/authority.enum'; | 22 | import { Authority } from '@shared/models/authority.enum'; |
23 | import { GeneralSettingsComponent } from '@modules/home/pages/admin/general-settings.component'; | 23 | import { GeneralSettingsComponent } from '@modules/home/pages/admin/general-settings.component'; |
24 | import { SecuritySettingsComponent } from '@modules/home/pages/admin/security-settings.component'; | 24 | import { SecuritySettingsComponent } from '@modules/home/pages/admin/security-settings.component'; |
25 | +import { OAuth2SettingsComponent } from '@home/pages/admin/oauth2-settings.component'; | ||
25 | 26 | ||
26 | const routes: Routes = [ | 27 | const routes: Routes = [ |
27 | { | 28 | { |
@@ -77,6 +78,19 @@ const routes: Routes = [ | @@ -77,6 +78,19 @@ const routes: Routes = [ | ||
77 | icon: 'security' | 78 | icon: 'security' |
78 | } | 79 | } |
79 | } | 80 | } |
81 | + }, | ||
82 | + { | ||
83 | + path: 'oauth2', | ||
84 | + component: OAuth2SettingsComponent, | ||
85 | + canDeactivate: [ConfirmOnExitGuard], | ||
86 | + data: { | ||
87 | + auth: [Authority.SYS_ADMIN], | ||
88 | + title: 'admin.oauth2.oauth2', | ||
89 | + breadcrumb: { | ||
90 | + label: 'admin.oauth2.oauth2', | ||
91 | + icon: 'security' | ||
92 | + } | ||
93 | + } | ||
80 | } | 94 | } |
81 | ] | 95 | ] |
82 | } | 96 | } |
@@ -23,13 +23,15 @@ import { MailServerComponent } from '@modules/home/pages/admin/mail-server.compo | @@ -23,13 +23,15 @@ import { MailServerComponent } from '@modules/home/pages/admin/mail-server.compo | ||
23 | import { GeneralSettingsComponent } from '@modules/home/pages/admin/general-settings.component'; | 23 | import { GeneralSettingsComponent } from '@modules/home/pages/admin/general-settings.component'; |
24 | import { SecuritySettingsComponent } from '@modules/home/pages/admin/security-settings.component'; | 24 | import { SecuritySettingsComponent } from '@modules/home/pages/admin/security-settings.component'; |
25 | import { HomeComponentsModule } from '@modules/home/components/home-components.module'; | 25 | import { HomeComponentsModule } from '@modules/home/components/home-components.module'; |
26 | +import { OAuth2SettingsComponent } from '@modules/home/pages/admin/oauth2-settings.component'; | ||
26 | 27 | ||
27 | @NgModule({ | 28 | @NgModule({ |
28 | declarations: | 29 | declarations: |
29 | [ | 30 | [ |
30 | GeneralSettingsComponent, | 31 | GeneralSettingsComponent, |
31 | MailServerComponent, | 32 | MailServerComponent, |
32 | - SecuritySettingsComponent | 33 | + SecuritySettingsComponent, |
34 | + OAuth2SettingsComponent | ||
33 | ], | 35 | ], |
34 | imports: [ | 36 | imports: [ |
35 | CommonModule, | 37 | CommonModule, |