Skip to content

Commit

Permalink
Merge pull request #1 from jzheaux/spring-projectsgh-14186
Browse files Browse the repository at this point in the history
Polish Custom Username Location
  • Loading branch information
ahmd-nabil committed Jan 19, 2024
2 parents 91e2203 + 00493dc commit 3dfafbb
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 235 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2020 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.
Expand All @@ -24,7 +24,6 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
Expand All @@ -38,7 +37,6 @@
* @see OAuth2ClientJackson2Module
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonDeserialize(using = DefaultOAuth2UserDeserializer.class)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
Expand All @@ -50,10 +48,4 @@ abstract class DefaultOAuth2UserMixin {
@JsonProperty("nameAttributeKey") String nameAttributeKey) {
}

@JsonCreator
DefaultOAuth2UserMixin(@JsonProperty("attributes") Map<String, Object> attributes,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
@JsonProperty("name") String name) {
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2020 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.
Expand All @@ -23,7 +23,6 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
Expand All @@ -39,7 +38,6 @@
* @see OAuth2ClientJackson2Module
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonDeserialize(using = DefaultOidcUserDeserializer.class)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(value = { "attributes" }, ignoreUnknown = true)
Expand All @@ -51,10 +49,4 @@ abstract class DefaultOidcUserMixin {
@JsonProperty("nameAttributeKey") String nameAttributeKey) {
}

@JsonCreator
DefaultOidcUserMixin(@JsonProperty("idToken") OidcIdToken idToken, @JsonProperty("userInfo") OidcUserInfo userInfo,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
@JsonProperty("name") String name) {
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2020 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.
Expand All @@ -16,16 +16,13 @@

package org.springframework.security.oauth2.client.jackson2;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.security.core.GrantedAuthority;

/**
* Utility class for {@code JsonNode}.
*
Expand All @@ -40,9 +37,6 @@ abstract class JsonNodeUtils {
static final TypeReference<Map<String, Object>> STRING_OBJECT_MAP = new TypeReference<Map<String, Object>>() {
};

static final TypeReference<Collection<? extends GrantedAuthority>> GRANTED_AUTHORITY_COLLECTION = new TypeReference<Collection<? extends GrantedAuthority>>() {
};

static String findStringValue(JsonNode jsonNode, String fieldName) {
if (jsonNode == null) {
return null;
Expand All @@ -68,12 +62,4 @@ static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) {
return (value != null && value.isObject()) ? value : null;
}

static <T> T findValueByPath(JsonNode jsonNode, String path, Class<T> type, ObjectMapper mapper) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.path(path);
return (value != null && !value.isMissingNode()) ? mapper.convertValue(value, type) : null;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
Expand All @@ -20,12 +20,8 @@
import java.util.LinkedHashSet;
import java.util.Map;

import org.springframework.context.expression.MapAccessor;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.convert.converter.Converter;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.GrantedAuthority;
Expand Down Expand Up @@ -80,7 +76,8 @@ public class DefaultOAuth2UserService implements OAuth2UserService<OAuth2UserReq

private Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();

private final SpelExpressionParser parser = new SpelExpressionParser();
private Converter<OAuth2UserRequest, Converter<Map<String, Object>, Map<String, Object>>> attributesConverter = (
request) -> (attributes) -> attributes;

private RestOperations restOperations;

Expand All @@ -97,10 +94,35 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic
RequestEntity<?> request = this.requestEntityConverter.convert(userRequest);
ResponseEntity<Map<String, Object>> response = getResponse(userRequest, request);
OAuth2AccessToken token = userRequest.getAccessToken();
Map<String, Object> attributes = response.getBody();
Map<String, Object> attributes = this.attributesConverter.convert(userRequest).convert(response.getBody());
Collection<GrantedAuthority> authorities = getAuthorities(token, attributes);
String name = getName(attributes, userNameAttributeName);
return new DefaultOAuth2User(attributes, authorities, name);
return new DefaultOAuth2User(authorities, attributes, userNameAttributeName);
}

/**
* Use this strategy to adapt user attributes into a format understood by Spring
* Security; by default, the original attributes are preserved.
*
* <p>
* This can be helpful, for example, if the user attribute is nested. Since Spring
* Security needs the username attribute to be at the top level, you can use this
* method to do:
*
* <pre>
* DefaultOAuth2UserService userService = new DefaultOAuth2UserService();
* userService.setAttributesConverter((userRequest) -> (attributes) ->
* Map&lt;String, Object&gt; userObject = (Map&lt;String, Object&gt;) attributes.get("user");
* attributes.put("user-name", userObject.get("user-name"));
* return attributes;
* });
* </pre>
* @param attributesConverter the attribute adaptation strategy to use
* @since 6.3
*/
public void setAttributesConverter(
Converter<OAuth2UserRequest, Converter<Map<String, Object>, Map<String, Object>>> attributesConverter) {
Assert.notNull(attributesConverter, "attributesConverter cannot be null");
this.attributesConverter = attributesConverter;
}

private ResponseEntity<Map<String, Object>> getResponse(OAuth2UserRequest userRequest, RequestEntity<?> request) {
Expand Down Expand Up @@ -174,16 +196,6 @@ private Collection<GrantedAuthority> getAuthorities(OAuth2AccessToken token, Map
return authorities;
}

private String getName(Map<String, Object> attributes, String userNameAttributeName) {
Assert.notEmpty(attributes, "attributes cannot be empty");
Assert.hasText(userNameAttributeName, "userNameAttributeName cannot be empty");
SimpleEvaluationContext context = SimpleEvaluationContext.forPropertyAccessors(new MapAccessor())
.withRootObject(attributes)
.build();
Expression expression = this.parser.parseExpression(userNameAttributeName);
return expression.getValue(context, String.class);
}

/**
* Sets the {@link Converter} used for converting the {@link OAuth2UserRequest} to a
* {@link RequestEntity} representation of the UserInfo Request.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -36,6 +36,7 @@
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.authentication.TestOAuth2AuthenticationTokens;
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
Expand Down Expand Up @@ -193,7 +194,7 @@ private static String asJson(DefaultOAuth2User oauth2User) {
" \"@class\": \"java.util.Collections$UnmodifiableMap\",\n" +
" \"username\": \"user\"\n" +
" },\n" +
" \"name\": \"user\"\n" +
" \"nameAttributeKey\": \"username\"\n" +
" }";
// @formatter:on
}
Expand All @@ -205,7 +206,7 @@ private static String asJson(DefaultOidcUser oidcUser) {
" \"authorities\": " + asJson(oidcUser.getAuthorities(), "java.util.Collections$UnmodifiableSet") + ",\n" +
" \"idToken\": " + asJson(oidcUser.getIdToken()) + ",\n" +
" \"userInfo\": " + asJson(oidcUser.getUserInfo()) + ",\n" +
" \"name\": \"" + oidcUser.getName() + "\"\n" +
" \"nameAttributeKey\": \"" + IdTokenClaimNames.SUB + "\"\n" +
" }";
// @formatter:on
}
Expand Down

0 comments on commit 3dfafbb

Please sign in to comment.