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.RoleDescriptor;
50 import org.opensaml.saml2.metadata.SPSSODescriptor;
51 import org.opensaml.ws.message.encoder.MessageEncodingException;
52 import org.opensaml.xml.XMLObjectBuilder;
53 import org.opensaml.xml.io.Marshaller;
54 import org.opensaml.xml.io.MarshallingException;
55 import org.opensaml.xml.security.SecurityException;
56 import org.opensaml.xml.security.SecurityHelper;
57 import org.opensaml.xml.security.credential.Credential;
58 import org.opensaml.xml.signature.Signature;
59 import org.opensaml.xml.signature.SignatureException;
60 import org.opensaml.xml.signature.Signer;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
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 log.debug("Building assertion NameIdentifier to relying party {} for principal {}", requestContext
364 .getInboundMessageIssuer(), requestContext.getPrincipalName());
365
366 List<String> supportedNameFormats = getNameFormats(requestContext);
367 if (!supportedNameFormats.isEmpty()) {
368 log.debug("SP-supported name formats: {}", supportedNameFormats);
369 } else {
370 log.debug("SP indicated no preferred name formats.");
371 }
372
373 Map<String, BaseAttribute> principalAttributes = requestContext.getAttributes();
374 if (principalAttributes == null || principalAttributes.isEmpty()) {
375 log.debug("No attributes for principal {}, no name identifier will be created.", requestContext
376 .getPrincipalName());
377 return null;
378 }
379
380 SAML1NameIdentifierEncoder nameIdEncoder;
381 try {
382 for (BaseAttribute<?> attribute : principalAttributes.values()) {
383 for (AttributeEncoder encoder : attribute.getEncoders()) {
384 if (encoder instanceof SAML1NameIdentifierEncoder) {
385 nameIdEncoder = (SAML1NameIdentifierEncoder) encoder;
386 if (supportedNameFormats.isEmpty()
387 || supportedNameFormats.contains(nameIdEncoder.getNameFormat())) {
388 log.debug("Using attribute {} supporting name format {} to create the NameIdentifier",
389 attribute.getId(), nameIdEncoder.getNameFormat());
390 return nameIdEncoder.encode(attribute);
391 }
392 }
393 }
394 }
395
396 log.debug("No attributes for principal {} support an encoding into a supported name ID format.",
397 requestContext.getPrincipalName());
398 return null;
399 } catch (AttributeEncodingException e) {
400 log.error("Unable to construct NameIdentifier", e);
401 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null,
402 "Unable to construct NameIdentifier"));
403 throw new ProfileException("Unable to encode NameIdentifier attribute", e);
404 }
405 }
406
407
408
409
410
411
412
413
414 protected Response buildErrorResponse(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) {
415 Response samlResponse = responseBuilder.buildObject();
416 samlResponse.setIssueInstant(new DateTime());
417 populateStatusResponse(requestContext, samlResponse);
418
419 samlResponse.setStatus(requestContext.getFailureStatus());
420
421 return samlResponse;
422 }
423
424
425
426
427
428
429
430 protected void populateStatusResponse(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext,
431 ResponseAbstractType response) {
432 response.setID(getIdGenerator().generateIdentifier());
433
434 if (requestContext != null) {
435 SAMLObject samlMessage = requestContext.getInboundSAMLMessage();
436 if (samlMessage != null && samlMessage instanceof RequestAbstractType) {
437 response.setInResponseTo(((RequestAbstractType) samlMessage).getID());
438 }
439 }
440
441 response.setVersion(SAMLVersion.VERSION_11);
442 }
443
444
445
446
447
448
449
450
451
452
453 protected Status buildStatus(QName topLevelCode, QName secondLevelCode, String failureMessage) {
454 Status status = statusBuilder.buildObject();
455
456 StatusCode statusCode = statusCodeBuilder.buildObject();
457 statusCode.setValue(topLevelCode);
458 status.setStatusCode(statusCode);
459
460 if (secondLevelCode != null) {
461 StatusCode secondLevelStatusCode = statusCodeBuilder.buildObject();
462 secondLevelStatusCode.setValue(secondLevelCode);
463 statusCode.setStatusCode(secondLevelStatusCode);
464 }
465
466 if (failureMessage != null) {
467 StatusMessage msg = statusMessageBuilder.buildObject();
468 msg.setMessage(failureMessage);
469 status.setStatusMessage(msg);
470 }
471
472 return status;
473 }
474
475
476
477
478
479
480
481
482 protected void resolveAttributes(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
483 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
484 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
485
486 try {
487 log.debug("Resolving attributes for principal {} of SAML request from relying party {}", requestContext
488 .getPrincipalName(), requestContext.getInboundMessageIssuer());
489 Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
490
491 requestContext.setAttributes(principalAttributes);
492 } catch (AttributeRequestException e) {
493 log.error("Error resolving attributes for SAML request from relying party "
494 + requestContext.getInboundMessageIssuer(), e);
495 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
496 throw new ProfileException("Error resolving attributes for SAML request from relying party "
497 + requestContext.getInboundMessageIssuer(), e);
498 }
499 }
500
501
502
503
504
505
506
507
508
509
510
511 protected AttributeStatement buildAttributeStatement(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext,
512 String subjectConfMethod) throws ProfileException {
513
514 log.debug("Creating attribute statement in response to SAML request from relying party {}", requestContext
515 .getInboundMessageIssuer());
516 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
517 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
518
519 try {
520 AttributeStatement statment;
521 if (requestContext.getInboundSAMLMessage() instanceof AttributeQuery) {
522 statment = attributeAuthority.buildAttributeStatement((AttributeQuery) requestContext
523 .getInboundSAMLMessage(), requestContext.getAttributes().values());
524 } else {
525 statment = attributeAuthority.buildAttributeStatement(null, requestContext.getAttributes().values());
526 }
527
528 if (statment != null) {
529 Subject statementSubject = buildSubject(requestContext, subjectConfMethod);
530 statment.setSubject(statementSubject);
531 }
532
533 return statment;
534 } catch (AttributeRequestException e) {
535 log.error("Error encoding attributes for principal " + requestContext.getPrincipalName(), e);
536 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
537 throw new ProfileException("Error encoding attributes for principal " + requestContext.getPrincipalName(),
538 e);
539 }
540 }
541
542
543
544
545
546
547
548
549 protected void resolvePrincipal(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
550 AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
551 SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
552
553 log.debug("Resolving principal name for subject of SAML request from relying party {}", requestContext
554 .getInboundMessageIssuer());
555
556 try {
557 String principal = attributeAuthority.getPrincipal(requestContext);
558 requestContext.setPrincipalName(principal);
559 } catch (AttributeRequestException e) {
560 log.error("Error resolving attributes for SAML request from relying party "
561 + requestContext.getInboundMessageIssuer(), e);
562 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
563 "Error resolving principal"));
564 throw new ProfileException("Error resolving attributes for SAML request from relying party "
565 + requestContext.getInboundMessageIssuer(), e);
566 }
567 }
568
569
570
571
572
573
574
575
576
577
578
579 protected void signAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
580 throws ProfileException {
581 log.debug("Determining if SAML assertion to relying party {} should be signed", requestContext
582 .getInboundMessageIssuer());
583
584 boolean signAssertion = false;
585
586 RoleDescriptor relyingPartyRole = requestContext.getPeerEntityRoleMetadata();
587 SAMLMessageEncoder encoder = getMessageEncoders().get(requestContext.getPeerEntityEndpoint().getBinding());
588 AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
589
590 try {
591 if (profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.always
592 || (profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.conditional && !encoder
593 .providesMessageIntegrity(requestContext))) {
594 signAssertion = true;
595 log.debug("IdP relying party configuration {} indicates to sign assertions: {}", requestContext
596 .getRelyingPartyConfiguration().getRelyingPartyId(), signAssertion);
597 }
598 } catch (MessageEncodingException e) {
599 log.error("Unable to determine if outbound encoding {} can provide integrity", encoder.getBindingURI());
600 throw new ProfileException("Unable to determine if outbound message should be signed");
601 }
602
603 if (!signAssertion && relyingPartyRole instanceof SPSSODescriptor) {
604 SPSSODescriptor ssoDescriptor = (SPSSODescriptor) relyingPartyRole;
605 if (ssoDescriptor.getWantAssertionsSigned() != null) {
606 signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
607 log.debug("Entity metadata for relying party {} indicates to sign assertions: {}", requestContext
608 .getInboundMessageIssuer(), signAssertion);
609 }
610 }
611
612 if (!signAssertion) {
613 return;
614 }
615
616 log.debug("Determining signing credntial for assertion to relying party {}", requestContext
617 .getInboundMessageIssuer());
618 Credential signatureCredential = profileConfig.getSigningCredential();
619 if (signatureCredential == null) {
620 signatureCredential = requestContext.getRelyingPartyConfiguration().getDefaultSigningCredential();
621 }
622
623 if (signatureCredential == null) {
624 throw new ProfileException("No signing credential is specified for relying party configuration "
625 + requestContext.getRelyingPartyConfiguration().getProviderId()
626 + " or it's SAML2 attribute query profile configuration");
627 }
628
629 log.debug("Signing assertion to relying party {}", requestContext.getInboundMessageIssuer());
630 Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
631
632 signature.setSigningCredential(signatureCredential);
633 try {
634
635
636 SecurityHelper.prepareSignatureParams(signature, signatureCredential, null, null);
637 } catch (SecurityException e) {
638 throw new ProfileException("Error preparing signature for signing", e);
639 }
640
641 assertion.setSignature(signature);
642
643 Marshaller assertionMarshaller = Configuration.getMarshallerFactory().getMarshaller(assertion);
644 try {
645 assertionMarshaller.marshall(assertion);
646 Signer.signObject(signature);
647 } catch (MarshallingException e) {
648 log.error("Unable to marshall assertion for signing", e);
649 throw new ProfileException("Unable to marshall assertion for signing", e);
650 } catch (SignatureException e) {
651 log.error("Unable to sign assertion", e);
652 throw new ProfileException("Unable to sign assertion", e);
653 }
654 }
655
656
657
658
659
660
661 protected void writeAuditLogEntry(BaseSAMLProfileRequestContext context) {
662 SAML1AuditLogEntry auditLogEntry = new SAML1AuditLogEntry();
663 auditLogEntry.setSAMLResponse((Response) context.getOutboundSAMLMessage());
664 auditLogEntry.setMessageProfile(getProfileId());
665 auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
666 auditLogEntry.setPrincipalName(context.getPrincipalName());
667 auditLogEntry.setAssertingPartyId(context.getLocalEntityId());
668 auditLogEntry.setRelyingPartyId(context.getInboundMessageIssuer());
669 auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
670 auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
671 auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
672 auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
673 if (context.getReleasedAttributes() != null) {
674 auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
675 }
676
677 getAduitLog().info(auditLogEntry.toString());
678 }
679
680
681 protected class SAML1AuditLogEntry extends AuditLogEntry {
682
683
684 private Response samlResponse;
685
686
687
688
689
690
691 public Response getSAMLResponse() {
692 return samlResponse;
693 }
694
695
696
697
698
699
700 public void setSAMLResponse(Response response) {
701 samlResponse = response;
702 }
703
704
705 public String toString() {
706 StringBuilder entryString = new StringBuilder(super.toString());
707
708 NameIdentifier nameIdentifier = null;
709 StringBuilder assertionIds = new StringBuilder();
710 List<Assertion> assertions = samlResponse.getAssertions();
711 if(assertions != null && !assertions.isEmpty()){
712 for(Assertion assertion : assertions){
713 assertionIds.append(assertion.getID());
714 assertionIds.append(",");
715
716 if(nameIdentifier == null){
717 List<Statement> statements = assertion.getStatements();
718 if(statements != null && !statements.isEmpty()){
719 for(Statement statement : statements){
720 if(statement instanceof SubjectStatement){
721 if(((SubjectStatement)statement).getSubject() != null){
722 nameIdentifier = ((SubjectStatement)statement).getSubject().getNameIdentifier();
723 }
724 }
725 }
726 }
727 }
728 }
729 }
730
731 if(nameIdentifier != null){
732 entryString.append(nameIdentifier.getNameIdentifier());
733 }
734 entryString.append("|");
735
736 entryString.append(assertionIds.toString());
737 entryString.append("|");
738
739 return entryString.toString();
740 }
741 }
742 }