[java-identity-provider] branch main updated: IDP-1716 - X509 flow within MFA and subject canonicalization
Scott Cantor
cantor.2 at osu.edu
Fri Jan 22 00:50:30 UTC 2021
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=3e62435100aacd2330b92477d75994557aa2a3d1
The following commit(s) were added to refs/heads/main by this push:
new 3e6243510 IDP-1716 - X509 flow within MFA and subject canonicalization
3e6243510 is described below
commit 3e62435100aacd2330b92477d75994557aa2a3d1
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Jan 21 19:50:26 2021 -0500
IDP-1716 - X509 flow within MFA and subject canonicalization
https://issues.shibboleth.net/jira/browse/IDP-1716
Serialize certificates in authentication results.
---
.../DefaultAuthenticationResultSerializer.java | 47 +++++++++++++++++++---
.../DefaultAuthenticationResultSerializerTest.java | 27 ++++++++++++-
2 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializer.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializer.java
index 1b2339bcd..9e5eed795 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializer.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializer.java
@@ -21,6 +21,9 @@ import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.Principal;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
@@ -54,11 +57,14 @@ import net.shibboleth.idp.authn.principal.PrincipalServiceManager;
import net.shibboleth.idp.authn.principal.impl.AuthenticationResultPrincipalSerializer;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+import net.shibboleth.utilities.java.support.codec.EncodingException;
import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import org.opensaml.security.x509.X509Support;
import org.opensaml.storage.StorageSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -82,6 +88,9 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
/** Field name of public credentials array. */
@Nonnull @NotEmpty private static final String PUB_CREDS_ARRAY_FIELD = "pub";
+ /** Field name of X.509 certificates array. */
+ @Nonnull @NotEmpty private static final String X509_CREDS_ARRAY_FIELD = "x509";
+
/** Field name of private credentials array. */
@Nonnull @NotEmpty private static final String PRIV_CREDS_ARRAY_FIELD = "priv";
@@ -181,6 +190,7 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
}
}
+// Checkstyle: CyclomaticComplexity|MethodLength OFF
/** {@inheritDoc} */
@Nonnull @NotEmpty public String serialize(@Nonnull final AuthenticationResult instance) throws IOException {
ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
@@ -222,7 +232,21 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
gen.writeEnd();
}
- // TODO handle custom creds
+ final Set<X509Certificate> x509Creds = instance.getSubject().getPublicCredentials(X509Certificate.class);
+ if (x509Creds != null && !x509Creds.isEmpty()) {
+ gen.writeStartArray(X509_CREDS_ARRAY_FIELD);
+ for (final X509Certificate x : x509Creds) {
+ try {
+ gen.write(Base64Support.encode(x.getEncoded(), false));
+ } catch (final CertificateEncodingException|EncodingException e) {
+ log.warn("Unable to serialize X.509 certificate with subject: {}",
+ x.getSubjectDN().toString());
+ }
+ }
+ gen.writeEnd();
+ }
+
+ // TODO handle other creds
gen.writeEnd().close();
@@ -231,8 +255,7 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
throw new IOException("Exception while serializing AuthenticationResult", e);
}
}
-
- // Checkstyle: CyclomaticComplexity OFF
+
/** {@inheritDoc} */
@Nonnull public AuthenticationResult deserialize(final long version, @Nonnull @NotEmpty final String context,
@Nonnull @NotEmpty final String key, @Nonnull @NotEmpty final String value,
@@ -294,8 +317,22 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
}
}
}
+
+ final JsonArray x509Creds = obj.getJsonArray(X509_CREDS_ARRAY_FIELD);
+ if (x509Creds != null) {
+ for (final JsonValue val : x509Creds) {
+ if (val.getValueType() == ValueType.STRING) {
+ try {
+ final X509Certificate cert = X509Support.decodeCertificate(val.toString());
+ result.getSubject().getPublicCredentials().add(cert);
+ } catch (final CertificateException e) {
+ log.warn("Unable to parse certificate", e);
+ }
+ }
+ }
+ }
- // TODO handle custom creds
+ // TODO handle other creds
return result;
@@ -303,7 +340,7 @@ public class DefaultAuthenticationResultSerializer extends AbstractInitializable
throw new IOException("Found invalid data structure while parsing AuthenticationResult", e);
}
}
- // Checkstyle: CyclomaticComplexity ON
+ // Checkstyle: CyclomaticComplexity|MethodLength ON
/**
* Attempt to serialize a principal with the registered and default serializers.
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializerTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializerTest.java
index 758df202d..db1071f1b 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializerTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/DefaultAuthenticationResultSerializerTest.java
@@ -62,6 +62,7 @@ import org.ldaptive.SortBehavior;
import org.ldaptive.jaas.LdapPrincipal;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.testing.RequestContextBuilder;
+import org.opensaml.security.x509.X509Support;
import org.springframework.core.io.ClassPathResource;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -80,7 +81,28 @@ public class DefaultAuthenticationResultSerializerTest {
private static final Instant INSTANT = Instant.ofEpochMilli(1378827849463L);
private static final long ACTIVITY = 1378827556778L;
-
+
+ private static final String entityCertBase64 =
+ "MIIDjDCCAnSgAwIBAgIBKjANBgkqhkiG9w0BAQUFADAtMRIwEAYDVQQKEwlJbnRl" +
+ "cm5ldDIxFzAVBgNVBAMTDmNhLmV4YW1wbGUub3JnMB4XDTA3MDQwOTA2MTIwOVoX" +
+ "DTE3MDQwNjA2MTIwOVowMTESMBAGA1UEChMJSW50ZXJuZXQyMRswGQYDVQQDExJm" +
+ "b29iYXIuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB" +
+ "AQDNWnkFmhy1vYa6gN/xBRKkZxFy3sUq2V0LsYb6Q3pe9Qlb6+BzaM5DrN8uIqqr" +
+ "oBE3Wp0LtrgKuQTpDpNFBdS2p5afiUtOYLWBDtizTOzs3Z36MGMjIPUYQ4s03IP3" +
+ "yPh2ud6EKpDPiYqzNbkRaiIwmYSit5r+RMYvd6fuKvTOn6h7PZI5AD7Rda7VWh5O" +
+ "VSoZXlRx3qxFho+mZhW0q4fUfTi5lWwf4EhkfBlzgw/k5gf4cOi6rrGpRS1zxmbt" +
+ "X1RAg+I20z6d04g0N2WsK5stszgYKoIROJCiXwjraa8/SoFcILolWQpttVHBIUYl" +
+ "yDlm8mIFleZf4ReFpfm+nUYxAgMBAAGjgbIwga8wCQYDVR0TBAIwADAsBglghkgB" +
+ "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" +
+ "FDgRgTkjaKoK6DoZfUZ4g9LDJUWuMFUGA1UdIwROMEyAFNXuZVPeUdqHrULqQW7y" +
+ "r9buRpQLoTGkLzAtMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDmNhLmV4" +
+ "YW1wbGUub3JnggEBMA0GCSqGSIb3DQEBBQUAA4IBAQCPj3Si4Eiw9abNgPBUhBXW" +
+ "d6eRYlIHaHcnez6j6g7foAOyuVIUso9Q5c6pvL87lmasK55l09YPXw1qmiH+bHMc" +
+ "rwEPODpLx7xd3snlOCi7FyxahxwSs8yfTu8Pq95rWt0LNcfHxQK938Cpnav6jgDo" +
+ "2uH/ywAOFFSnoBzGHAfScHMfj8asZ6THosYsklII7FSU8j49GV2utkvGB3mcu4ST" +
+ "uLdeRCZmi93vq1D4JVGsXC4UaHjg114+a+9q0XZdz6a1UW4pt1ryXIPotCS62M71" +
+ "pkJf5neHUinKAqgoRfPXowudZg1Zl8DjzoOBn+MNHRrR5KYbVGvdHcxoJLCwVB/v";
+
private PrincipalServiceManager manager;
private DefaultAuthenticationResultSerializer serializer;
@@ -117,7 +139,7 @@ public class DefaultAuthenticationResultSerializerTest {
new GenericPrincipalService<>(ProxyAuthenticationPrincipal.class, proxySerializer);
proxyService.setId("proxy");
proxyService.initialize();
-
+
final ClassPathResource keystoreResource = new ClassPathResource("/net/shibboleth/idp/authn/impl/SealerKeyStore.jks");
final ClassPathResource versionResource = new ClassPathResource("/net/shibboleth/idp/authn/impl/SealerKeyStore.kver");
@@ -255,6 +277,7 @@ public class DefaultAuthenticationResultSerializerTest {
final AuthenticationResult result = createResult(flowDescriptor, new Subject());
result.getSubject().getPrincipals().add(new UsernamePrincipal("bob"));
+ result.getSubject().getPublicCredentials().add(X509Support.decodeCertificate(entityCertBase64));
result.getSubject().getPrivateCredentials().add(new PasswordPrincipal("bar"));
final ProfileRequestContext prc = getProfileRequestContext(Collections.singletonList(flowDescriptor));
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list