parent
df84826c95
commit
6c3d183a94
|
@ -47,7 +47,7 @@ class UnmodifiableMapDeserializerTests extends AbstractMixinTests {
|
|||
Collections.unmodifiableMap(Collections.emptyMap()).getClass());
|
||||
|
||||
assertThat(map).isNotNull().isInstanceOf(Collections.unmodifiableMap(Collections.emptyMap()).getClass())
|
||||
.containsAllEntriesOf(Map.of("Key", "Value"));
|
||||
.containsAllEntriesOf(Collections.singletonMap("Key", "Value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 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 org.springframework.security.saml2.jackson2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
|
||||
|
||||
/**
|
||||
* Custom deserializer for {@link DefaultSaml2AuthenticatedPrincipal}.
|
||||
*
|
||||
* @author Ulrich Grave
|
||||
* @since 5.7
|
||||
* @see DefaultSaml2AuthenticatedPrincipalMixin
|
||||
*/
|
||||
class DefaultSaml2AuthenticatedPrincipalDeserializer extends JsonDeserializer<DefaultSaml2AuthenticatedPrincipal> {
|
||||
|
||||
private static final TypeReference<List<String>> SESSION_INDICES_LIST = new TypeReference<List<String>>() {
|
||||
};
|
||||
|
||||
private static final TypeReference<Map<String, List<Object>>> ATTRIBUTES_MAP = new TypeReference<Map<String, List<Object>>>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
public DefaultSaml2AuthenticatedPrincipal deserialize(JsonParser jp, DeserializationContext ctxt)
|
||||
throws IOException {
|
||||
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
|
||||
JsonNode jsonNode = mapper.readTree(jp);
|
||||
|
||||
String name = JsonNodeUtils.findStringValue(jsonNode, "name");
|
||||
Map<String, List<Object>> attributes = JsonNodeUtils.findValue(jsonNode, "attributes", ATTRIBUTES_MAP, mapper);
|
||||
List<String> sessionIndexes = JsonNodeUtils.findValue(jsonNode, "sessionIndexes", SESSION_INDICES_LIST, mapper);
|
||||
String registrationId = JsonNodeUtils.findStringValue(jsonNode, "registrationId");
|
||||
|
||||
DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(name, attributes,
|
||||
sessionIndexes);
|
||||
if (registrationId != null) {
|
||||
principal.setRelyingPartyRegistrationId(registrationId);
|
||||
}
|
||||
return principal;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,9 +16,13 @@
|
|||
|
||||
package org.springframework.security.saml2.jackson2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
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.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
|
||||
|
@ -40,7 +44,16 @@ import org.springframework.security.saml2.provider.service.authentication.Defaul
|
|||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonDeserialize(using = DefaultSaml2AuthenticatedPrincipalDeserializer.class)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
class DefaultSaml2AuthenticatedPrincipalMixin {
|
||||
|
||||
@JsonProperty("registrationId")
|
||||
String registrationId;
|
||||
|
||||
DefaultSaml2AuthenticatedPrincipalMixin(@JsonProperty("name") String name,
|
||||
@JsonProperty("attributes") Map<String, List<Object>> attributes,
|
||||
@JsonProperty("sessionIndexes") List<String> sessionIndexes) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 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 org.springframework.security.saml2.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.MissingNode;
|
||||
|
||||
final class JsonNodeUtils {
|
||||
|
||||
private JsonNodeUtils() {
|
||||
}
|
||||
|
||||
static String findStringValue(JsonNode jsonNode, String fieldName) {
|
||||
if (jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
JsonNode value = jsonNode.findValue(fieldName);
|
||||
return (value != null && value.isTextual()) ? value.asText() : null;
|
||||
}
|
||||
|
||||
static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference,
|
||||
ObjectMapper mapper) {
|
||||
if (jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
JsonNode value = jsonNode.findValue(fieldName);
|
||||
return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null;
|
||||
}
|
||||
|
||||
static JsonNode readJsonNode(JsonNode jsonNode, String field) {
|
||||
return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2022 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 org.springframework.security.saml2.jackson2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||
|
||||
/**
|
||||
* Custom deserializer for {@link Saml2Authentication}.
|
||||
*
|
||||
* @author Ulrich Grave
|
||||
* @since 5.7
|
||||
* @see Saml2AuthenticationMixin
|
||||
*/
|
||||
class Saml2AuthenticationDeserializer extends JsonDeserializer<Saml2Authentication> {
|
||||
|
||||
private static final TypeReference<List<GrantedAuthority>> GRANTED_AUTHORITY_LIST = new TypeReference<List<GrantedAuthority>>() {
|
||||
};
|
||||
|
||||
private static final TypeReference<Object> OBJECT = new TypeReference<Object>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
public Saml2Authentication deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
|
||||
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
|
||||
JsonNode jsonNode = mapper.readTree(jp);
|
||||
|
||||
boolean authenticated = JsonNodeUtils.readJsonNode(jsonNode, "authenticated").asBoolean();
|
||||
JsonNode principalNode = JsonNodeUtils.readJsonNode(jsonNode, "principal");
|
||||
AuthenticatedPrincipal principal = getPrincipal(mapper, principalNode);
|
||||
String saml2Response = JsonNodeUtils.findStringValue(jsonNode, "saml2Response");
|
||||
List<GrantedAuthority> authorities = JsonNodeUtils.findValue(jsonNode, "authorities", GRANTED_AUTHORITY_LIST,
|
||||
mapper);
|
||||
Object details = JsonNodeUtils.findValue(jsonNode, "details", OBJECT, mapper);
|
||||
|
||||
Saml2Authentication authentication = new Saml2Authentication(principal, saml2Response, authorities);
|
||||
authentication.setAuthenticated(authenticated);
|
||||
authentication.setDetails(details);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
private AuthenticatedPrincipal getPrincipal(ObjectMapper mapper, JsonNode principalNode) throws IOException {
|
||||
return mapper.readValue(principalNode.traverse(mapper), AuthenticatedPrincipal.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,10 +16,16 @@
|
|||
|
||||
package org.springframework.security.saml2.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||
|
||||
|
@ -40,7 +46,13 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
|
|||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonDeserialize(using = Saml2AuthenticationDeserializer.class)
|
||||
@JsonIgnoreProperties(value = { "authenticated" }, ignoreUnknown = true)
|
||||
class Saml2AuthenticationMixin {
|
||||
|
||||
@JsonCreator
|
||||
Saml2AuthenticationMixin(@JsonProperty("principal") AuthenticatedPrincipal principal,
|
||||
@JsonProperty("saml2Response") String saml2Response,
|
||||
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -204,7 +204,6 @@ final class TestSaml2JsonPayloads {
|
|||
+ " \"credentialsNonExpired\": true,"
|
||||
+ " \"enabled\": true"
|
||||
+ " },"
|
||||
+ " \"authenticated\": true,"
|
||||
+ " \"principal\": " + DEFAULT_AUTHENTICATED_PRINCIPAL_JSON + ","
|
||||
+ " \"saml2Response\": \"" + SAML_RESPONSE + "\""
|
||||
+ "}";
|
||||
|
|
Loading…
Reference in New Issue