From 192e1b726faadd07004dbdf0f5a8b57501815262 Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Fri, 5 Jul 2019 17:28:00 +0200 Subject: [PATCH] Made OIDC flow working --- gms/pom.xml | 4 ++ .../ia2/gms/CustomAuthenticationData.java | 20 ++++++ .../inaf/ia2/gms/CustomIdTokenConverter.java | 36 ++++++++++ .../java/it/inaf/ia2/gms/GmsApplication.java | 22 ------ .../java/it/inaf/ia2/gms/LoginController.java | 6 +- .../java/it/inaf/ia2/gms/OAuth2Config.java | 68 +++++++++++++++++++ gms/src/main/resources/application.properties | 6 +- 7 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 gms/src/main/java/it/inaf/ia2/gms/CustomAuthenticationData.java create mode 100644 gms/src/main/java/it/inaf/ia2/gms/CustomIdTokenConverter.java create mode 100644 gms/src/main/java/it/inaf/ia2/gms/OAuth2Config.java diff --git a/gms/pom.xml b/gms/pom.xml index 1aeca7e..6ab11e6 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 0000000..49d9fbc --- /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 0000000..beabbe5 --- /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 a4f87c4..5833724 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 9b63328..e94ecfe 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 0000000..c823502 --- /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 b2167d9..f256cf2 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 -- GitLab