diff --git a/gms/pom.xml b/gms/pom.xml index 1aeca7e3cca1ed0ef04ac3180b1ba8bdee8a6c84..6ab11e6f5f79ce17a038a8086bb3bd6ee3bf7ba8 100644 --- a/gms/pom.xml +++ b/gms/pom.xml @@ -28,6 +28,10 @@ <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>${project.parent.version}</version> </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-oauth2-client</artifactId> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> diff --git a/gms/src/main/java/it/inaf/ia2/gms/CustomAuthenticationData.java b/gms/src/main/java/it/inaf/ia2/gms/CustomAuthenticationData.java new file mode 100644 index 0000000000000000000000000000000000000000..49d9fbcb5fd5600471369c48bb216a28356d3682 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/CustomAuthenticationData.java @@ -0,0 +1,20 @@ +package it.inaf.ia2.gms; + +import java.util.Collection; +import java.util.Map; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +public class CustomAuthenticationData extends UsernamePasswordAuthenticationToken { + + private final Map<String, Object> attributes; + + public CustomAuthenticationData(String username, Map<String, Object> attributes, Collection<? extends GrantedAuthority> authorities) { + super(username, "N/A", authorities); + this.attributes = attributes; + } + + public Map<String, Object> getAttributes() { + return attributes; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/CustomIdTokenConverter.java b/gms/src/main/java/it/inaf/ia2/gms/CustomIdTokenConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..beabbe56b934ecb7d18ffc375f477c1c3df33e16 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/CustomIdTokenConverter.java @@ -0,0 +1,36 @@ +package it.inaf.ia2.gms; + +import java.util.List; +import java.util.Map; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter; +import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore; + +public class CustomIdTokenConverter extends DefaultUserAuthenticationConverter { + + private final JwkTokenStore jwkTokenStore; + + public CustomIdTokenConverter(String keySetUri) { + this.jwkTokenStore = new JwkTokenStore(keySetUri); + } + + @Override + public Authentication extractAuthentication(Map<String, ?> map) { + + String idToken = (String) map.get("id_token"); + + OAuth2AccessToken token = jwkTokenStore.readAccessToken(idToken); + + Map<String, Object> claims = token.getAdditionalInformation(); + //OAuth2RefreshToken refreshToken = token.getRefreshToken(); + + String principal = (String) claims.get("sub"); + + List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); + + return new CustomAuthenticationData(principal, claims, authorities); + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/GmsApplication.java b/gms/src/main/java/it/inaf/ia2/gms/GmsApplication.java index a4f87c4282a0ab45526b6df2e2e17badb9b6ea10..583372471d738a43a2dd4ba8892a45e1ec35faac 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/GmsApplication.java +++ b/gms/src/main/java/it/inaf/ia2/gms/GmsApplication.java @@ -1,34 +1,12 @@ package it.inaf.ia2.gms; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; -import org.springframework.context.annotation.Bean; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore; @SpringBootApplication -@EnableOAuth2Sso public class GmsApplication { public static void main(String[] args) { SpringApplication.run(GmsApplication.class, args); } - - @Value("${security.oauth2.resource.jwk.key-set-uri}") - private String keySetUri; - - @Bean - public TokenStore tokenStore() { - JwkTokenStore jwkTokenStore = new JwkTokenStore(keySetUri, accessTokenConverter()); - return jwkTokenStore; - } - - @Bean - public JwtAccessTokenConverter accessTokenConverter() { - JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); - return converter; - } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/LoginController.java b/gms/src/main/java/it/inaf/ia2/gms/LoginController.java index 9b63328a25da49f2080b28af05e442715764d366..e94ecfea291ad9aee9415f530754b37dd5f7bb03 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/LoginController.java +++ b/gms/src/main/java/it/inaf/ia2/gms/LoginController.java @@ -1,6 +1,7 @@ package it.inaf.ia2.gms; import java.security.Principal; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -11,9 +12,8 @@ public class LoginController { public Principal start(Principal principal) { return principal; } - - - @GetMapping("/") + + @GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public Principal root(Principal principal) { return principal; } diff --git a/gms/src/main/java/it/inaf/ia2/gms/OAuth2Config.java b/gms/src/main/java/it/inaf/ia2/gms/OAuth2Config.java new file mode 100644 index 0000000000000000000000000000000000000000..c823502a5fd94c590626233c0f9a23bffad3d734 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/OAuth2Config.java @@ -0,0 +1,68 @@ +package it.inaf.ia2.gms; + +import java.util.List; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; +import org.springframework.boot.autoconfigure.security.oauth2.resource.DefaultUserInfoRestTemplateFactory; +import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateCustomizer; +import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.RemoteTokenServices; + +/** + * Extending the AuthorizationServerEndpointsConfiguration disables the Spring + * Boot ResourceServerTokenServicesConfiguration. + */ +@Configuration +@EnableOAuth2Sso +public class OAuth2Config extends AuthorizationServerEndpointsConfiguration { + + @Value("${security.oauth2.resource.jwk.key-set-uri}") + private String keySetUri; + + @Value("${security.oauth2.resource.token-info-uri}") + private String checkTokenEndpointUrl; + + @Value("${security.oauth2.client.client-id}") + private String clientId; + + @Value("${security.oauth2.client.client-secret}") + private String clientSecret; + + @Bean + public RemoteTokenServices resourceServerTokenServices() { + RemoteTokenServices tokenService = new RemoteTokenServices(); + + DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); + accessTokenConverter.setUserTokenConverter(new CustomIdTokenConverter(keySetUri)); + tokenService.setAccessTokenConverter(accessTokenConverter); + + tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl); + tokenService.setClientId(clientId); + tokenService.setClientSecret(clientSecret); + + return tokenService; + } + + @Bean + public ClientDetailsService clientDetailsService() { + return new InMemoryClientDetailsService(); + } + + @Bean + public UserInfoRestTemplateFactory userInfoRestTemplateFactory( + ObjectProvider<List<UserInfoRestTemplateCustomizer>> customizers, + ObjectProvider<OAuth2ProtectedResourceDetails> details, + ObjectProvider<OAuth2ClientContext> oauth2ClientContext) { + return new DefaultUserInfoRestTemplateFactory(customizers, details, + oauth2ClientContext); + } +} diff --git a/gms/src/main/resources/application.properties b/gms/src/main/resources/application.properties index b2167d98813c451edc2d3398e3d5ddb58d432c72..f256cf2f8f3dde5482e978eff9743de529d1e228 100644 --- a/gms/src/main/resources/application.properties +++ b/gms/src/main/resources/application.properties @@ -4,8 +4,8 @@ security.oauth2.client.client-id=gms security.oauth2.client.client-secret=gms-secret security.oauth2.client.access-token-uri=http://localhost/rap-ia2/auth/oauth2/token security.oauth2.client.user-authorization-uri=http://localhost/rap-ia2/auth/oauth2/authorize -#security.oauth2.resource.token-info-uri=http://localhost/rap-ia2/auth/oauth2/check_token -security.oauth2.client.scope=email,profile +security.oauth2.resource.token-info-uri=http://localhost/rap-ia2/auth/oauth2/check_token +security.oauth2.client.scope=openid,email,profile security.oauth2.resource.jwk.key-set-uri=http://localhost/rap-ia2/auth/oidc/jwks -logging.level.org.springframework.security=DEBUG +logging.level.org.springframework.security=DEBUG \ No newline at end of file