mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-25 13:32:30 +00:00
Add SAML Attribute Support
Closes gh-8661
This commit is contained in:
parent
efb6953017
commit
eed33228f4
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,11 +17,13 @@ package org.springframework.security.saml2.provider.service.authentication;
|
|||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -31,7 +33,19 @@ import javax.annotation.Nonnull;
|
|||||||
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
|
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
import org.opensaml.core.criterion.EntityIdCriterion;
|
import org.opensaml.core.criterion.EntityIdCriterion;
|
||||||
|
import org.opensaml.core.xml.XMLObject;
|
||||||
|
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
|
||||||
|
import org.opensaml.core.xml.io.Marshaller;
|
||||||
|
|
||||||
|
import org.opensaml.core.xml.schema.XSAny;
|
||||||
|
import org.opensaml.core.xml.schema.XSBoolean;
|
||||||
|
import org.opensaml.core.xml.schema.XSBooleanValue;
|
||||||
|
import org.opensaml.core.xml.schema.XSDateTime;
|
||||||
|
import org.opensaml.core.xml.schema.XSInteger;
|
||||||
|
import org.opensaml.core.xml.schema.XSString;
|
||||||
|
import org.opensaml.core.xml.schema.XSURI;
|
||||||
import org.opensaml.saml.common.assertion.ValidationContext;
|
import org.opensaml.saml.common.assertion.ValidationContext;
|
||||||
import org.opensaml.saml.common.assertion.ValidationResult;
|
import org.opensaml.saml.common.assertion.ValidationResult;
|
||||||
import org.opensaml.saml.common.xml.SAMLConstants;
|
import org.opensaml.saml.common.xml.SAMLConstants;
|
||||||
@ -45,6 +59,8 @@ import org.opensaml.saml.saml2.assertion.SubjectConfirmationValidator;
|
|||||||
import org.opensaml.saml.saml2.assertion.impl.AudienceRestrictionConditionValidator;
|
import org.opensaml.saml.saml2.assertion.impl.AudienceRestrictionConditionValidator;
|
||||||
import org.opensaml.saml.saml2.assertion.impl.BearerSubjectConfirmationValidator;
|
import org.opensaml.saml.saml2.assertion.impl.BearerSubjectConfirmationValidator;
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
import org.opensaml.saml.saml2.core.Attribute;
|
||||||
|
import org.opensaml.saml.saml2.core.AttributeStatement;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedID;
|
import org.opensaml.saml.saml2.core.EncryptedID;
|
||||||
import org.opensaml.saml.saml2.core.NameID;
|
import org.opensaml.saml.saml2.core.NameID;
|
||||||
@ -205,8 +221,9 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
List<Assertion> validAssertions = validateResponse(token, response);
|
List<Assertion> validAssertions = validateResponse(token, response);
|
||||||
Assertion assertion = validAssertions.get(0);
|
Assertion assertion = validAssertions.get(0);
|
||||||
String username = getUsername(token, assertion);
|
String username = getUsername(token, assertion);
|
||||||
|
Map<String, List<Object>> attributes = getAssertionAttributes(assertion);
|
||||||
return new Saml2Authentication(
|
return new Saml2Authentication(
|
||||||
new SimpleSaml2AuthenticatedPrincipal(username), token.getSaml2Response(),
|
new SimpleSaml2AuthenticatedPrincipal(username, attributes), token.getSaml2Response(),
|
||||||
this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion)));
|
this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion)));
|
||||||
} catch (Saml2AuthenticationException e) {
|
} catch (Saml2AuthenticationException e) {
|
||||||
throw e;
|
throw e;
|
||||||
@ -494,6 +511,60 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
throw last;
|
throw last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, List<Object>> getAssertionAttributes(Assertion assertion) {
|
||||||
|
Map<String, List<Object>> attributeMap = new LinkedHashMap<>();
|
||||||
|
for (AttributeStatement attributeStatement : assertion.getAttributeStatements()) {
|
||||||
|
for (Attribute attribute : attributeStatement.getAttributes()) {
|
||||||
|
|
||||||
|
List<Object> attributeValues = new ArrayList<>();
|
||||||
|
for (XMLObject xmlObject : attribute.getAttributeValues()) {
|
||||||
|
Object attributeValue = getXmlObjectValue(xmlObject);
|
||||||
|
if (attributeValue != null) {
|
||||||
|
attributeValues.add(attributeValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributeMap.put(attribute.getName(), attributeValues);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attributeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getXmlObjectValue(XMLObject xmlObject) {
|
||||||
|
if (xmlObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSAny) {
|
||||||
|
return getXSAnyObjectValue((XSAny) xmlObject);
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSString) {
|
||||||
|
return ((XSString) xmlObject).getValue();
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSInteger) {
|
||||||
|
return ((XSInteger) xmlObject).getValue();
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSURI) {
|
||||||
|
return ((XSURI) xmlObject).getValue();
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSBoolean) {
|
||||||
|
XSBooleanValue xsBooleanValue = ((XSBoolean) xmlObject).getValue();
|
||||||
|
return xsBooleanValue != null ? xsBooleanValue.getValue() : null;
|
||||||
|
}
|
||||||
|
if (xmlObject instanceof XSDateTime) {
|
||||||
|
DateTime dateTime = ((XSDateTime) xmlObject).getValue();
|
||||||
|
return dateTime != null ? Instant.ofEpochMilli(dateTime.getMillis()) : null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getXSAnyObjectValue(XSAny xsAny) {
|
||||||
|
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(xsAny);
|
||||||
|
if (marshaller != null) {
|
||||||
|
return this.saml.serialize(xsAny);
|
||||||
|
}
|
||||||
|
return xsAny.getTextContent();
|
||||||
|
}
|
||||||
|
|
||||||
private Saml2Error validationError(String code, String description) {
|
private Saml2Error validationError(String code, String description) {
|
||||||
return new Saml2Error(code, description);
|
return new Saml2Error(code, description);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,7 +16,13 @@
|
|||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.authentication;
|
package org.springframework.security.saml2.provider.service.authentication;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saml2 representation of an {@link AuthenticatedPrincipal}.
|
* Saml2 representation of an {@link AuthenticatedPrincipal}.
|
||||||
@ -25,4 +31,40 @@ import org.springframework.security.core.AuthenticatedPrincipal;
|
|||||||
* @since 5.2.2
|
* @since 5.2.2
|
||||||
*/
|
*/
|
||||||
public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal {
|
public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal {
|
||||||
|
/**
|
||||||
|
* Get the first value of Saml2 token attribute by name
|
||||||
|
*
|
||||||
|
* @param name the name of the attribute
|
||||||
|
* @param <A> the type of the attribute
|
||||||
|
* @return the first attribute value or {@code null} otherwise
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default <A> A getFirstAttribute(String name) {
|
||||||
|
List<A> values = getAttribute(name);
|
||||||
|
return CollectionUtils.firstElement(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Saml2 token attribute by name
|
||||||
|
*
|
||||||
|
* @param name the name of the attribute
|
||||||
|
* @param <A> the type of the attribute
|
||||||
|
* @return the attribute or {@code null} otherwise
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default <A> List<A> getAttribute(String name) {
|
||||||
|
return (List<A>) getAttributes().get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Saml2 token attributes
|
||||||
|
*
|
||||||
|
* @return the Saml2 token attributes
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
default Map<String, List<Object>> getAttributes() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,6 +17,8 @@
|
|||||||
package org.springframework.security.saml2.provider.service.authentication;
|
package org.springframework.security.saml2.provider.service.authentication;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of a {@link Saml2AuthenticatedPrincipal}.
|
* Default implementation of a {@link Saml2AuthenticatedPrincipal}.
|
||||||
@ -27,13 +29,20 @@ import java.io.Serializable;
|
|||||||
class SimpleSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPrincipal, Serializable {
|
class SimpleSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPrincipal, Serializable {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final Map<String, List<Object>> attributes;
|
||||||
|
|
||||||
SimpleSaml2AuthenticatedPrincipal(String name) {
|
SimpleSaml2AuthenticatedPrincipal(String name, Map<String, List<Object>> attributes) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, List<Object>> getAttributes() {
|
||||||
|
return this.attributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,11 @@ package org.springframework.security.saml2.provider.service.authentication;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hamcrest.BaseMatcher;
|
import org.hamcrest.BaseMatcher;
|
||||||
import org.hamcrest.Description;
|
import org.hamcrest.Description;
|
||||||
@ -39,6 +43,7 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
||||||
|
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.assertion;
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.assertion;
|
||||||
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.attributeStatements;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.encrypted;
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.encrypted;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.response;
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.response;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.signed;
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.signed;
|
||||||
@ -47,6 +52,7 @@ import static org.springframework.security.saml2.credentials.TestSaml2X509Creden
|
|||||||
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.assertingPartySigningCredential;
|
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.assertingPartySigningCredential;
|
||||||
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.relyingPartyDecryptingCredential;
|
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.relyingPartyDecryptingCredential;
|
||||||
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.relyingPartyVerifyingCredential;
|
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.relyingPartyVerifyingCredential;
|
||||||
|
import static org.springframework.test.util.AssertionErrors.assertEquals;
|
||||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||||
import static org.springframework.util.StringUtils.hasText;
|
import static org.springframework.util.StringUtils.hasText;
|
||||||
|
|
||||||
@ -193,6 +199,30 @@ public class OpenSamlAuthenticationProviderTests {
|
|||||||
this.provider.authenticate(token);
|
this.provider.authenticate(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticateWhenAssertionContainsAttributesThenItSucceeds() {
|
||||||
|
Response response = response();
|
||||||
|
Assertion assertion = assertion();
|
||||||
|
attributeStatements().forEach(as -> assertion.getAttributeStatements().add(as));
|
||||||
|
signed(assertion, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
|
||||||
|
response.getAssertions().add(assertion);
|
||||||
|
Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential());
|
||||||
|
Authentication authentication = this.provider.authenticate(token);
|
||||||
|
Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) authentication.getPrincipal();
|
||||||
|
|
||||||
|
Map<String, Object> attributes = new LinkedHashMap<>();
|
||||||
|
attributes.put("email", Arrays.asList("john.doe@example.com", "doe.john@example.com"));
|
||||||
|
attributes.put("name", Collections.singletonList("John Doe"));
|
||||||
|
attributes.put("age", Collections.singletonList(21));
|
||||||
|
attributes.put("website", Collections.singletonList("https://johndoe.com/"));
|
||||||
|
attributes.put("registered", Collections.singletonList(true));
|
||||||
|
Instant registeredDate = Instant.ofEpochMilli(DateTime.parse("1970-01-01T00:00:00Z").getMillis());
|
||||||
|
attributes.put("registeredDate", Collections.singletonList(registeredDate));
|
||||||
|
|
||||||
|
assertEquals("Values should be equal", "John Doe", principal.getFirstAttribute("name"));
|
||||||
|
assertTrue("Attributes should be equal", attributes.equals(principal.getAttributes()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authenticateWhenEncryptedAssertionWithoutSignatureThenItFails() throws Exception {
|
public void authenticateWhenEncryptedAssertionWithoutSignatureThenItFails() throws Exception {
|
||||||
this.exception.expect(authenticationMatcher(Saml2ErrorCodes.INVALID_SIGNATURE));
|
this.exception.expect(authenticationMatcher(Saml2ErrorCodes.INVALID_SIGNATURE));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,15 +16,58 @@
|
|||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.authentication;
|
package org.springframework.security.saml2.provider.service.authentication;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
public class SimpleSaml2AuthenticatedPrincipalTests {
|
public class SimpleSaml2AuthenticatedPrincipalTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createSimpleSaml2AuthenticatedPrincipal() {
|
public void createSimpleSaml2AuthenticatedPrincipal() {
|
||||||
SimpleSaml2AuthenticatedPrincipal principal = new SimpleSaml2AuthenticatedPrincipal("user");
|
Map<String, List<Object>> attributes = new LinkedHashMap<>();
|
||||||
|
attributes.put("email", Arrays.asList("john.doe@example.com", "doe.john@example.com"));
|
||||||
|
SimpleSaml2AuthenticatedPrincipal principal = new SimpleSaml2AuthenticatedPrincipal("user", attributes);
|
||||||
|
assertThat(principal.getName()).isEqualTo("user");
|
||||||
|
assertThat(principal.getAttributes()).isEqualTo(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
Assert.assertEquals("user", principal.getName());
|
@Test
|
||||||
|
public void getFirstAttributeWhenStringValueThenReturnsValue() {
|
||||||
|
Map<String, List<Object>> attributes = new LinkedHashMap<>();
|
||||||
|
attributes.put("email", Arrays.asList("john.doe@example.com", "doe.john@example.com"));
|
||||||
|
SimpleSaml2AuthenticatedPrincipal principal = new SimpleSaml2AuthenticatedPrincipal("user", attributes);
|
||||||
|
assertThat(principal.<String>getFirstAttribute("email")).isEqualTo(attributes.get("email").get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAttributeWhenStringValuesThenReturnsValues() {
|
||||||
|
Map<String, List<Object>> attributes = new LinkedHashMap<>();
|
||||||
|
attributes.put("email", Arrays.asList("john.doe@example.com", "doe.john@example.com"));
|
||||||
|
SimpleSaml2AuthenticatedPrincipal principal = new SimpleSaml2AuthenticatedPrincipal("user", attributes);
|
||||||
|
assertThat(principal.<String>getAttribute("email")).isEqualTo(attributes.get("email"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAttributeWhenDistinctValuesThenReturnsValues() {
|
||||||
|
final Boolean registered = true;
|
||||||
|
final Instant registeredDate = Instant.ofEpochMilli(DateTime.parse("1970-01-01T00:00:00Z").getMillis());
|
||||||
|
|
||||||
|
Map<String, List<Object>> attributes = new LinkedHashMap<>();
|
||||||
|
attributes.put("registration", Arrays.asList(registered, registeredDate));
|
||||||
|
|
||||||
|
SimpleSaml2AuthenticatedPrincipal principal = new SimpleSaml2AuthenticatedPrincipal("user", attributes);
|
||||||
|
|
||||||
|
List<Object> registrationInfo = principal.getAttribute("registration");
|
||||||
|
|
||||||
|
assertThat(registrationInfo).isNotNull();
|
||||||
|
assertThat((Boolean) registrationInfo.get(0)).isEqualTo(registered);
|
||||||
|
assertThat((Instant) registrationInfo.get(1)).isEqualTo(registeredDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package org.springframework.security.saml2.provider.service.authentication;
|
|||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
@ -26,9 +28,26 @@ import org.apache.xml.security.encryption.XMLCipherParameters;
|
|||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
import org.opensaml.core.xml.io.MarshallingException;
|
import org.opensaml.core.xml.io.MarshallingException;
|
||||||
|
|
||||||
|
import org.opensaml.core.xml.schema.XSAny;
|
||||||
|
import org.opensaml.core.xml.schema.XSBoolean;
|
||||||
|
import org.opensaml.core.xml.schema.XSBooleanValue;
|
||||||
|
import org.opensaml.core.xml.schema.XSDateTime;
|
||||||
|
import org.opensaml.core.xml.schema.XSInteger;
|
||||||
|
import org.opensaml.core.xml.schema.XSString;
|
||||||
|
import org.opensaml.core.xml.schema.XSURI;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSAnyBuilder;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSBooleanBuilder;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSDateTimeBuilder;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSIntegerBuilder;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSStringBuilder;
|
||||||
|
import org.opensaml.core.xml.schema.impl.XSURIBuilder;
|
||||||
import org.opensaml.saml.common.SAMLVersion;
|
import org.opensaml.saml.common.SAMLVersion;
|
||||||
import org.opensaml.saml.common.SignableSAMLObject;
|
import org.opensaml.saml.common.SignableSAMLObject;
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
import org.opensaml.saml.saml2.core.Attribute;
|
||||||
|
import org.opensaml.saml.saml2.core.AttributeStatement;
|
||||||
|
import org.opensaml.saml.saml2.core.AttributeValue;
|
||||||
import org.opensaml.saml.saml2.core.Conditions;
|
import org.opensaml.saml.saml2.core.Conditions;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedID;
|
import org.opensaml.saml.saml2.core.EncryptedID;
|
||||||
@ -38,6 +57,8 @@ import org.opensaml.saml.saml2.core.Response;
|
|||||||
import org.opensaml.saml.saml2.core.Subject;
|
import org.opensaml.saml.saml2.core.Subject;
|
||||||
import org.opensaml.saml.saml2.core.SubjectConfirmation;
|
import org.opensaml.saml.saml2.core.SubjectConfirmation;
|
||||||
import org.opensaml.saml.saml2.core.SubjectConfirmationData;
|
import org.opensaml.saml.saml2.core.SubjectConfirmationData;
|
||||||
|
import org.opensaml.saml.saml2.core.impl.AttributeBuilder;
|
||||||
|
import org.opensaml.saml.saml2.core.impl.AttributeStatementBuilder;
|
||||||
import org.opensaml.saml.saml2.encryption.Encrypter;
|
import org.opensaml.saml.saml2.encryption.Encrypter;
|
||||||
import org.opensaml.security.SecurityException;
|
import org.opensaml.security.SecurityException;
|
||||||
import org.opensaml.security.credential.BasicCredential;
|
import org.opensaml.security.credential.BasicCredential;
|
||||||
@ -222,4 +243,66 @@ final class TestOpenSamlObjects {
|
|||||||
|
|
||||||
return encrypter;
|
return encrypter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<AttributeStatement> attributeStatements() {
|
||||||
|
List<AttributeStatement> attributeStatements = new ArrayList<>();
|
||||||
|
|
||||||
|
AttributeStatementBuilder attributeStatementBuilder = new AttributeStatementBuilder();
|
||||||
|
AttributeBuilder attributeBuilder = new AttributeBuilder();
|
||||||
|
|
||||||
|
AttributeStatement attrStmt1 = attributeStatementBuilder.buildObject();
|
||||||
|
|
||||||
|
Attribute emailAttr = attributeBuilder.buildObject();
|
||||||
|
emailAttr.setName("email");
|
||||||
|
XSAny email1 = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
|
||||||
|
email1.setTextContent("john.doe@example.com");
|
||||||
|
emailAttr.getAttributeValues().add(email1);
|
||||||
|
XSAny email2 = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
|
||||||
|
email2.setTextContent("doe.john@example.com");
|
||||||
|
emailAttr.getAttributeValues().add(email2);
|
||||||
|
attrStmt1.getAttributes().add(emailAttr);
|
||||||
|
|
||||||
|
Attribute nameAttr = attributeBuilder.buildObject();
|
||||||
|
nameAttr.setName("name");
|
||||||
|
XSString name = new XSStringBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
|
||||||
|
name.setValue("John Doe");
|
||||||
|
nameAttr.getAttributeValues().add(name);
|
||||||
|
attrStmt1.getAttributes().add(nameAttr);
|
||||||
|
|
||||||
|
Attribute ageAttr = attributeBuilder.buildObject();
|
||||||
|
ageAttr.setName("age");
|
||||||
|
XSInteger age = new XSIntegerBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
|
||||||
|
age.setValue(21);
|
||||||
|
ageAttr.getAttributeValues().add(age);
|
||||||
|
attrStmt1.getAttributes().add(ageAttr);
|
||||||
|
|
||||||
|
attributeStatements.add(attrStmt1);
|
||||||
|
|
||||||
|
AttributeStatement attrStmt2 = attributeStatementBuilder.buildObject();
|
||||||
|
|
||||||
|
Attribute websiteAttr = attributeBuilder.buildObject();
|
||||||
|
websiteAttr.setName("website");
|
||||||
|
XSURI uri = new XSURIBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSURI.TYPE_NAME);
|
||||||
|
uri.setValue("https://johndoe.com/");
|
||||||
|
websiteAttr.getAttributeValues().add(uri);
|
||||||
|
attrStmt2.getAttributes().add(websiteAttr);
|
||||||
|
|
||||||
|
Attribute registeredAttr = attributeBuilder.buildObject();
|
||||||
|
registeredAttr.setName("registered");
|
||||||
|
XSBoolean registered = new XSBooleanBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSBoolean.TYPE_NAME);
|
||||||
|
registered.setValue(new XSBooleanValue(true, false));
|
||||||
|
registeredAttr.getAttributeValues().add(registered);
|
||||||
|
attrStmt2.getAttributes().add(registeredAttr);
|
||||||
|
|
||||||
|
Attribute registeredDateAttr = attributeBuilder.buildObject();
|
||||||
|
registeredDateAttr.setName("registeredDate");
|
||||||
|
XSDateTime registeredDate = new XSDateTimeBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSDateTime.TYPE_NAME);
|
||||||
|
registeredDate.setValue(DateTime.parse("1970-01-01T00:00:00Z"));
|
||||||
|
registeredDateAttr.getAttributeValues().add(registeredDate);
|
||||||
|
attrStmt2.getAttributes().add(registeredDateAttr);
|
||||||
|
|
||||||
|
attributeStatements.add(attrStmt2);
|
||||||
|
|
||||||
|
return attributeStatements;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user