1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.internet2.middleware.shibboleth.idp.profile.saml1;
18
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.xml.namespace.QName;
24
25 import org.joda.time.DateTime;
26 import org.opensaml.Configuration;
27 import org.opensaml.common.SAMLObject;
28 import org.opensaml.common.SAMLObjectBuilder;
29 import org.opensaml.common.SAMLVersion;
30 import org.opensaml.common.binding.encoding.SAMLMessageEncoder;
31 import org.opensaml.saml1.core.Assertion;
32 import org.opensaml.saml1.core.AttributeQuery;
33 import org.opensaml.saml1.core.AttributeStatement;
34 import org.opensaml.saml1.core.Audience;
35 import org.opensaml.saml1.core.AudienceRestrictionCondition;
36 import org.opensaml.saml1.core.Conditions;
37 import org.opensaml.saml1.core.ConfirmationMethod;
38 import org.opensaml.saml1.core.NameIdentifier;
39 import org.opensaml.saml1.core.RequestAbstractType;
40 import org.opensaml.saml1.core.Response;
41 import org.opensaml.saml1.core.ResponseAbstractType;
42 import org.opensaml.saml1.core.Statement;
43 import org.opensaml.saml1.core.Status;
44 import org.opensaml.saml1.core.StatusCode;
45 import org.opensaml.saml1.core.StatusMessage;
46 import org.opensaml.saml1.core.Subject;
47 import org.opensaml.saml1.core.SubjectConfirmation;
48 import org.opensaml.saml1.core.SubjectStatement;
49 import org.opensaml.saml2.metadata.SPSSODescriptor;
50 import org.opensaml.ws.message.encoder.MessageEncodingException;
51 import org.opensaml.xml.XMLObjectBuilder;
52 import org.opensaml.xml.io.Marshaller;
53 import org.opensaml.xml.io.MarshallingException;
54 import org.opensaml.xml.security.SecurityException;
55 import org.opensaml.xml.security.SecurityHelper;
56 import org.opensaml.xml.security.credential.Credential;
57 import org.opensaml.xml.signature.Signature;
58 import org.opensaml.xml.signature.SignatureException;
59 import org.opensaml.xml.signature.Signer;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62 import org.slf4j.helpers.MessageFormatter;
63
64 import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
65 import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
66 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncoder;
67 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncodingException;
68 import edu.internet2.middleware.shibboleth.common.attribute.encoding.SAML1NameIdentifierEncoder;
69 import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
70 import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
71 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
72 import edu.internet2.middleware.shibboleth.common.profile.provider.BaseSAMLProfileRequestContext;
73 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.CryptoOperationRequirementLevel;
74 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.AbstractSAML1ProfileConfiguration;
75 import edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler;
76 import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
77 import edu.internet2.middleware.shibboleth.idp.session.Session;
78
79
80 public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHandler {
81
82
83 public static final SAMLVersion SAML_VERSION = SAMLVersion.VERSION_11;
84
85
86 private static Logger log = LoggerFactory.getLogger(AbstractSAML1ProfileHandler.class);
87
88
89 private SAMLObjectBuilder<Response> responseBuilder;
90
91
92 private SAMLObjectBuilder<Assertion> assertionBuilder;
93
94
95 private SAMLObjectBuilder<Conditions> conditionsBuilder;
96
97
98 private SAMLObjectBuilder<AudienceRestrictionCondition> audienceRestrictionConditionBuilder;
99
100
101 private SAMLObjectBuilder<Audience> audienceBuilder;
102
103
104 private SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder;
105
106
107 private SAMLObjectBuilder<ConfirmationMethod> confirmationMethodBuilder;
108
109
110 private SAMLObjectBuilder<Subject> subjectBuilder;
111
112
113 private SAMLObjectBuilder<Status> statusBuilder;
114
115
116 private SAMLObjectBuilder<StatusCode> statusCodeBuilder;
117
118
119 private SAMLObjectBuilder<StatusMessage> statusMessageBuilder;
120
121
122 private XMLObjectBuilder<Signature> signatureBuilder;
123
124
125
126
127 @SuppressWarnings("unchecked")
128 public AbstractSAML1ProfileHandler() {
129 super();
130 responseBuilder = (SAMLObjectBuilder<Response>) getBuilderFactory().getBuilder(Response.DEFAULT_ELEMENT_NAME);
131 assertionBuilder = (SAMLObjectBuilder<Assertion>) getBuilderFactory()
132 .getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
133 conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory().getBuilder(
134 Conditions.DEFAULT_ELEMENT_NAME);
135 audienceRestrictionConditionBuilder = (SAMLObjectBuilder<AudienceRestrictionCondition>) getBuilderFactory()
136 .getBuilder(AudienceRestrictionCondition.DEFAULT_ELEMENT_NAME);
137 audienceBuilder = (SAMLObjectBuilder<Audience>) getBuilderFactory().getBuilder(Audience.DEFAULT_ELEMENT_NAME);
138 subjectConfirmationBuilder = (SAMLObjectBuilder<SubjectConfirmation>) getBuilderFactory().getBuilder(
139 SubjectConfirmation.DEFAULT_ELEMENT_NAME);
140 confirmationMethodBuilder = (SAMLObjectBuilder<ConfirmationMethod>) getBuilderFactory().getBuilder(
141 ConfirmationMethod.DEFAULT_ELEMENT_NAME);
142 subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(Subject.DEFAULT_ELEMENT_NAME);
143 statusBuilder = (SAMLObjectBuilder<Status>) getBuilderFactory().getBuilder(Status.DEFAULT_ELEMENT_NAME);
144 statusCodeBuilder = (SAMLObjectBuilder<StatusCode>) getBuilderFactory().getBuilder(
145 StatusCode.DEFAULT_ELEMENT_NAME);
146 statusMessageBuilder = (SAMLObjectBuilder<StatusMessage>) getBuilderFactory().getBuilder(
147 StatusMessage.DEFAULT_ELEMENT_NAME);
148 signatureBuilder = (XMLObjectBuilder<Signature>) getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME);
149 }
150
151
152 protected void populateRequestContext(BaseSAMLProfileRequestContext requestContext) throws ProfileException {
153 BaseSAML1ProfileRequestContext saml1Request = (BaseSAML1ProfileRequestContext) requestContext;
154 try {
155 super.populateRequestContext(requestContext);
156 } catch (ProfileException e) {
157 if (saml1Request.getFailureStatus() == null) {
158 saml1Request.setFailureStatus(buildStatus(StatusCode.REQUESTER, null, e.getMessage()));
159 }
160 throw e;
161 }
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175 protected void populateUserInformation(BaseSAMLProfileRequestContext requestContext) {
176 Session userSession = getUserSession(requestContext.getInboundMessageTransport());
177 if (userSession == null) {
178 NameIdentifier subject = (NameIdentifier) requestContext.getSubjectNameIdentifier();
179 if (subject != null && subject.getNameIdentifier() != null) {
180 userSession = getUserSession(subject.getNameIdentifier());
181 }
182 }
183
184 if (userSession != null) {
185 requestContext.setUserSession(userSession);
186 requestContext.setPrincipalName(userSession.getPrincipalName());
187 ServiceInformation serviceInfo = userSession.getServicesInformation().get(
188 requestContext.getInboundMessageIssuer());
189 if (serviceInfo != null) {
190 requestContext.setPrincipalAuthenticationMethod(serviceInfo.getAuthenticationMethod()
191 .getAuthenticationMethod());
192 }
193 }
194 }
195
196
197
198
199
200
201
202
203 protected void checkSamlVersion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
204 SAMLObject samlObject = requestContext.getInboundSAMLMessage();
205
206 if (samlObject instanceof RequestAbstractType) {
207 RequestAbstractType request = (RequestAbstractType) samlObject;
208 if (request.getMajorVersion() < 1) {
209 requestContext.setFailureStatus(buildStatus(StatusCode.REQUESTER, StatusCode.REQUEST_VERSION_TOO_LOW,
210 null));
211 throw new ProfileException("SAML request major version too low");
212 } else if (request.getMajorVersion() > 1) {
213 requestContext.setFailureStatus(buildStatus(StatusCode.REQUESTER, StatusCode.REQUEST_VERSION_TOO_HIGH,
214 null));
215 throw new ProfileException("SAML request major version too low");
216 }
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230 protected Response buildResponse(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, List<Statement> statements)
231 throws ProfileException {
232
233 DateTime issueInstant = new DateTime();
234
235
236 Response samlResponse = responseBuilder.buildObject();
237 samlResponse.setIssueInstant(issueInstant);
238 populateStatusResponse(requestContext, samlResponse);
239
240
241 Assertion assertion = null;
242 if (statements != null && !statements.isEmpty()) {
243 assertion = buildAssertion(requestContext, issueInstant);
244 assertion.getStatements().addAll(statements);
245 samlResponse.getAssertions().add(assertion);
246 signAssertion(requestContext, assertion);
247 }
248
249 Status status = buildStatus(StatusCode.SUCCESS, null, null);
250 samlResponse.setStatus(status);
251
252 return samlResponse;
253 }
254
255
256
257
258
259
260
261
262
263 protected Assertion buildAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, DateTime issueInstant) {
264 Assertion assertion = assertionBuilder.buildObject();
265 assertion.setID(getIdGenerator().generateIdentifier());
266 assertion.setIssueInstant(issueInstant);
267 assertion.setVersion(SAMLVersion.VERSION_11);
268 assertion.setIssuer(requestContext.getLocalEntityId());
269
270 Conditions conditions = buildConditions(requestContext, issueInstant);
271 assertion.setConditions(conditions);
272
273 return assertion;
274 }
275
276
277
278
279
280
281
282
283
284
285 protected Conditions buildConditions(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, DateTime issueInstant) {
286 AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
287
288 Conditions conditions = conditionsBuilder.buildObject();
289 conditions.setNotBefore(issueInstant);
290 conditions.setNotOnOrAfter(issueInstant.plus(profileConfig.getAssertionLifetime()));
291
292 Collection<String> audiences;
293
294 AudienceRestrictionCondition audienceRestriction = audienceRestrictionConditionBuilder.buildObject();
295 conditions.getAudienceRestrictionConditions().add(audienceRestriction);
296
297 Audience audience = audienceBuilder.buildObject();
298 audience.setUri(requestContext.getInboundMessageIssuer());
299 audienceRestriction.getAudiences().add(audience);
300
301
302 audiences = profileConfig.getAssertionAudiences();
303 if (audiences != null && audiences.size() > 0) {
304 for (String audienceUri : audiences) {
305 audience = audienceBuilder.buildObject();
306 audience.setUri(audienceUri);
307 audienceRestriction.getAudiences().add(audience);
308 }
309 }
310
311 return conditions;
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325 protected Subject buildSubject(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, String confirmationMethod)
326 throws ProfileException {
327
328 ConfirmationMethod method = confirmationMethodBuilder.buildObject();
329 method.setConfirmationMethod(confirmationMethod);
330
331 SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
332 subjectConfirmation.getConfirmationMethods().add(method);
333
334 NameIdentifier nameID = buildNameId(requestContext);
335
336 Subject subject = subjectBuilder.buildObject();
337 subject.setSubjectConfirmation(subjectConfirmation);
338
339 if (nameID != null) {
340 subject.setNameIdentifier(nameID);
341 requestContext.setSubjectNameIdentifier(nameID);
342 }
343
344 return subject;
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361 protected NameIdentifier buildNameId(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext)
362 throws ProfileException {
363 if(requestContext.getAttributes() == null){
364 return null;
365 }
366
367 log.debug("Attemping to build NameIdentifier for principal '{}' in response to request from relying party '{}",
368 requestContext.getPrincipalName(), requestContext.getInboundMessageIssuer());
369
370 List<String> supportedNameFormats = getNameFormats(requestContext);
371 if (!supportedNameFormats.isEmpty()) {
372 log.debug("Relying party '{}' supports the name formats: {}", requestContext.getInboundMessageIssuer(),
373 supportedNameFormats);
374 } else {
375 log.debug("Relying party '{}' indicated no preferred name formats", requestContext
376 .getInboundMessageIssuer());
377 }
378
379 Map<String, BaseAttribute> principalAttributes = requestContext.getAttributes();
380 if (principalAttributes == null || principalAttributes.isEmpty()) {
381 log.debug("No attributes for principal '{}', no NameIdentifier will be created for relying party '{}'",
382 requestContext.getPrincipalName(), requestContext.getInboundMessageIssuer());
383 return null;
384 }
385
386 BaseAttribute<?> nameIdAttribute = null;
387 SAML1NameIdentifierEncoder nameIdEncoder = null;
388 ATTRIBUTESELECT: for (BaseAttribute<?> attribute : principalAttributes.values()) {
389 if (attribute == null) {
390 continue;
391 }
392 for (AttributeEncoder encoder : attribute.getEncoders()) {
393 if (encoder == null) {
394 continue;
395 }
396 if (encoder instanceof SAML1NameIdentifierEncoder) {
397 nameIdEncoder = (SAML1NameIdentifierEncoder) encoder;
398 if (supportedNameFormats.isEmpty() || supportedNameFormats.contains(nameIdEncoder.getNameFormat())) {
399 nameIdAttribute = attribute;
400 break ATTRIBUTESELECT;
401 }
402 }
403 }
404 }
405
406 if (nameIdAttribute == null || nameIdEncoder == null) {
407 log.debug("No attributes for principal '{}' supports encoding into a supported NameIdentifier format for relying party '{}'",
408 requestContext.getPrincipalName(), requestContext.getInboundMessageIssuer());
409 return null;
410 }
411
412 try {
413 log.debug("Using attribute '{}' supporting name format '{}' to create the NameIdentifier for relying party '{}'",
414 new Object[] { nameIdAttribute.getId(), nameIdEncoder.getNameFormat(), requestContext.getInboundMessageIssuer(), });
415 return nameIdEncoder.encode(nameIdAttribute);
416 } catch (AttributeEncodingException e) {
417 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Unable to encode NameIdentifier"));
418 String msg = MessageFormatter.format("Unable to encode NameIdentifier for relying party '{}'",
419 requestContext.getInboundMessageIssuer());
420 log.error(msg, e);
421 throw new ProfileException(msg, e);
422 }
423 }
424
425
426
427
428
429
430
431
432 protected Response buildErrorResponse(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) {
433 Response samlResponse = responseBuilder.buildObject();
434 samlResponse.setIssueInstant(new DateTime());
435 populateStatusResponse(requestContext, samlResponse);
436
437 samlResponse.setStatus(requestContext.getFailureStatus());
438
439 return samlResponse;
440 }
441
442
443
444
445
446
447
448 protected void populateStatusResponse(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext,
449 ResponseAbstractType response) {
450 response.setID(getIdGenerator().generateIdentifier());
451
452 SAMLObject samlMessage = requestContext.getInboundSAMLMessage();
453 if (samlMessage != null && samlMessage instanceof RequestAbstractType) {
454 response.setInResponseTo(((RequestAbstractType) samlMessage).getID());
455 }
456
457 response.setVersion(SAMLVersion.VERSION_11);
458 }
459
460
461
462
463
464
465
466
467
468
469 protected Status buildStatus(QName topLevelCode, QName secondLevelCode, String failureMessage) {
470 Status status = statusBuilder.buildObject();
471
472 StatusCode statusCode = statusCodeBuilder.buildObject();
473 statusCode.setValue(topLevelCode);
474 status.setStatusCode(statusCode);
475
476 if (secondLevelCode != null) {
477 StatusCode secondLevelStatusCode = statusCodeBuilder.buildObject();
478 secondLevelStatusCode.setValue(secondLevelCode);
479 statusCode.setStatusCode(secondLevelStatusCode);
480 }
481
482 if (failureMessage != null) {
483 StatusMessage msg = statusMessageBuilder.buildObject();
484 msg.setMessage(failureMessage);
485 status.setStatusMessage(msg);
486 }
487
488 return status;
489 }
490
491
492
493
494
495
496 protected void resolveAttributes(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
497 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
498 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
499
500 try {
501 log.debug("Resolving attributes for principal '{}' for SAML request from relying party '{}'",
502 requestContext.getPrincipalName(), requestContext.getInboundMessageIssuer());
503 Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
504
505 requestContext.setAttributes(principalAttributes);
506 } catch (AttributeRequestException e) {
507 log.warn("Error resolving attributes for principal '{}'. No name identifier or attribute statement will be included in response",
508 requestContext.getPrincipalName());
509 }
510 }
511
512
513
514
515
516
517
518
519
520
521
522 protected AttributeStatement buildAttributeStatement(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext,
523 String subjectConfMethod) throws ProfileException {
524
525 if(requestContext.getAttributes() == null){
526 return null;
527 }
528
529 log.debug(
530 "Creating attribute statement about principal '{}'in response to SAML request from relying party '{}'",
531 requestContext.getPrincipalName(), requestContext.getInboundMessageIssuer());
532 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
533 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
534
535 try {
536 AttributeStatement statment;
537 if (requestContext.getInboundSAMLMessage() instanceof AttributeQuery) {
538 statment = attributeAuthority.buildAttributeStatement((AttributeQuery) requestContext
539 .getInboundSAMLMessage(), requestContext.getAttributes().values());
540 } else {
541 statment = attributeAuthority.buildAttributeStatement(null, requestContext.getAttributes().values());
542 }
543
544 if (statment != null) {
545 Subject statementSubject = buildSubject(requestContext, subjectConfMethod);
546 statment.setSubject(statementSubject);
547 }
548
549 return statment;
550 } catch (AttributeRequestException e) {
551 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
552 String msg = MessageFormatter.format("Error encoding attributes for principal '{}'", requestContext
553 .getPrincipalName());
554 log.error(msg, e);
555 throw new ProfileException(msg, e);
556 }
557 }
558
559
560
561
562
563
564
565
566 protected void resolvePrincipal(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
567 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
568 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
569
570 log.debug("Resolving principal name for subject of SAML request from relying party '{}'", requestContext
571 .getInboundMessageIssuer());
572
573 try {
574 String principal = attributeAuthority.getPrincipal(requestContext);
575 requestContext.setPrincipalName(principal);
576 } catch (AttributeRequestException e) {
577 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
578 "Error resolving principal"));
579 String msg = MessageFormatter.format(
580 "Error resolving principal name for SAML request from relying party '{}'", requestContext
581 .getInboundMessageIssuer());
582 log.warn(msg, e);
583 throw new ProfileException(msg, e);
584 }
585 }
586
587
588
589
590
591
592
593
594
595
596
597 protected void signAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
598 throws ProfileException {
599 log.debug("Determining if SAML assertion to relying party '{}' should be signed", requestContext
600 .getInboundMessageIssuer());
601
602 boolean signAssertion = isSignAssertion(requestContext);
603
604 if (!signAssertion) {
605 return;
606 }
607
608 AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
609
610 log.debug("Determining credential to use to sign assertion to relying party '{}'", requestContext
611 .getInboundMessageIssuer());
612 Credential signatureCredential = profileConfig.getSigningCredential();
613 if (signatureCredential == null) {
614 signatureCredential = requestContext.getRelyingPartyConfiguration().getDefaultSigningCredential();
615 }
616
617 if (signatureCredential == null) {
618 String msg = MessageFormatter.format(
619 "No signing credential is specified for relying party configuration '{}'", requestContext
620 .getRelyingPartyConfiguration().getProviderId());
621 log.warn(msg);
622 throw new ProfileException(msg);
623 }
624
625 log.debug("Signing assertion to relying party '{}'", requestContext.getInboundMessageIssuer());
626 Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
627
628 signature.setSigningCredential(signatureCredential);
629 try {
630
631
632 SecurityHelper.prepareSignatureParams(signature, signatureCredential, null, null);
633 } catch (SecurityException e) {
634 String msg = "Error preparing signature for signing";
635 log.error(msg);
636 throw new ProfileException(msg, e);
637 }
638
639 assertion.setSignature(signature);
640
641 Marshaller assertionMarshaller = Configuration.getMarshallerFactory().getMarshaller(assertion);
642 try {
643 assertionMarshaller.marshall(assertion);
644 Signer.signObject(signature);
645 } catch (MarshallingException e) {
646 String errMsg = "Unable to marshall assertion for signing";
647 log.error(errMsg, e);
648 throw new ProfileException(errMsg, e);
649 } catch (SignatureException e) {
650 String msg = "Unable to sign assertion";
651 log.error(msg, e);
652 throw new ProfileException(msg, e);
653 }
654 }
655
656
657
658
659
660
661
662
663 protected boolean isSignAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
664
665 SAMLMessageEncoder encoder = getOutboundMessageEncoder(requestContext);
666 AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
667
668 try {
669 boolean signAssertion = profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.always
670 || (profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.conditional
671 && !encoder.providesMessageIntegrity(requestContext));
672
673 log.debug("IdP relying party configuration '{}' indicates to sign assertions: {}", requestContext
674 .getRelyingPartyConfiguration().getRelyingPartyId(), signAssertion);
675
676 if (!signAssertion && requestContext.getPeerEntityRoleMetadata() instanceof SPSSODescriptor) {
677 SPSSODescriptor ssoDescriptor = (SPSSODescriptor) requestContext.getPeerEntityRoleMetadata();
678 if (ssoDescriptor.getWantAssertionsSigned() != null) {
679 signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
680 log.debug("Entity metadata for relying party '{} 'indicates to sign assertions: {}", requestContext
681 .getInboundMessageIssuer(), signAssertion);
682 }
683 }
684
685 return signAssertion;
686 } catch (MessageEncodingException e) {
687 log.error("Unable to determine if outbound encoding '{}' provides message integrity protection",
688 encoder.getBindingURI());
689 throw new ProfileException("Unable to determine if outbound assertion should be signed");
690 }
691 }
692
693
694
695
696
697
698 protected void writeAuditLogEntry(BaseSAMLProfileRequestContext context) {
699 SAML1AuditLogEntry auditLogEntry = new SAML1AuditLogEntry();
700 auditLogEntry.setSAMLResponse((Response) context.getOutboundSAMLMessage());
701 auditLogEntry.setMessageProfile(getProfileId());
702 auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
703 auditLogEntry.setPrincipalName(context.getPrincipalName());
704 auditLogEntry.setAssertingPartyId(context.getLocalEntityId());
705 auditLogEntry.setRelyingPartyId(context.getInboundMessageIssuer());
706 auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
707 auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
708 auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
709 auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
710 if (context.getReleasedAttributes() != null) {
711 auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
712 }
713
714 getAduitLog().info(auditLogEntry.toString());
715 }
716
717
718 protected class SAML1AuditLogEntry extends AuditLogEntry {
719
720
721 private Response samlResponse;
722
723
724
725
726
727
728 public Response getSAMLResponse() {
729 return samlResponse;
730 }
731
732
733
734
735
736
737 public void setSAMLResponse(Response response) {
738 samlResponse = response;
739 }
740
741
742 public String toString() {
743 StringBuilder entryString = new StringBuilder(super.toString());
744
745 NameIdentifier nameIdentifier = null;
746 StringBuilder assertionIds = new StringBuilder();
747 List<Assertion> assertions = samlResponse.getAssertions();
748 if (assertions != null && !assertions.isEmpty()) {
749 for (Assertion assertion : assertions) {
750 assertionIds.append(assertion.getID());
751 assertionIds.append(",");
752
753 if (nameIdentifier == null) {
754 List<Statement> statements = assertion.getStatements();
755 if (statements != null && !statements.isEmpty()) {
756 for (Statement statement : statements) {
757 if (statement instanceof SubjectStatement) {
758 if (((SubjectStatement) statement).getSubject() != null) {
759 nameIdentifier = ((SubjectStatement) statement).getSubject()
760 .getNameIdentifier();
761 }
762 }
763 }
764 }
765 }
766 }
767 }
768
769 if (nameIdentifier != null) {
770 entryString.append(nameIdentifier.getNameIdentifier());
771 }
772 entryString.append("|");
773
774 entryString.append(assertionIds.toString());
775 entryString.append("|");
776
777 return entryString.toString();
778 }
779 }
780 }