diff --git a/application/src/main/java/it/smartcommunitylabdhub/core/config/SecurityConfig.java b/application/src/main/java/it/smartcommunitylabdhub/core/config/SecurityConfig.java index 51a74367..36bf852d 100644 --- a/application/src/main/java/it/smartcommunitylabdhub/core/config/SecurityConfig.java +++ b/application/src/main/java/it/smartcommunitylabdhub/core/config/SecurityConfig.java @@ -187,8 +187,8 @@ public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exce return securityChain.build(); } - @Bean("authSecurityFilterChain") - public SecurityFilterChain authSecurityFilterChain(HttpSecurity http) throws Exception { + @Bean("tokenSecurityFilterChain") + public SecurityFilterChain tokenSecurityFilterChain(HttpSecurity http) throws Exception { //token chain HttpSecurity securityChain = http .securityMatcher(new AntPathRequestMatcher("/auth/token")) @@ -202,13 +202,9 @@ public SecurityFilterChain authSecurityFilterChain(HttpSecurity http) throws Exc // disable session for token requests .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); - // allow cors + // always allow cors securityChain.cors(cors -> { - if (StringUtils.hasText(corsOrigins)) { - cors.configurationSource(corsConfigurationSource(corsOrigins)); - } else { - cors.disable(); - } + cors.configurationSource(corsConfigurationSource("*")); }); //enable anonymous auth, we'll double check auth in granters @@ -232,6 +228,49 @@ public SecurityFilterChain authSecurityFilterChain(HttpSecurity http) throws Exc return securityChain.build(); } + @Bean("userinfoSecurityFilterChain") + public SecurityFilterChain userinfoSecurityFilterChain(HttpSecurity http) throws Exception { + //userinfo chain + HttpSecurity securityChain = http + .securityMatcher(new AntPathRequestMatcher("/auth/userinfo")) + .authorizeHttpRequests(auth -> { + auth.requestMatchers(getAuthRequestMatcher()).hasRole("USER").anyRequest().authenticated(); + }) + // disable request cache + .requestCache(requestCache -> requestCache.disable()) + //disable csrf + .csrf(csrf -> csrf.disable()) + // disable session + .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + + // always allow cors + securityChain.cors(cors -> { + cors.configurationSource(corsConfigurationSource("*")); + }); + + //disable anonymous auth + securityChain.anonymous(anon -> anon.disable()); + + //authentication (when configured) + if (properties.isOidcAuthEnabled() && jwtTokenService != null) { + // enable internal jwt auth provider + JwtAuthenticationProvider coreJwtAuthProvider = new JwtAuthenticationProvider(jwtTokenService.getDecoder()); + coreJwtAuthProvider.setJwtAuthenticationConverter(jwtTokenService.getAuthenticationConverter()); + UserAuthenticationManager authManager = authenticationManagerBuilder.build(coreJwtAuthProvider); + + securityChain.authenticationManager(authManager); + securityChain.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.authenticationManager(authManager))); + } + + securityChain.exceptionHandling(handling -> { + handling + .authenticationEntryPoint(new Http403ForbiddenEntryPoint()) + .accessDeniedHandler(new AccessDeniedHandlerImpl()); // use 403 + }); + + return securityChain.build(); + } + @Bean("authorizeSecurityFilterChain") public SecurityFilterChain authorizeSecurityFilterChain(HttpSecurity http) throws Exception { //token chain @@ -314,6 +353,28 @@ public SecurityFilterChain authorizeSecurityFilterChain(HttpSecurity http) throw return securityChain.build(); } + @Bean("wellKnownSecurityFilterChain") + public SecurityFilterChain wellKnownSecurityFilterChain(HttpSecurity http) throws Exception { + return http + .securityMatcher(new AntPathRequestMatcher("/.well-known/**")) + .authorizeHttpRequests(auth -> { + auth.anyRequest().permitAll(); + }) + // disable request cache + .requestCache(requestCache -> requestCache.disable()) + //disable csrf + .csrf(csrf -> csrf.disable()) + // we don't want a session for these endpoints, each request should be evaluated + .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + // enable frame options + .headers(headers -> headers.frameOptions(frame -> frame.sameOrigin())) + // always allow cors + .cors(cors -> { + cors.configurationSource(corsConfigurationSource("*")); + }) + .build(); + } + @Bean("h2SecurityFilterChain") public SecurityFilterChain h2SecurityFilterChain(HttpSecurity http) throws Exception { return http diff --git a/application/src/main/resources/application.yml b/application/src/main/resources/application.yml index 8e7dcde0..8a2746c2 100644 --- a/application/src/main/resources/application.yml +++ b/application/src/main/resources/application.yml @@ -244,7 +244,7 @@ jwt: duration: ${JWT_REFRESH_TOKEN_DURATION:} client-id: ${JWT_CLIENT_ID:${security.basic.username}} client-secret: ${JWT_CLIENT_SECRET:${security.basic.password}} - redirect-uris: ${JWT_REDIRECT_URIS:http://localhost:*,${application.endpoint}} + redirect-uris: ${JWT_REDIRECT_URIS:http://localhost:*,${application.endpoint}/console/auth-callback} cache-control: ${JWKS_CACHE_CONTROL:public, max-age=900, must-revalidate, no-transform} diff --git a/frontend/src/main/java/it/smartcommunitylabdhub/console/controllers/ConsoleController.java b/frontend/src/main/java/it/smartcommunitylabdhub/console/controllers/ConsoleController.java index 40b20df1..2650ec29 100644 --- a/frontend/src/main/java/it/smartcommunitylabdhub/console/controllers/ConsoleController.java +++ b/frontend/src/main/java/it/smartcommunitylabdhub/console/controllers/ConsoleController.java @@ -36,6 +36,9 @@ public class ConsoleController { @Value("${solr.url}") private String solrUrl; + @Value("${jwt.client-id}") + private String clientId; + public static final String CONSOLE_CONTEXT = Keys.CONSOLE_CONTEXT; @GetMapping(value = { "/", CONSOLE_CONTEXT }) @@ -79,11 +82,11 @@ public String console(Model model, HttpServletRequest request) { if (securityProperties.isOidcAuthEnabled()) { config.put("REACT_APP_AUTH_URL", "/api"); config.put("REACT_APP_LOGIN_URL", "/auth"); - config.put("REACT_APP_ISSUER_URI", securityProperties.getOidc().getIssuerUri()); - config.put("REACT_APP_CLIENT_ID", securityProperties.getOidc().getClientId()); - if (securityProperties.getOidc().getScope() != null) { - config.put("REACT_APP_SCOPE", String.join(" ", securityProperties.getOidc().getScope())); - } + config.put("REACT_APP_ISSUER_URI", applicationUrl); + config.put("REACT_APP_CLIENT_ID", clientId); + // if (securityProperties.getOidc().getScope() != null) { + // config.put("REACT_APP_SCOPE", String.join(" ", securityProperties.getOidc().getScope())); + // } } config.put("REACT_APP_ENABLE_SOLR", String.valueOf(StringUtils.hasText(solrUrl))); diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/OAuth2ConfigurationEndpoint.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/OAuth2ConfigurationEndpoint.java index 1ec18cf6..df7feba0 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/OAuth2ConfigurationEndpoint.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/OAuth2ConfigurationEndpoint.java @@ -1,22 +1,27 @@ package it.smartcommunitylabdhub.authorization.controllers; +import it.smartcommunitylabdhub.authorization.model.OpenIdConfig; +import it.smartcommunitylabdhub.authorization.model.OpenIdConfig.OpenIdConfigBuilder; import it.smartcommunitylabdhub.commons.config.ApplicationProperties; import it.smartcommunitylabdhub.commons.config.SecurityProperties; -import java.util.Collections; -import java.util.HashMap; +import it.smartcommunitylabdhub.commons.infrastructure.ConfigurationProvider; +import java.io.Serializable; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Stream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController -public class OAuth2ConfigurationEndpoint { +public class OAuth2ConfigurationEndpoint implements ConfigurationProvider { @Autowired private ApplicationProperties applicationProperties; @@ -27,10 +32,10 @@ public class OAuth2ConfigurationEndpoint { @Value("${jwt.cache-control}") private String cacheControl; - private Map config = null; + private OpenIdConfig config = null; @GetMapping(value = { "/.well-known/openid-configuration", "/.well-known/oauth-authorization-server" }) - public ResponseEntity> getCOnfiguration() { + public ResponseEntity> getConfiguration() { if (!securityProperties.isRequired()) { throw new UnsupportedOperationException(); } @@ -39,32 +44,63 @@ public ResponseEntity> getCOnfiguration() { config = generate(); } - return ResponseEntity.ok().header(HttpHeaders.CACHE_CONTROL, cacheControl).body(config); + return ResponseEntity.ok().header(HttpHeaders.CACHE_CONTROL, cacheControl).body(config.toMap()); } - private Map generate() { + private OpenIdConfig generate() { /* * OpenID Provider Metadata * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata */ String baseUrl = applicationProperties.getEndpoint(); - Map m = new HashMap<>(); + OpenIdConfigBuilder builder = OpenIdConfig.builder(); - m.put("issuer", baseUrl); - m.put("jwks_uri", baseUrl + JWKSEndpoint.JWKS_URL); - m.put("response_types_supported", Collections.emptyList()); + builder.issuer(baseUrl); + builder.jwksUri(baseUrl + JWKSEndpoint.JWKS_URL); + builder.responseTypesSupported(Set.of("code")); List grantTypes = Stream - .of(AuthorizationGrantType.CLIENT_CREDENTIALS, AuthorizationGrantType.REFRESH_TOKEN) + .of( + AuthorizationGrantType.CLIENT_CREDENTIALS, + AuthorizationGrantType.REFRESH_TOKEN, + AuthorizationGrantType.TOKEN_EXCHANGE + ) .map(t -> t.getValue()) .toList(); - m.put("grant_types_supported", grantTypes); - m.put("token_endpoint", baseUrl + TokenEndpoint.TOKEN_URL); - List authMethods = Collections.singletonList("client_secret_basic"); - m.put("token_endpoint_auth_methods_supported", authMethods); + if (securityProperties.isOidcAuthEnabled()) { + grantTypes = + Stream + .of( + AuthorizationGrantType.CLIENT_CREDENTIALS, + AuthorizationGrantType.REFRESH_TOKEN, + AuthorizationGrantType.AUTHORIZATION_CODE, + AuthorizationGrantType.TOKEN_EXCHANGE + ) + .map(t -> t.getValue()) + .toList(); - return m; + builder.authorizationEndpoint(baseUrl + AuthorizationEndpoint.AUTHORIZE_URL); + builder.userinfoEndpoint(baseUrl + UserInfoEndpoint.USERINFO_URL); + } + + builder.grantTypesSupported(new HashSet<>(grantTypes)); + + builder.tokenEndpoint(baseUrl + TokenEndpoint.TOKEN_URL); + Set authMethods = Set.of("client_secret_basic", "client_secret_post", "none"); + builder.tokenEndpointAuthMethodsSupported(authMethods); + + return builder.build(); + } + + @Override + @Nullable + public OpenIdConfig getConfig() { + if (config == null) { + config = generate(); + } + + return config; } } diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/UserInfoEndpoint.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/UserInfoEndpoint.java new file mode 100644 index 00000000..51361d8f --- /dev/null +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/controllers/UserInfoEndpoint.java @@ -0,0 +1,86 @@ +/** + * Copyright 2025 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package it.smartcommunitylabdhub.authorization.controllers; + +import com.nimbusds.jwt.SignedJWT; +import it.smartcommunitylabdhub.authorization.model.UserAuthentication; +import it.smartcommunitylabdhub.authorization.services.JwtTokenService; +import it.smartcommunitylabdhub.commons.config.SecurityProperties; +import java.text.ParseException; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.annotation.CurrentSecurityContext; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +public class UserInfoEndpoint { + + public static final String USERINFO_URL = "/auth/userinfo"; + + @Autowired + private SecurityProperties securityProperties; + + @Autowired(required = false) + private JwtTokenService jwtTokenService; + + @RequestMapping(value = USERINFO_URL, method = { RequestMethod.POST, RequestMethod.GET }) + public Map userinfo( + @RequestParam Map parameters, + @CurrentSecurityContext SecurityContext securityContext + ) { + if (!securityProperties.isOidcAuthEnabled() || jwtTokenService == null) { + throw new UnsupportedOperationException(); + } + + Authentication authentication = securityContext.getAuthentication(); + + //resolve user authentication + if ( + authentication == null || + !(authentication.isAuthenticated()) || + !(authentication instanceof UserAuthentication) + ) { + throw new InsufficientAuthenticationException("Invalid or missing authentication"); + } + try { + UserAuthentication user = (UserAuthentication) authentication; + log.debug("read userinfo for {}", user.getUsername()); + + //fetch token + SignedJWT token = jwtTokenService.generateAccessToken(user); + Map claims; + + claims = token.getJWTClaimsSet().getClaims(); + + if (log.isTraceEnabled()) { + log.trace("userinfo: {}", claims); + } + + return claims; + } catch (ParseException e) { + throw new IllegalArgumentException(); + } + } +} diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/grants/AuthorizationCodeGranter.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/grants/AuthorizationCodeGranter.java index 20c84ba2..96c74f1b 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/grants/AuthorizationCodeGranter.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/grants/AuthorizationCodeGranter.java @@ -124,11 +124,6 @@ public TokenResponse grant(@NotNull Map parameters, Authenticati throw new IllegalArgumentException("Invalid or missing code"); } - String state = parameters.get(OAuth2ParameterNames.STATE); - if (state == null) { - throw new IllegalArgumentException("invalid or missing state"); - } - //secret auth String cid = parameters.get(OAuth2ParameterNames.CLIENT_ID); if (cid == null || !clientId.equals(cid)) { @@ -153,7 +148,6 @@ public TokenResponse grant(@NotNull Map parameters, Authenticati .code(code) .redirectUri(redirectUri) .codeVerifier(codeVerifier) - .state(state) .build(); if (log.isTraceEnabled()) { diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/OpenIdConfig.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/OpenIdConfig.java new file mode 100644 index 00000000..a8a17f05 --- /dev/null +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/OpenIdConfig.java @@ -0,0 +1,62 @@ +/** + * Copyright 2025 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package it.smartcommunitylabdhub.authorization.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import it.smartcommunitylabdhub.commons.infrastructure.AbstractConfiguration; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OpenIdConfig extends AbstractConfiguration { + + @JsonProperty("issuer") + private String issuer; + + @JsonProperty("jwks_uri") + private String jwksUri; + + @JsonProperty("authorization_endpoint") + private String authorizationEndpoint; + + @JsonProperty("userinfo_endpoint") + private String userinfoEndpoint; + + @JsonProperty("token_endpoint") + private String tokenEndpoint; + + @JsonProperty("token_endpoint_auth_methods_supported") + private Set tokenEndpointAuthMethodsSupported; + + @JsonProperty("response_types_supported") + private Set responseTypesSupported; + + @JsonProperty("grant_types_supported") + private Set grantTypesSupported; +} diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/TokenRequest.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/TokenRequest.java index 7dd85c63..79765406 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/TokenRequest.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/model/TokenRequest.java @@ -43,9 +43,6 @@ public class TokenRequest { @JsonProperty("code_verifier") private String codeVerifier; - @JsonProperty("state") - private String state; - @JsonProperty("code") private String code; } diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentials.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentials.java index af0f9118..635f1ff7 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentials.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentials.java @@ -46,6 +46,9 @@ public class CoreCredentials extends AbstractCredentials { @JsonProperty("access_token") private SignedJWT accessToken; + @JsonProperty("id_token") + private SignedJWT idToken; + @JsonProperty("refresh_token") private String refreshToken; @@ -70,4 +73,9 @@ private String getProjectsAsString() { public String getAccessToken() { return accessToken != null ? accessToken.serialize() : null; } + + @JsonGetter("id_token") + public String getIdToken() { + return idToken != null ? idToken.serialize() : null; + } } diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsConfig.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsConfig.java index cd340639..a93fd7fd 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsConfig.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsConfig.java @@ -42,30 +42,4 @@ public class CoreCredentialsConfig extends AbstractConfiguration { //basic auth @JsonProperty("realm") private String realm; - - // oauth2 - - @JsonProperty("issuer") - private String issuer; - - @JsonProperty("client_id") - private String clientId; - - @JsonProperty("jwks_uri") - private String jwksUri; - - @JsonProperty("authorization_endpoint") - private String authorizationEndpoint; - - @JsonProperty("token_endpoint") - private String tokenEndpoint; - - @JsonProperty("token_endpoint_auth_methods_supported") - private Set tokenEndpointAuthMethodsSupported; - - @JsonProperty("response_types_supported") - private Set responseTypesSupported; - - @JsonProperty("grant_types_supported") - private Set grantTypesSupported; } diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsProvider.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsProvider.java index 7272ac75..fd4f7ecd 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsProvider.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/providers/CoreCredentialsProvider.java @@ -17,8 +17,6 @@ package it.smartcommunitylabdhub.authorization.providers; import com.nimbusds.jwt.SignedJWT; -import it.smartcommunitylabdhub.authorization.controllers.JWKSEndpoint; -import it.smartcommunitylabdhub.authorization.controllers.TokenEndpoint; import it.smartcommunitylabdhub.authorization.model.UserAuthentication; import it.smartcommunitylabdhub.authorization.providers.CoreCredentials.CoreCredentialsBuilder; import it.smartcommunitylabdhub.authorization.providers.CoreCredentialsConfig.CoreCredentialsConfigBuilder; @@ -71,18 +69,12 @@ public CoreCredentialsProvider( //basic if (security.isBasicAuthEnabled()) { authMethods.add("basic"); - builder.realm(baseUrl); } //oauth2 if (security.isJwtAuthEnabled()) { authMethods.add("jwt"); - - builder.issuer(properties.getEndpoint()); - builder.clientId(jwtTokenService.getClientId()); - builder.jwksUri(baseUrl + JWKSEndpoint.JWKS_URL); - builder.tokenEndpoint(baseUrl + TokenEndpoint.TOKEN_URL); } if (security.isOidcAuthEnabled()) { @@ -127,6 +119,7 @@ public CoreCredentials get(@NotNull UserAuthentication auth) { .builder() .accessToken(accessToken) .refreshToken(refreshToken) + .idToken(accessToken) .expiration(exp) .clientId(jwtTokenService.getClientId()) .issuer(jwtTokenService.getIssuer()); diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/repositories/AuthorizationRequestStore.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/repositories/AuthorizationRequestStore.java index 53677fce..1bb8a354 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/repositories/AuthorizationRequestStore.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/repositories/AuthorizationRequestStore.java @@ -83,12 +83,12 @@ public void remove(String key) { } private String extractKey(AuthorizationRequest request) { - //we use state+clientId+redirect as key because we receive those from token request as well - return request.getState() + "|" + request.getClientId() + "|" + request.getRedirectUri(); + //we use clientId+redirect as key because we receive those from token request as well + return request.getClientId() + "|" + request.getRedirectUri(); } private String extractKey(TokenRequest request) { - //we use state+clientId+redirect as key because we receive those from token request as well - return request.getState() + "|" + request.getClientId() + "|" + request.getRedirectUri(); + //we use clientId+redirect as key because we receive those from token request as well + return request.getClientId() + "|" + request.getRedirectUri(); } } diff --git a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/services/JwtTokenService.java b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/services/JwtTokenService.java index d960f289..a2fb3eb9 100644 --- a/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/services/JwtTokenService.java +++ b/modules/authorization/src/main/java/it/smartcommunitylabdhub/authorization/services/JwtTokenService.java @@ -46,6 +46,8 @@ import org.springframework.security.crypto.keygen.StringKeyGenerator; import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidator; +import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; +import org.springframework.security.oauth2.core.oidc.StandardClaimNames; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtClaimNames; import org.springframework.security.oauth2.jwt.JwtClaimValidator; @@ -218,6 +220,7 @@ public SignedJWT generateAccessToken(@NotNull UserAuthentication authenticati .audience(audience) .jwtID(keyGenerator.generateKey()) .expirationTime(Date.from(now.plusSeconds(accessTokenDuration))); + claims.claim(StandardClaimNames.PREFERRED_USERNAME, authentication.getUsername()); //define authorities as claims List authorities = authentication