1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.validate;
21
22 import java.util.List;
23
24 import org.apache.ws.security.WSSecurityException;
25 import org.apache.ws.security.handler.RequestData;
26 import org.apache.ws.security.saml.SAMLKeyInfo;
27 import org.apache.ws.security.saml.ext.AssertionWrapper;
28 import org.apache.ws.security.saml.ext.OpenSAMLUtil;
29 import org.joda.time.DateTime;
30 import org.opensaml.common.SAMLVersion;
31 import org.opensaml.xml.validation.ValidationException;
32 import org.opensaml.xml.validation.ValidatorSuite;
33
34
35
36
37
38
39
40
41 public class SamlAssertionValidator extends SignatureTrustValidator {
42
43 private static final org.apache.commons.logging.Log LOG =
44 org.apache.commons.logging.LogFactory.getLog(SamlAssertionValidator.class);
45
46
47
48
49
50 private int futureTTL = 60;
51
52
53
54
55
56 public void setFutureTTL(int newFutureTTL) {
57 futureTTL = newFutureTTL;
58 }
59
60
61
62
63
64
65
66
67
68 public Credential validate(Credential credential, RequestData data) throws WSSecurityException {
69 if (credential == null || credential.getAssertion() == null) {
70 throw new WSSecurityException(WSSecurityException.FAILURE, "noCredential");
71 }
72 AssertionWrapper assertion = credential.getAssertion();
73
74
75 String confirmMethod = null;
76 List<String> methods = assertion.getConfirmationMethods();
77 if (methods != null && methods.size() > 0) {
78 confirmMethod = methods.get(0);
79 }
80 if (OpenSAMLUtil.isMethodHolderOfKey(confirmMethod)) {
81 if (assertion.getSubjectKeyInfo() == null) {
82 LOG.debug("There is no Subject KeyInfo to match the holder-of-key subject conf method");
83 throw new WSSecurityException(WSSecurityException.FAILURE, "noKeyInSAMLToken");
84 }
85
86 if (!assertion.isSigned()) {
87 LOG.debug("A holder-of-key assertion must be signed");
88 throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity");
89 }
90 }
91
92
93 checkConditions(assertion);
94
95
96 validateAssertion(assertion);
97
98
99 if (assertion.isSigned()) {
100 verifySignedAssertion(assertion, data);
101 }
102 return credential;
103 }
104
105
106
107
108
109
110
111
112
113 protected Credential verifySignedAssertion(
114 AssertionWrapper assertion,
115 RequestData data
116 ) throws WSSecurityException {
117 Credential trustCredential = new Credential();
118 SAMLKeyInfo samlKeyInfo = assertion.getSignatureKeyInfo();
119 trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
120 trustCredential.setCertificates(samlKeyInfo.getCerts());
121 return super.validate(trustCredential, data);
122 }
123
124
125
126
127 protected void checkConditions(AssertionWrapper assertion) throws WSSecurityException {
128 DateTime validFrom = null;
129 DateTime validTill = null;
130 if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)
131 && assertion.getSaml2().getConditions() != null) {
132 validFrom = assertion.getSaml2().getConditions().getNotBefore();
133 validTill = assertion.getSaml2().getConditions().getNotOnOrAfter();
134 } else if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_11)
135 && assertion.getSaml1().getConditions() != null) {
136 validFrom = assertion.getSaml1().getConditions().getNotBefore();
137 validTill = assertion.getSaml1().getConditions().getNotOnOrAfter();
138 }
139
140 if (validFrom != null) {
141 DateTime currentTime = new DateTime();
142 currentTime = currentTime.plusSeconds(futureTTL);
143 if (validFrom.isAfter(currentTime)) {
144 LOG.debug("SAML Token condition (Not Before) not met");
145 throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity");
146 }
147 }
148
149 if (validTill != null && validTill.isBeforeNow()) {
150 LOG.debug("SAML Token condition (Not On Or After) not met");
151 throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity");
152 }
153 }
154
155
156
157
158 protected void validateAssertion(AssertionWrapper assertion) throws WSSecurityException {
159 if (assertion.getSaml1() != null) {
160 ValidatorSuite schemaValidators =
161 org.opensaml.Configuration.getValidatorSuite("saml1-schema-validator");
162 ValidatorSuite specValidators =
163 org.opensaml.Configuration.getValidatorSuite("saml1-spec-validator");
164 try {
165 schemaValidators.validate(assertion.getSaml1());
166 specValidators.validate(assertion.getSaml1());
167 } catch (ValidationException e) {
168 LOG.debug("Saml Validation error: " + e.getMessage(), e);
169 throw new WSSecurityException(
170 WSSecurityException.FAILURE, "invalidSAMLsecurity", null, e
171 );
172 }
173 } else if (assertion.getSaml2() != null) {
174 ValidatorSuite schemaValidators =
175 org.opensaml.Configuration.getValidatorSuite("saml2-core-schema-validator");
176 ValidatorSuite specValidators =
177 org.opensaml.Configuration.getValidatorSuite("saml2-core-spec-validator");
178 try {
179 schemaValidators.validate(assertion.getSaml2());
180 specValidators.validate(assertion.getSaml2());
181 } catch (ValidationException e) {
182 LOG.debug("Saml Validation error: " + e.getMessage(), e);
183 throw new WSSecurityException(
184 WSSecurityException.FAILURE, "invalidSAMLsecurity", null, e
185 );
186 }
187 }
188 }
189
190 }