Skip to content

Commit c135ece

Browse files
committed
Support parsing SAML Responses containing multiple Assertion elements. The AuthenticationResponse contains all parsed assertions from the XML document.
1 parent b11137a commit c135ece

23 files changed

+573
-132
lines changed

build.savant

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jakartaXMLBindVersion = "4.0.0"
1919
slf4jVersion = "2.0.7"
2020
testngVersion = "7.8.0"
2121

22-
project(group: "io.fusionauth", name: "fusionauth-samlv2", version: "0.11.1", licenses: ["ApacheV2_0"]) {
22+
project(group: "io.fusionauth", name: "fusionauth-samlv2", version: "1.0.0", licenses: ["ApacheV2_0"]) {
2323
workflow {
2424
fetch {
2525
cache()

src/main/java/io/fusionauth/samlv2/domain/Assertion.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2019-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,17 +18,43 @@
1818
import java.util.HashMap;
1919
import java.util.List;
2020
import java.util.Map;
21+
import java.util.Map.Entry;
2122
import java.util.Objects;
23+
import java.util.stream.Collectors;
2224

2325
public class Assertion {
2426
public Map<String, List<String>> attributes = new HashMap<>();
2527

2628
public Conditions conditions;
2729

30+
public String id;
31+
2832
public String issuer;
2933

3034
public Subject subject;
3135

36+
public Assertion() {
37+
}
38+
39+
public Assertion(Assertion other) {
40+
this.attributes = other.attributes
41+
.entrySet()
42+
.stream()
43+
.collect(
44+
Collectors.toMap(
45+
Entry::getKey,
46+
entry -> entry.getValue()
47+
.stream()
48+
.map(String::new)
49+
.toList()
50+
)
51+
);
52+
this.conditions = other.conditions == null ? null : new Conditions(other.conditions);
53+
this.id = other.id;
54+
this.issuer = other.issuer;
55+
this.subject = other.subject == null ? null : new Subject(other.subject);
56+
}
57+
3258
@Override
3359
public boolean equals(Object o) {
3460
if (this == o) {
@@ -40,12 +66,13 @@ public boolean equals(Object o) {
4066
Assertion assertion = (Assertion) o;
4167
return Objects.equals(attributes, assertion.attributes) &&
4268
Objects.equals(conditions, assertion.conditions) &&
69+
Objects.equals(id, assertion.id) &&
4370
Objects.equals(issuer, assertion.issuer) &&
4471
Objects.equals(subject, assertion.subject);
4572
}
4673

4774
@Override
4875
public int hashCode() {
49-
return Objects.hash(attributes, conditions, issuer, subject);
76+
return Objects.hash(attributes, conditions, id, issuer, subject);
5077
}
5178
}

src/main/java/io/fusionauth/samlv2/domain/AuthenticationResponse.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2013-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616
package io.fusionauth.samlv2.domain;
1717

1818
import java.time.ZonedDateTime;
19+
import java.util.ArrayList;
20+
import java.util.List;
1921
import java.util.Objects;
2022

2123
/**
@@ -24,14 +26,25 @@
2426
* @author Brian Pontarelli
2527
*/
2628
public class AuthenticationResponse extends SAMLResponse {
27-
public Assertion assertion = new Assertion();
29+
public List<Assertion> assertions = new ArrayList<>();
2830

2931
public String rawResponse;
3032

3133
public ZonedDateTime sessionExpiry;
3234

3335
public String sessionIndex;
3436

37+
public AuthenticationResponse() {
38+
}
39+
40+
public AuthenticationResponse(AuthenticationResponse other) {
41+
super(other);
42+
this.assertions.addAll(other.assertions.stream().map(Assertion::new).toList());
43+
this.rawResponse = other.rawResponse;
44+
this.sessionExpiry = other.sessionExpiry;
45+
this.sessionIndex = other.sessionIndex;
46+
}
47+
3548
@Override
3649
public boolean equals(Object o) {
3750
if (this == o) {
@@ -46,13 +59,13 @@ public boolean equals(Object o) {
4659
AuthenticationResponse that = (AuthenticationResponse) o;
4760
// The comparison does not include the rawResponse because different raw encoded responses can be parsed into
4861
// identical domain objects. This is mainly true for responses containing an encrypted assertion
49-
return Objects.equals(assertion, that.assertion) &&
62+
return Objects.equals(assertions, that.assertions) &&
5063
Objects.equals(sessionExpiry, that.sessionExpiry) &&
5164
Objects.equals(sessionIndex, that.sessionIndex);
5265
}
5366

5467
@Override
5568
public int hashCode() {
56-
return Objects.hash(super.hashCode(), assertion, rawResponse, sessionExpiry, sessionIndex);
69+
return Objects.hash(super.hashCode(), assertions, rawResponse, sessionExpiry, sessionIndex);
5770
}
5871
}

src/main/java/io/fusionauth/samlv2/domain/Conditions.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2019-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,15 @@ public class Conditions {
2727

2828
public ZonedDateTime notOnOrAfter;
2929

30+
public Conditions() {
31+
}
32+
33+
public Conditions(Conditions other) {
34+
this.audiences.addAll(other.audiences);
35+
this.notBefore = other.notBefore;
36+
this.notOnOrAfter = other.notOnOrAfter;
37+
}
38+
3039
@Override
3140
public boolean equals(Object o) {
3241
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/NameID.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2019-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,15 @@ public class NameID {
2222

2323
public String id;
2424

25+
public NameID() {
26+
27+
}
28+
29+
public NameID(NameID other) {
30+
this.format = other.format;
31+
this.id = other.id;
32+
}
33+
2534
@Override
2635
public boolean equals(Object o) {
2736
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/SAMLRequest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2021-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,18 @@ public class SAMLRequest {
3636

3737
public String xml;
3838

39+
public SAMLRequest() {
40+
}
41+
42+
public SAMLRequest(SAMLRequest other) {
43+
this.destination = other.destination;
44+
this.id = other.id;
45+
this.issueInstant = other.issueInstant;
46+
this.issuer = other.issuer;
47+
this.version = other.version;
48+
this.xml = other.xml;
49+
}
50+
3951
@Override
4052
public boolean equals(Object o) {
4153
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/SAMLResponse.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2021-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,15 @@ public class SAMLResponse extends SAMLRequest {
2727

2828
public Status status = new Status();
2929

30+
public SAMLResponse() {
31+
}
32+
33+
public SAMLResponse(SAMLResponse other) {
34+
super(other);
35+
this.inResponseTo = other.inResponseTo;
36+
this.status = new Status(other.status);
37+
}
38+
3039
@Override
3140
public boolean equals(Object o) {
3241
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/Status.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2019-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,14 @@ public class Status {
2727

2828
public String message;
2929

30+
public Status() {
31+
}
32+
33+
public Status(Status other) {
34+
this.code = other.code;
35+
this.message = other.message;
36+
}
37+
3038
@Override
3139
public boolean equals(Object o) {
3240
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/Subject.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2019-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,14 @@ public class Subject {
2323

2424
public SubjectConfirmation subjectConfirmation;
2525

26+
public Subject() {
27+
}
28+
29+
public Subject(Subject other) {
30+
this.nameIDs = other.nameIDs == null ? null : other.nameIDs.stream().map(NameID::new).toList();
31+
this.subjectConfirmation = other.subjectConfirmation == null ? null : new SubjectConfirmation(other.subjectConfirmation);
32+
}
33+
2634
@Override
2735
public boolean equals(Object o) {
2836
if (this == o) {

src/main/java/io/fusionauth/samlv2/domain/SubjectConfirmation.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013-2024, Inversoft Inc., All Rights Reserved
2+
* Copyright (c) 2013-2025, Inversoft Inc., All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,6 +32,17 @@ public class SubjectConfirmation {
3232

3333
public String recipient;
3434

35+
public SubjectConfirmation() {
36+
}
37+
38+
public SubjectConfirmation(SubjectConfirmation subjectConfirmation) {
39+
this.address = subjectConfirmation.address;
40+
this.inResponseTo = subjectConfirmation.inResponseTo;
41+
this.method = subjectConfirmation.method;
42+
this.notOnOrAfter = subjectConfirmation.notOnOrAfter;
43+
this.recipient = subjectConfirmation.recipient;
44+
}
45+
3546
@Override
3647
public boolean equals(Object o) {
3748
if (this == o) {

0 commit comments

Comments
 (0)