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