Skip to content

Commit 43377a4

Browse files
committed
Add open-saml
1 parent 53c26b6 commit 43377a4

File tree

14 files changed

+742
-0
lines changed

14 files changed

+742
-0
lines changed

java/cbsso-opensaml/.gitattributes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# https://help.github.com/articles/dealing-with-line-endings/
3+
#
4+
# Linux start script should use lf
5+
/gradlew text eol=lf
6+
7+
# These are Windows script files and should use crlf
8+
*.bat text eol=crlf
9+

java/cbsso-opensaml/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Ignore Gradle project-specific cache directory
2+
.gradle
3+
4+
# Ignore Gradle build output directory
5+
build
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* This file was generated by the Gradle 'init' task.
3+
*
4+
* This generated file contains a sample Java application project to get you started.
5+
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.8/userguide/building_java_projects.html in the Gradle documentation.
6+
*/
7+
8+
plugins {
9+
// Apply the application plugin to add support for building a CLI application in Java.
10+
id 'application'
11+
}
12+
13+
repositories {
14+
// Use Maven Central for resolving dependencies.
15+
mavenCentral()
16+
}
17+
18+
dependencies {
19+
// Use JUnit Jupiter for testing.
20+
testImplementation libs.junit.jupiter
21+
22+
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
23+
24+
// This dependency is used by the application.
25+
implementation libs.guava
26+
27+
implementation "org.opensaml:opensaml-core:$opensamlVersion"
28+
implementation "org.opensaml:opensaml-saml-impl:$opensamlVersion"
29+
implementation "org.opensaml:opensaml-soap-api:$opensamlVersion"
30+
implementation "org.opensaml:opensaml-xmlsec-api:$opensamlVersion"
31+
implementation "org.opensaml:opensaml-security-api:$opensamlVersion"
32+
implementation "org.opensaml:opensaml-security-impl:$opensamlVersion"
33+
implementation "org.opensaml:opensaml-profile-api:$opensamlVersion"
34+
35+
implementation "org.slf4j:slf4j-api:1.7.36"
36+
implementation "org.slf4j:slf4j-simple:1.7.36"
37+
}
38+
39+
// Apply a specific Java toolchain to ease working on different environments.
40+
java {
41+
toolchain {
42+
languageVersion = JavaLanguageVersion.of(21)
43+
}
44+
}
45+
46+
application {
47+
// Define the main class for the application.
48+
mainClass = 'cbsso.opensaml.App'
49+
}
50+
51+
tasks.named('test') {
52+
// Use JUnit Platform for unit tests.
53+
useJUnitPlatform()
54+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
opensamlVersion=4.0.1
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* This source file was generated by the Gradle 'init' task
3+
*/
4+
package cbsso.opensaml;
5+
6+
import java.time.Instant;
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
import org.opensaml.core.config.ConfigurationService;
11+
import org.opensaml.core.config.InitializationException;
12+
import org.opensaml.core.config.InitializationService;
13+
import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
14+
import org.opensaml.saml.saml2.core.AuthnRequest;
15+
import org.opensaml.saml.saml2.core.Issuer;
16+
import org.opensaml.saml.saml2.core.NameIDPolicy;
17+
import org.opensaml.saml.saml2.core.NameIDType;
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
21+
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
22+
import net.shibboleth.utilities.java.support.xml.BasicParserPool;
23+
import net.shibboleth.utilities.java.support.xml.ParserPool;
24+
25+
public class App {
26+
public String getGreeting() {
27+
return "Hello World!";
28+
}
29+
30+
private static final String IPD_SSO_DESTINATION = "https://idp.example.com/singleSingOnService";
31+
private static final String SP_ASSERTION_CONSUMER_SERVICE_URL = "https://sp.example.com/assertionConsumerService";
32+
private static final String SP_ISSUED_ID = "IssuerEntityId";
33+
private static Logger logger = LoggerFactory.getLogger(App.class);
34+
35+
public static void main(String[] args) {
36+
37+
initOpenSAML();
38+
AuthnRequest authnRequest = buildAuthnRequest();
39+
OpenSAMLUtils.logSAMLObject(authnRequest);
40+
}
41+
42+
private static void initOpenSAML() {
43+
XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
44+
ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
45+
46+
registry.setParserPool(getParserPool());
47+
try {
48+
InitializationService.initialize();
49+
} catch (InitializationException e) {
50+
logger.error(e.getMessage(), e);
51+
}
52+
}
53+
54+
private static ParserPool getParserPool() {
55+
BasicParserPool parserPool = new BasicParserPool();
56+
parserPool.setMaxPoolSize(100);
57+
parserPool.setCoalescing(true);
58+
parserPool.setIgnoreComments(true);
59+
parserPool.setIgnoreElementContentWhitespace(true);
60+
parserPool.setNamespaceAware(true);
61+
parserPool.setExpandEntityReferences(false);
62+
parserPool.setXincludeAware(false);
63+
64+
final Map<String, Boolean> features = new HashMap<String, Boolean>();
65+
features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE);
66+
features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE);
67+
features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
68+
features.put("http://apache.org/xml/features/validation/schema/normalized-value", Boolean.FALSE);
69+
features.put("http://javax.xml.XMLConstants/feature/secure-processing", Boolean.TRUE);
70+
71+
parserPool.setBuilderFeatures(features);
72+
73+
parserPool.setBuilderAttributes(new HashMap<String, Object>());
74+
75+
try {
76+
parserPool.initialize();
77+
} catch (ComponentInitializationException e) {
78+
logger.error(e.getMessage(), e);
79+
}
80+
81+
return parserPool;
82+
}
83+
84+
private static AuthnRequest buildAuthnRequest() {
85+
AuthnRequest authnRequest = OpenSAMLUtils.buildSAMLObject(AuthnRequest.class);
86+
authnRequest.setIssueInstant(Instant.now());
87+
// authnRequest.setDestination(IPD_SSO_DESTINATION);
88+
// authnRequest.setProtocolBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
89+
// authnRequest.setAssertionConsumerServiceURL(SP_ASSERTION_CONSUMER_SERVICE_URL);
90+
authnRequest.setID(OpenSAMLUtils.generateSecureRandomId());
91+
authnRequest.setIssuer(buildIssuer());
92+
authnRequest.setNameIDPolicy(buildNameIdPolicy());
93+
94+
return authnRequest;
95+
}
96+
97+
private static NameIDPolicy buildNameIdPolicy() {
98+
NameIDPolicy nameIDPolicy = OpenSAMLUtils.buildSAMLObject(NameIDPolicy.class);
99+
nameIDPolicy.setAllowCreate(true);
100+
nameIDPolicy.setFormat(NameIDType.TRANSIENT);
101+
102+
return nameIDPolicy;
103+
}
104+
105+
private static Issuer buildIssuer() {
106+
Issuer issuer = OpenSAMLUtils.buildSAMLObject(Issuer.class);
107+
issuer.setValue(SP_ISSUED_ID);
108+
109+
return issuer;
110+
}
111+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package cbsso.opensaml;
2+
3+
import java.time.Instant;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
import org.opensaml.core.config.ConfigurationService;
8+
import org.opensaml.core.config.InitializationException;
9+
import org.opensaml.core.config.InitializationService;
10+
import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
11+
import org.opensaml.saml.saml2.core.AuthnRequest;
12+
import org.opensaml.saml.saml2.core.Issuer;
13+
import org.opensaml.saml.saml2.core.NameIDPolicy;
14+
import org.opensaml.saml.saml2.core.NameIDType;
15+
16+
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
17+
import net.shibboleth.utilities.java.support.xml.BasicParserPool;
18+
import net.shibboleth.utilities.java.support.xml.ParserPool;
19+
20+
public class AuthNRequestGenerator {
21+
public static String generateAuthNRequest(String issuerId, String requestId)
22+
throws InitializationException, ComponentInitializationException {
23+
initOpenSAML();
24+
AuthnRequest authnRequest = buildAuthnRequest(issuerId, requestId);
25+
return OpenSAMLUtils.stringifySAMLObject(authnRequest);
26+
}
27+
28+
private static void initOpenSAML() throws InitializationException, ComponentInitializationException {
29+
XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
30+
ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
31+
32+
registry.setParserPool(getParserPool());
33+
InitializationService.initialize();
34+
}
35+
36+
private static ParserPool getParserPool() throws ComponentInitializationException {
37+
BasicParserPool parserPool = new BasicParserPool();
38+
parserPool.setMaxPoolSize(100);
39+
parserPool.setCoalescing(true);
40+
parserPool.setIgnoreComments(true);
41+
parserPool.setIgnoreElementContentWhitespace(true);
42+
parserPool.setNamespaceAware(true);
43+
parserPool.setExpandEntityReferences(false);
44+
parserPool.setXincludeAware(false);
45+
46+
final Map<String, Boolean> features = new HashMap<String, Boolean>();
47+
features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE);
48+
features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE);
49+
features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
50+
features.put("http://apache.org/xml/features/validation/schema/normalized-value", Boolean.FALSE);
51+
features.put("http://javax.xml.XMLConstants/feature/secure-processing", Boolean.TRUE);
52+
53+
parserPool.setBuilderFeatures(features);
54+
55+
parserPool.setBuilderAttributes(new HashMap<String, Object>());
56+
57+
parserPool.initialize();
58+
59+
return parserPool;
60+
}
61+
62+
private static AuthnRequest buildAuthnRequest(String issuerId, String requestId) {
63+
AuthnRequest authnRequest = OpenSAMLUtils.buildSAMLObject(AuthnRequest.class);
64+
authnRequest.setIssueInstant(Instant.now());
65+
// authnRequest.setDestination(IPD_SSO_DESTINATION);
66+
// authnRequest.setProtocolBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
67+
// authnRequest.setAssertionConsumerServiceURL(SP_ASSERTION_CONSUMER_SERVICE_URL);
68+
authnRequest.setID(requestId);
69+
authnRequest.setIssuer(buildIssuer(issuerId));
70+
authnRequest.setNameIDPolicy(buildNameIdPolicy());
71+
72+
return authnRequest;
73+
}
74+
75+
private static NameIDPolicy buildNameIdPolicy() {
76+
NameIDPolicy nameIDPolicy = OpenSAMLUtils.buildSAMLObject(NameIDPolicy.class);
77+
nameIDPolicy.setAllowCreate(true);
78+
nameIDPolicy.setFormat(NameIDType.TRANSIENT);
79+
80+
return nameIDPolicy;
81+
}
82+
83+
private static Issuer buildIssuer(String issuerId) {
84+
Issuer issuer = OpenSAMLUtils.buildSAMLObject(Issuer.class);
85+
issuer.setValue(issuerId);
86+
87+
return issuer;
88+
}
89+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package cbsso.opensaml;
2+
3+
import javax.xml.namespace.QName;
4+
5+
import org.opensaml.core.xml.XMLObject;
6+
import org.opensaml.core.xml.XMLObjectBuilderFactory;
7+
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
8+
import org.opensaml.core.xml.io.Marshaller;
9+
import org.opensaml.core.xml.io.MarshallingException;
10+
import org.opensaml.saml.common.SignableSAMLObject;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
import org.w3c.dom.Element;
14+
15+
import net.shibboleth.utilities.java.support.security.impl.RandomIdentifierGenerationStrategy;
16+
import net.shibboleth.utilities.java.support.xml.SerializeSupport;
17+
18+
public class OpenSAMLUtils {
19+
private static Logger logger = LoggerFactory.getLogger(OpenSAMLUtils.class);
20+
private static RandomIdentifierGenerationStrategy secureRandomIdGenerator;
21+
22+
static {
23+
secureRandomIdGenerator = new RandomIdentifierGenerationStrategy();
24+
25+
}
26+
27+
public static <T> T buildSAMLObject(final Class<T> clazz) {
28+
T object = null;
29+
try {
30+
XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
31+
QName defaultElementName = (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
32+
object = (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
33+
} catch (IllegalAccessException e) {
34+
throw new IllegalArgumentException("Could not create SAML object");
35+
} catch (NoSuchFieldException e) {
36+
throw new IllegalArgumentException("Could not create SAML object");
37+
}
38+
39+
return object;
40+
}
41+
42+
public static String generateSecureRandomId() {
43+
return secureRandomIdGenerator.generateIdentifier();
44+
}
45+
46+
public static void logSAMLObject(final XMLObject object) {
47+
Element element = null;
48+
49+
if (object instanceof SignableSAMLObject && ((SignableSAMLObject) object).isSigned()
50+
&& object.getDOM() != null) {
51+
element = object.getDOM();
52+
} else {
53+
try {
54+
Marshaller out = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
55+
out.marshall(object);
56+
element = object.getDOM();
57+
58+
} catch (MarshallingException e) {
59+
logger.error(e.getMessage(), e);
60+
}
61+
}
62+
String xmlString = SerializeSupport.prettyPrintXML(element);
63+
64+
logger.info(xmlString);
65+
66+
}
67+
68+
public static String stringifySAMLObject(final XMLObject object) {
69+
Element element = null;
70+
71+
if (object instanceof SignableSAMLObject && ((SignableSAMLObject) object).isSigned()
72+
&& object.getDOM() != null) {
73+
element = object.getDOM();
74+
} else {
75+
try {
76+
Marshaller out = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
77+
out.marshall(object);
78+
element = object.getDOM();
79+
80+
} catch (MarshallingException e) {
81+
logger.error(e.getMessage(), e);
82+
}
83+
}
84+
85+
return SerializeSupport.prettyPrintXML(element);
86+
}
87+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* This source file was generated by the Gradle 'init' task
3+
*/
4+
package cbsso.opensaml;
5+
6+
import org.junit.jupiter.api.Test;
7+
import static org.junit.jupiter.api.Assertions.*;
8+
9+
class AppTest {
10+
@Test void appHasAGreeting() {
11+
App classUnderTest = new App();
12+
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
13+
}
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file was generated by the Gradle 'init' task.
2+
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
3+
4+
[versions]
5+
guava = "33.0.0-jre"
6+
junit-jupiter = "5.10.2"
7+
8+
[libraries]
9+
guava = { module = "com.google.guava:guava", version.ref = "guava" }
10+
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
42.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)