Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IS-59 Added getResponse to ResponseProcessingResult #60

Merged
merged 2 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ See <https://github.com/swedenconnect/opensaml-security-ext>.

---

Copyright &copy; 2016-2023, [Sweden Connect](https://swedenconnect.se). Licensed under version 2.0 of the [Apache License](http://www.apache.org/licenses/LICENSE-2.0).
Copyright &copy; 2016-2024, [Sweden Connect](https://swedenconnect.se). Licensed under version 2.0 of the [Apache License](http://www.apache.org/licenses/LICENSE-2.0).
20 changes: 13 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<groupId>se.swedenconnect.opensaml</groupId>
<artifactId>opensaml-addons</artifactId>
<packaging>jar</packaging>
<version>2.0.2</version>
<version>2.0.3-SNAPSHOT</version>

<name>Sweden Connect :: OpenSAML 5.X utility extensions</name>
<description>OpenSAML 5.X utility extension library</description>
Expand Down Expand Up @@ -46,8 +46,8 @@

<opensaml.version>5.0.0</opensaml.version>
<shib.support.version>9.0.0</shib.support.version>
<slf4j.version>2.0.9</slf4j.version>
<jackson.version>2.15.2</jackson.version>
<slf4j.version>2.0.12</slf4j.version>
<jackson.version>2.17.0</jackson.version>
</properties>

<repositories>
Expand Down Expand Up @@ -106,6 +106,12 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>

</dependencies>
Expand Down Expand Up @@ -142,28 +148,28 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
</dependency>

<!-- For testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<version>5.10.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.10.0</version>
<version>5.10.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.5.0</version>
<version>5.11.0</version>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public final class LibraryVersion {

private static final int MAJOR = 2;
private static final int MINOR = 0;
private static final int PATCH = 2;
private static final int PATCH = 3;

/**
* Global serialization value for library classes.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2023 Sweden Connect
* Copyright 2016-2024 Sweden Connect
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,10 +21,12 @@
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.saml.saml2.core.Response;

/**
* Interface that describes the result of a response processing operation. It contains the actual {@code Assertion} that
* really holds all information, but also "easy to access" methods of the elements that are of most interest.
* Interface that describes the result of a response processing operation. It contains the actual {@link Response} and
* {@link Assertion} objects that really holds all information, but also "easy to access" methods of the elements that
* are of most interest.
* <p>
* Note that only successful responses are represented. Error responses are represented using the
* {@link ResponseStatusErrorException}.
Expand Down Expand Up @@ -55,6 +57,13 @@ public interface ResponseProcessingResult {
*/
Instant getIssueInstant();

/**
* Gets the actual {@link Response} object.
*
* @return the {@link Response}
*/
Response getResponse();

/**
* Gets the {@code Assertion} from the response.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

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.AuthnContext;
import org.opensaml.saml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml.saml2.core.AuthnStatement;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.saml.saml2.core.Response;
Expand All @@ -35,14 +39,8 @@
*/
public class ResponseProcessingResultImpl implements ResponseProcessingResult {

/** The response ID. */
private final String responseId;

/** The InResponseTo attribute of the response. */
private final String inResponseTo;

/** The issue instant. */
private final Instant issueInstant;
/** The response. */
private final Response response;

/** The assertion. */
private final Assertion assertion;
Expand All @@ -54,31 +52,33 @@ public class ResponseProcessingResultImpl implements ResponseProcessingResult {
* @param assertion the Assertion
*/
public ResponseProcessingResultImpl(final Response response, final Assertion assertion) {
this.responseId = Optional.ofNullable(response).map(Response::getID)
.orElseThrow(() -> new NullPointerException("response is required"));
this.inResponseTo = Optional.ofNullable(response).map(Response::getInResponseTo)
.orElseThrow(() -> new NullPointerException("response is required"));
this.issueInstant = Optional.ofNullable(response).map(Response::getIssueInstant)
.orElseThrow(() -> new NullPointerException("response is required"));
this.response = Objects.requireNonNull(response, "response is required");
this.assertion = Objects.requireNonNull(assertion, "assertion is required");
}

/** {@inheritDoc} */
@Override
public Response getResponse() {
return this.response;
}


/** {@inheritDoc} */
@Override
public String getResponseId() {
return this.responseId;
return this.response.getID();
}

/** {@inheritDoc} */
@Override
public String getInResponseTo() {
return this.inResponseTo;
return this.response.getInResponseTo();
}

/** {@inheritDoc} */
@Override
public Instant getIssueInstant() {
return this.issueInstant;
return this.response.getIssueInstant();
}

/** {@inheritDoc} */
Expand All @@ -90,30 +90,31 @@ public Assertion getAssertion() {
/** {@inheritDoc} */
@Override
public List<Attribute> getAttributes() {
try {
return Collections.unmodifiableList(this.assertion.getAttributeStatements().get(0).getAttributes());
}
catch (NullPointerException | IndexOutOfBoundsException e) {
return Collections.emptyList();
}
return Collections.unmodifiableList(this.assertion.getAttributeStatements().stream()
.map(AttributeStatement::getAttributes)
.findFirst()
.orElseGet(() -> Collections.emptyList()));
}

/** {@inheritDoc} */
@Override
public String getAuthnContextClassUri() {
try {
return this.assertion.getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef().getURI();
}
catch (NullPointerException e) {
return null;
}
return this.assertion.getAuthnStatements().stream()
.map(AuthnStatement::getAuthnContext)
.map(AuthnContext::getAuthnContextClassRef)
.map(AuthnContextClassRef::getURI)
.findFirst()
.orElse(null);
}

/** {@inheritDoc} */
@Override
public Instant getAuthnInstant() {

Instant authnInstant = this.assertion.getAuthnStatements().get(0).getAuthnInstant();
final Instant authnInstant = this.assertion.getAuthnStatements().stream()
.map(AuthnStatement::getAuthnInstant)
.findFirst()
.orElseGet(() -> Instant.now());

// We have already checked the validity of the authentication instant, but if it is
// after the current time it means that it is within the allowed clock skew. If so,
Expand Down