diff --git a/src/main/java/se/su/dsv/seshat/TokenIntrospectionRequestEntityConverter.java b/src/main/java/se/su/dsv/seshat/TokenIntrospectionRequestEntityConverter.java new file mode 100644 index 0000000..794b84a --- /dev/null +++ b/src/main/java/se/su/dsv/seshat/TokenIntrospectionRequestEntityConverter.java @@ -0,0 +1,42 @@ +package se.su.dsv.seshat; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import java.net.URI; +import java.util.Collections; + +public class TokenIntrospectionRequestEntityConverter implements Converter<OAuth2UserRequest, RequestEntity<?>> { + private static final MediaType FORM_URL_ENCODED = MediaType.valueOf( + MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8" + ); + + @Override + public RequestEntity<?> convert(OAuth2UserRequest userRequest) { + ClientRegistration clientRegistration = userRequest.getClientRegistration(); + + URI uri = UriComponentsBuilder.fromUriString( + clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri() + ) + .build() + .toUri(); + + HttpHeaders headers = new HttpHeaders(); + headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret()); + headers.setAccept(Collections.singletonList(MediaType.ALL)); + headers.setContentType(FORM_URL_ENCODED); + + MultiValueMap<String, String> formParameters = new LinkedMultiValueMap<>(); + formParameters.add(OAuth2ParameterNames.TOKEN, userRequest.getAccessToken().getTokenValue()); + return new RequestEntity<>(formParameters, headers, HttpMethod.POST, uri); + } +} diff --git a/src/main/java/se/su/dsv/seshat/configuration/SeshatConfiguration.java b/src/main/java/se/su/dsv/seshat/configuration/SeshatConfiguration.java new file mode 100644 index 0000000..c37b80d --- /dev/null +++ b/src/main/java/se/su/dsv/seshat/configuration/SeshatConfiguration.java @@ -0,0 +1,25 @@ +package se.su.dsv.seshat.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import se.su.dsv.seshat.TokenIntrospectionRequestEntityConverter; + +@Configuration +public class SeshatConfiguration { + + // Stop gap measure to switch to Token Introspection instead of OIDC UserInfo + // endpoint. This is necessary because the UserInfo endpoint will in soon require + // the "openid" scope, which is not granted to our clients. Unfortunately we can't + // request the scope because that makes Spring require an id token in the token + // exchange which is not granted at the moment. + // + // Once a new authorization server is in place we can remove this bean and use + // straight up id tokens with "openid" scope. + @Bean + public DefaultOAuth2UserService defaultOAuth2UserService() { + DefaultOAuth2UserService defaultOAuth2UserService = new DefaultOAuth2UserService(); + defaultOAuth2UserService.setRequestEntityConverter(new TokenIntrospectionRequestEntityConverter()); + return defaultOAuth2UserService; + } +} diff --git a/src/main/java/se/su/dsv/seshat/services/CustomOAuth2loginSuccessHandler.java b/src/main/java/se/su/dsv/seshat/services/CustomOAuth2loginSuccessHandler.java index b1cb137..805ac55 100644 --- a/src/main/java/se/su/dsv/seshat/services/CustomOAuth2loginSuccessHandler.java +++ b/src/main/java/se/su/dsv/seshat/services/CustomOAuth2loginSuccessHandler.java @@ -35,7 +35,7 @@ public class CustomOAuth2loginSuccessHandler implements AuthenticationSuccessHan String email = oAuth2User.getAttribute("mail") != null ? oAuth2User.getAttribute("mail") : "no-email"; - if(!userService.existsByUsername(oAuth2User.getAttribute("principal"))) { + if(!userService.existsByUsername(username)) { userService.registerUser(username, email); } response.sendRedirect(redirectUrl); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index cbca5ec..b200329 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -32,7 +32,7 @@ spring.jpa.show-sql=false # OAuth2 properties, remember if you change the registration.provider the provider properties must be updated spring.security.oauth2.client.provider.docker.authorization-uri=http://localhost:51337/authorize spring.security.oauth2.client.provider.docker.token-uri=http://localhost:51337/exchange -spring.security.oauth2.client.provider.docker.user-info-uri=http://localhost:51337/verify +spring.security.oauth2.client.provider.docker.user-info-uri=http://localhost:51337/introspect spring.security.oauth2.client.provider.docker.user-name-attribute=sub spring.security.oauth2.client.registration.seshat.client-id=seshat spring.security.oauth2.client.registration.seshat.client-secret=n0tS3cr3t