2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
24 * Formatted event record logging.
29 #if defined(XMLTOOLING_LOG4SHIB)
30 # ifndef SHIBSP_LOG4SHIB
31 # error "Logging library mismatch (XMLTooling is using log4shib)."
33 #elif defined(XMLTOOLING_LOG4CPP)
34 # ifndef SHIBSP_LOG4CPP
35 # error "Logging library mismatch (XMLTooling is using log4cpp)."
38 # error "No supported logging library."
41 #include "Application.h"
42 #include "SessionCache.h"
43 #include "TransactionLog.h"
44 #include "attribute/Attribute.h"
46 #include <saml/saml1/core/Assertions.h>
47 #include <saml/saml1/core/Protocols.h>
48 #include <saml/saml2/core/Protocols.h>
49 #include <saml/saml2/metadata/Metadata.h>
50 #include <xmltooling/util/Threads.h>
52 using namespace shibsp;
53 using namespace opensaml::saml1;
54 using namespace opensaml::saml2;
55 using namespace opensaml;
56 using namespace xmltooling;
60 TransactionLog::Event* SHIBSP_DLLLOCAL LoginEventFactory(void* const &)
62 return new LoginEvent();
65 TransactionLog::Event* SHIBSP_DLLLOCAL LogoutEventFactory(void* const &)
67 return new LogoutEvent();
70 TransactionLog::Event* SHIBSP_DLLLOCAL AuthnRequestEventFactory(void* const &)
72 return new AuthnRequestEvent();
76 void SHIBSP_API shibsp::registerEvents()
78 SPConfig& conf=SPConfig::getConfig();
79 conf.EventManager.registerFactory(LOGIN_EVENT, LoginEventFactory);
80 conf.EventManager.registerFactory(LOGOUT_EVENT, LogoutEventFactory);
81 conf.EventManager.registerFactory(AUTHNREQUEST_EVENT, AuthnRequestEventFactory);
84 TransactionLog::TransactionLog(const char* fmt, const char* absent)
85 : log(logging::Category::getInstance(SHIBSP_TX_LOGCAT)), m_lock(Mutex::create()), m_absent(absent ? absent : "")
87 // Split the formatting string into named '%' parameter tokens, and "other stuff" to be echoed
88 // literally in log messages.
90 bool in_token = false;
91 m_formatting.push_back(string());
92 vector<string>::iterator field = m_formatting.begin();
95 if (!isalnum(*fmt) && *fmt != '-' && *fmt != '%') {
96 m_formatting.push_back(string());
97 field = m_formatting.begin() + m_formatting.size() - 1;
101 else if (*fmt == '%') {
102 if (!field->empty()) {
103 m_formatting.push_back(string());
104 field = m_formatting.begin() + m_formatting.size() - 1;
110 if (!m_formatting.empty() && m_formatting.back().empty())
111 m_formatting.pop_back();
114 TransactionLog::~TransactionLog()
118 Lockable* TransactionLog::lock()
124 void TransactionLog::unlock()
129 void TransactionLog::write(const TransactionLog::Event& e)
131 if (m_formatting.empty()) {
132 // For compatibility, we support the old transaction log format, ugly though it may be.
133 // The session log line would be easy to emulate, but the old attribute logging isn't
134 // easy to represent with a formatting string.
138 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
140 os << "New session (ID: ";
141 login->write(os, "%s", nullptr);
142 os << ") with (applicationId: ";
143 login->write(os, "%app", nullptr);
144 os << ") for principal from (IdP: ";
145 login->write(os, "%IDP", "none");
146 os << ") at (ClientAddress: ";
147 login->write(os, "%a", nullptr);
148 os << ") with (NameIdentifier: ";
149 login->write(os, "%n", "none");
150 os << ") using (Protocol: ";
151 login->write(os, "%p", "none");
152 os << ") from (AssertionID: ";
153 login->write(os, "%i", nullptr);
160 os << "Cached the following attributes with session (ID: ";
161 login->write(os, "%s", nullptr);
162 os << ") for (applicationId: ";
163 login->write(os, "%app", nullptr);
167 if (login->m_attributes) {
168 for (vector<Attribute*>::const_iterator a=login->m_attributes->begin(); a != login->m_attributes->end(); ++a)
169 log.infoStream() << "\t" << (*a)->getId() << " (" << (*a)->valueCount() << " values)";
176 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
177 if (logout && (logout->m_sessionID || logout->m_session || !logout->m_sessions.empty())) {
178 os << "Destroyed session (applicationId: ";
179 logout->write(os, "%app", nullptr);
181 logout->write(os, "%s", nullptr);
189 for (vector<string>::const_iterator i = m_formatting.begin(); i != m_formatting.end() && !i->empty(); ++i) {
190 if ((*i)[0] != '%' || !e.write(os, i->c_str(), m_absent.c_str())) {
194 Category::getInstance(string(SHIBSP_TX_LOGCAT) + "." + e.getType()).info(os.str());
199 bool _URL(const TransactionLog::Event& e, ostream& os) {
200 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
202 os << http->getRequestURL();
208 bool _URI(const TransactionLog::Event& e, ostream& os) {
209 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
211 os << http->getRequestURI();
217 bool _Header(const TransactionLog::Event& e, ostream& os, const char* name) {
218 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
220 string s = http->getHeader(name);
229 bool _ExceptionMessage(const TransactionLog::Event& e, ostream& os) {
230 if (e.m_exception && e.m_exception->what()) {
231 os << e.m_exception->what();
237 bool _ExceptionType(const TransactionLog::Event& e, ostream& os) {
238 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
240 os << x->getClassName();
246 bool _AssertionID(const TransactionLog::Event& e, ostream& os) {
247 const XMLCh* id = nullptr;
248 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
250 if (login->m_saml2AuthnStatement) {
251 const saml2::Assertion* a = dynamic_cast<const saml2::Assertion*>(login->m_saml2AuthnStatement->getParent());
255 else if (login->m_saml1AuthnStatement) {
256 const saml1::Assertion* a = dynamic_cast<const saml1::Assertion*>(login->m_saml1AuthnStatement->getParent());
258 id = a->getAssertionID();
262 auto_ptr_char temp(id);
269 bool _ProtocolID(const TransactionLog::Event& e, ostream& os) {
270 const XMLCh* id = nullptr;
271 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
273 if (login->m_saml2Response)
274 id = login->m_saml2Response->getID();
275 else if (login->m_saml1Response)
276 id = login->m_saml1Response->getResponseID();
279 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
281 if (request->m_saml2Request)
282 id = request->m_saml2Request->getID();
285 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
287 if (logout->m_saml2Request)
288 id = logout->m_saml2Request->getID();
289 else if (logout->m_saml2Response)
290 id = logout->m_saml2Response->getID();
295 auto_ptr_char temp(id);
302 bool _InResponseTo(const TransactionLog::Event& e, ostream& os) {
303 const XMLCh* id = nullptr;
304 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
306 if (login->m_saml2Response)
307 id = login->m_saml2Response->getInResponseTo();
308 else if (login->m_saml1Response)
309 id = login->m_saml1Response->getInResponseTo();
312 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
313 if (logout && logout->m_saml2Response) {
314 id = logout->m_saml2Response->getInResponseTo();
318 auto_ptr_char temp(id);
325 bool _StatusCode(const TransactionLog::Event& e, ostream& os) {
326 const saml1p::Status* s1 = nullptr;
327 const saml2p::Status* s2 = nullptr;
328 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
330 if (login->m_saml2Response)
331 s2 = login->m_saml2Response->getStatus();
332 else if (login->m_saml1Response)
333 s1 = login->m_saml1Response->getStatus();
336 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
337 if (logout && logout->m_saml2Response)
338 s2 = logout->m_saml2Response->getStatus();
341 if (s2 && s2->getStatusCode() && s2->getStatusCode()->getValue()) {
342 auto_ptr_char temp(s2->getStatusCode()->getValue());
343 if (temp.get() && *temp.get()) {
348 else if (s1 && s1->getStatusCode() && s1->getStatusCode()->getValue()) {
349 os << s1->getStatusCode()->getValue()->toString();
353 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
355 const char* s = x->getProperty("statusCode");
364 bool _SubStatusCode(const TransactionLog::Event& e, ostream& os) {
365 const saml1p::Status* s1 = nullptr;
366 const saml2p::Status* s2 = nullptr;
367 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
369 if (login->m_saml2Response)
370 s2 = login->m_saml2Response->getStatus();
371 else if (login->m_saml1Response)
372 s1 = login->m_saml1Response->getStatus();
375 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
376 if (logout && logout->m_saml2Response)
377 s2 = logout->m_saml2Response->getStatus();
380 if (s2 && s2->getStatusCode() && s2->getStatusCode()->getStatusCode()) {
381 auto_ptr_char temp(s2->getStatusCode()->getStatusCode()->getValue());
382 if (temp.get() && *temp.get()) {
387 else if (s1 && s1->getStatusCode() && s1->getStatusCode()->getStatusCode()) {
388 if (s1->getStatusCode()->getStatusCode()->getValue()) {
389 os << s1->getStatusCode()->getValue()->toString();
394 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
396 const char* s = x->getProperty("statusCode2");
405 bool _StatusMessage(const TransactionLog::Event& e, ostream& os) {
406 const XMLCh* msg = nullptr;
407 const saml1p::Status* s1 = nullptr;
408 const saml2p::Status* s2 = nullptr;
409 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
411 if (login->m_saml2Response)
412 s2 = login->m_saml2Response->getStatus();
413 else if (login->m_saml1Response)
414 s1 = login->m_saml1Response->getStatus();
417 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
418 if (logout && logout->m_saml2Response)
419 s2 = logout->m_saml2Response->getStatus();
422 if (s2 && s2->getStatusMessage())
423 msg = s2->getStatusMessage()->getMessage();
424 else if (s1 && s1->getStatusMessage())
425 msg = s1->getStatusMessage()->getMessage();
428 auto_ptr_char temp(msg);
429 if (temp.get() && *temp.get()) {
435 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
437 const char* s = x->getProperty("statusMessage");
448 bool _AssertionIssueInstant(const TransactionLog::Event& e, ostream& os) {
450 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
452 if (login->m_saml2AuthnStatement) {
453 const saml2::Assertion* a = dynamic_cast<const saml2::Assertion*>(login->m_saml2AuthnStatement->getParent());
454 if (a && a->getIssueInstant())
455 t = a->getIssueInstantEpoch();
457 else if (login->m_saml1AuthnStatement) {
458 const saml1::Assertion* a = dynamic_cast<const saml1::Assertion*>(login->m_saml1AuthnStatement->getParent());
459 if (a && a->getIssueInstant())
460 t = a->getIssueInstantEpoch();
465 #ifndef HAVE_GMTIME_R
466 struct tm* ptime=localtime(&t);
469 struct tm* ptime=localtime_r(&t, &res);
472 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
477 bool _ProtocolIssueInstant(const TransactionLog::Event& e, ostream& os) {
479 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
481 if (login->m_saml2Response && login->m_saml2Response->getIssueInstant())
482 t = login->m_saml2Response->getIssueInstantEpoch();
483 else if (login->m_saml1Response && login->m_saml1Response->getIssueInstant())
484 t = login->m_saml1Response->getIssueInstantEpoch();
487 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
489 if (request->m_saml2Request && request->m_saml2Request->getIssueInstant())
490 t = request->m_saml2Request->getIssueInstantEpoch();
493 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
495 if (logout->m_saml2Request && logout->m_saml2Request->getIssueInstant())
496 t = logout->m_saml2Request->getIssueInstantEpoch();
497 else if (logout->m_saml2Response && logout->m_saml2Response->getIssueInstant())
498 t = logout->m_saml2Response->getIssueInstantEpoch();
504 #ifndef HAVE_GMTIME_R
505 struct tm* ptime=localtime(&t);
508 struct tm* ptime=localtime_r(&t, &res);
511 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
516 bool _AuthnInstant(const TransactionLog::Event& e, ostream& os) {
518 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
520 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getAuthnInstant())
521 t = login->m_saml2AuthnStatement->getAuthnInstantEpoch();
522 else if (login->m_saml1AuthnStatement && login->m_saml1AuthnStatement->getAuthenticationInstant())
523 t = login->m_saml1AuthnStatement->getAuthenticationInstantEpoch();
527 #ifndef HAVE_GMTIME_R
528 struct tm* ptime=localtime(&t);
531 struct tm* ptime=localtime_r(&t, &res);
534 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
539 bool _SessionIndex(const TransactionLog::Event& e, ostream& os) {
540 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
542 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getSessionIndex()) {
543 auto_ptr_char ix(login->m_saml2AuthnStatement->getSessionIndex());
544 if (ix.get() && *ix.get()) {
551 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
552 if (logout && logout->m_saml2Request && !logout->m_saml2Request->getSessionIndexs().empty()) {
553 const vector<saml2p::SessionIndex*>& indexes = logout->m_saml2Request->getSessionIndexs();
554 for (vector<saml2p::SessionIndex*>::const_iterator i = indexes.begin(); i != indexes.end(); ++i) {
555 auto_ptr_char ix((*i)->getSessionIndex());
556 if (ix.get() && *ix.get()) {
557 if (i != indexes.begin())
568 bool _SessionID(const TransactionLog::Event& e, ostream& os) {
569 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
571 if (!logout->m_sessions.empty()) {
572 for (vector<string>::const_iterator s = logout->m_sessions.begin(); s != logout->m_sessions.end(); ++s) {
573 if (s != logout->m_sessions.begin())
579 else if (logout->m_session) {
580 os << logout->m_session->getID();
584 else if (e.m_sessionID) {
591 bool _REMOTE_USER(const TransactionLog::Event& e, ostream& os) {
592 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
593 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
594 if (e.m_app && ((login && login->m_attributes) || (logout && logout->m_session))) {
595 const vector<string>& ids = e.m_app->getRemoteUserAttributeIds();
596 const vector<shibsp::Attribute*>& attrs = (login ? *login->m_attributes : logout->m_session->getAttributes());
597 for (vector<string>::const_iterator id = ids.begin(); id != ids.end(); ++id) {
598 for (vector<shibsp::Attribute*>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
599 if (*id == (*a)->getId() && (*a)->valueCount() > 0) {
600 os << (*a)->getSerializedValues().front();
609 bool _REMOTE_ADDR(const TransactionLog::Event& e, ostream& os) {
611 string s = e.m_request->getRemoteAddr();
620 bool _AuthnContext(const TransactionLog::Event& e, ostream& os) {
621 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
623 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getAuthnContext()) {
624 const AuthnContext* ctx = login->m_saml2AuthnStatement->getAuthnContext();
625 if (ctx->getAuthnContextClassRef()) {
626 auto_ptr_char ref(ctx->getAuthnContextClassRef()->getReference());
632 else if (ctx->getAuthnContextDeclRef()) {
633 auto_ptr_char ref(ctx->getAuthnContextDeclRef()->getReference());
639 else if (ctx->getAuthnContextDecl()) {
640 os << "(full declaration)";
644 else if (login->m_saml1AuthnStatement && login->m_saml1AuthnStatement->getAuthenticationMethod()) {
645 auto_ptr_char ac(login->m_saml1AuthnStatement->getAuthenticationMethod());
655 bool _UserAgent(const TransactionLog::Event& e, ostream& os) {
656 return _Header(e, os, "User-Agent");
659 bool _ApplicationID(const TransactionLog::Event& e, ostream& os) {
661 os << e.m_app->getId();
667 bool _SP_(const TransactionLog::Event& e, ostream& os) {
669 const PropertySet* props = e.m_app->getRelyingParty(e.m_peer);
671 pair<bool,const char*> entityid = props->getString("entityID");
672 if (entityid.first) {
673 os << entityid.second;
681 bool _IDP(const TransactionLog::Event& e, ostream& os) {
683 auto_ptr_char entityid(e.m_peer->getEntityID());
684 if (entityid.get()) {
685 os << entityid.get();
690 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
691 if (logout && logout->m_session) {
692 os << logout->m_session->getEntityID();
699 bool _Protocol(const TransactionLog::Event& e, ostream& os) {
707 bool _Binding(const TransactionLog::Event& e, ostream& os) {
715 bool _NameID(const TransactionLog::Event& e, ostream& os) {
716 if (e.m_nameID && e.m_nameID->getName()) {
717 auto_ptr_char temp(e.m_nameID->getName());
718 if (temp.get() && *temp.get()) {
724 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
726 if (request->m_saml2Request && request->m_saml2Request->getSubject()) {
727 const saml2::NameID* n = request->m_saml2Request->getSubject()->getNameID();
729 auto_ptr_char temp(n->getName());
730 if (temp.get() && *temp.get()) {
738 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
740 const saml2::NameID* n = nullptr;
741 if (logout->m_session)
742 n = logout->m_session->getNameID();
743 else if (logout->m_saml2Request)
744 n = logout->m_saml2Request->getNameID();
746 auto_ptr_char temp(n->getName());
747 if (temp.get() && *temp.get()) {
758 bool _Attributes(const TransactionLog::Event& e, ostream& os) {
759 const vector<shibsp::Attribute*>* attrs = nullptr;
760 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
762 attrs = login->m_attributes;
765 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
766 if (logout && logout->m_session)
767 attrs = &logout->m_session->getAttributes();
769 if (attrs && !attrs->empty()) {
770 map<string,size_t> valcounts;
771 for (vector<shibsp::Attribute*>::const_iterator a = attrs->begin(); a != attrs->end(); ++a) {
772 valcounts[(*a)->getId()] += (*a)->valueCount();
774 for (map<string,size_t>::const_iterator c = valcounts.begin(); c != valcounts.end(); ++c) {
775 if (c != valcounts.begin())
777 os << c->first << '(' << c->second << ')';
784 bool _Logout(const TransactionLog::Event& e, ostream& os) {
785 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
787 switch (logout->m_logoutType) {
788 case LogoutEvent::LOGOUT_EVENT_INVALID:
791 case LogoutEvent::LOGOUT_EVENT_LOCAL:
794 case LogoutEvent::LOGOUT_EVENT_GLOBAL:
797 case LogoutEvent::LOGOUT_EVENT_PARTIAL:
806 TransactionLog::Event::Event()
807 : m_exception(nullptr),
810 m_sessionID(nullptr),
816 m_handlers["e"] = _ExceptionMessage;
817 m_handlers["E"] = _ExceptionType;
818 m_handlers["S"] = _StatusCode;
819 m_handlers["SS"] = _SubStatusCode;
820 m_handlers["SM"] = _StatusMessage;
821 m_handlers["URL"] = _URL;
822 m_handlers["URI"] = _URI;
823 m_handlers["s"] = _SessionID;
824 m_handlers["a"] = _REMOTE_ADDR;
825 m_handlers["UA"] = _UserAgent;
826 m_handlers["app"] = _ApplicationID;
827 m_handlers["SP"] = _SP_;
828 m_handlers["IDP"] = _IDP;
829 m_handlers["p"] = _Protocol;
830 m_handlers["b"] = _Binding;
831 m_handlers["n"] = _NameID;
834 TransactionLog::Event::~Event()
838 bool TransactionLog::Event::write(ostream& out, const char* field, const char* absent) const
840 if (!field || *field++ != '%') {
844 if (*field == '%' || *field == '\0') {
848 map<string,handler_fn>::const_iterator h = m_handlers.find(field);
849 if ((h != m_handlers.end() && !h->second(*this, out)) || (h == m_handlers.end() && !_Header(*this, out, field))) {
857 LoginEvent::LoginEvent()
858 : m_saml2AuthnStatement(nullptr),
859 m_saml2Response(nullptr),
860 m_saml1AuthnStatement(nullptr),
861 m_saml1Response(nullptr),
862 m_attributes(nullptr)
864 m_handlers["u"] = _REMOTE_USER;
865 m_handlers["i"] = _AssertionID;
866 m_handlers["I"] = _ProtocolID;
867 m_handlers["II"] = _InResponseTo;
868 m_handlers["d"] = _AssertionIssueInstant;
869 m_handlers["D"] = _ProtocolIssueInstant;
870 m_handlers["t"] = _AuthnInstant;
871 m_handlers["x"] = _SessionIndex;
872 m_handlers["ac"] = _AuthnContext;
873 m_handlers["attr"] = _Attributes;
876 const char* LoginEvent::getType() const
881 LoginEvent::~LoginEvent()
885 LogoutEvent::LogoutEvent()
886 : m_logoutType(LOGOUT_EVENT_UNKNOWN),
887 m_saml2Request(nullptr),
888 m_saml2Response(nullptr),
891 m_handlers["L"] = _Logout;
892 m_handlers["u"] = _REMOTE_USER;
893 m_handlers["I"] = _ProtocolID;
894 m_handlers["II"] = _InResponseTo;
895 m_handlers["D"] = _ProtocolIssueInstant;
896 m_handlers["x"] = _SessionIndex;
899 LogoutEvent::~LogoutEvent()
903 const char* LogoutEvent::getType() const
906 return "Logout.Request";
907 else if (m_saml2Response)
908 return "Logout.Response";
912 AuthnRequestEvent::AuthnRequestEvent() : m_saml2Request(nullptr)
914 m_handlers["I"] = _ProtocolID;
915 m_handlers["D"] = _ProtocolIssueInstant;
918 AuthnRequestEvent::~AuthnRequestEvent()
922 const char* AuthnRequestEvent::getType() const
924 return "AuthnRequest";