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()
119 Lockable* TransactionLog::lock()
125 void TransactionLog::unlock()
130 void TransactionLog::write(const TransactionLog::Event& e)
132 if (m_formatting.empty()) {
133 // For compatibility, we support the old transaction log format, ugly though it may be.
134 // The session log line would be easy to emulate, but the old attribute logging isn't
135 // easy to represent with a formatting string.
139 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
141 os << "New session (ID: ";
142 login->write(os, "%s", nullptr);
143 os << ") with (applicationId: ";
144 login->write(os, "%app", nullptr);
145 os << ") for principal from (IdP: ";
146 login->write(os, "%IDP", "none");
147 os << ") at (ClientAddress: ";
148 login->write(os, "%a", nullptr);
149 os << ") with (NameIdentifier: ";
150 login->write(os, "%n", "none");
151 os << ") using (Protocol: ";
152 login->write(os, "%p", "none");
153 os << ") from (AssertionID: ";
154 login->write(os, "%i", nullptr);
161 os << "Cached the following attributes with session (ID: ";
162 login->write(os, "%s", nullptr);
163 os << ") for (applicationId: ";
164 login->write(os, "%app", nullptr);
168 if (login->m_attributes) {
169 for (vector<Attribute*>::const_iterator a=login->m_attributes->begin(); a != login->m_attributes->end(); ++a)
170 log.infoStream() << "\t" << (*a)->getId() << " (" << (*a)->valueCount() << " values)";
177 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
178 if (logout && (logout->m_sessionID || logout->m_session || !logout->m_sessions.empty())) {
179 os << "Destroyed session (applicationId: ";
180 logout->write(os, "%app", nullptr);
182 logout->write(os, "%s", nullptr);
190 for (vector<string>::const_iterator i = m_formatting.begin(); i != m_formatting.end() && !i->empty(); ++i) {
191 if ((*i)[0] != '%' || !e.write(os, i->c_str(), m_absent.c_str())) {
195 Category::getInstance(string(SHIBSP_TX_LOGCAT) + "." + e.getType()).info(os.str());
200 bool _URL(const TransactionLog::Event& e, ostream& os) {
201 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
203 os << http->getRequestURL();
209 bool _URI(const TransactionLog::Event& e, ostream& os) {
210 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
212 os << http->getRequestURI();
218 bool _Header(const TransactionLog::Event& e, ostream& os, const char* name) {
219 const HTTPRequest* http = dynamic_cast<const HTTPRequest*>(e.m_request);
221 string s = http->getHeader(name);
230 bool _ExceptionMessage(const TransactionLog::Event& e, ostream& os) {
231 if (e.m_exception && e.m_exception->what()) {
232 os << e.m_exception->what();
238 bool _ExceptionType(const TransactionLog::Event& e, ostream& os) {
239 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
241 os << x->getClassName();
247 bool _AssertionID(const TransactionLog::Event& e, ostream& os) {
248 const XMLCh* id = nullptr;
249 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
251 if (login->m_saml2AuthnStatement) {
252 const saml2::Assertion* a = dynamic_cast<const saml2::Assertion*>(login->m_saml2AuthnStatement->getParent());
256 else if (login->m_saml1AuthnStatement) {
257 const saml1::Assertion* a = dynamic_cast<const saml1::Assertion*>(login->m_saml1AuthnStatement->getParent());
259 id = a->getAssertionID();
263 auto_ptr_char temp(id);
270 bool _ProtocolID(const TransactionLog::Event& e, ostream& os) {
271 const XMLCh* id = nullptr;
272 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
274 if (login->m_saml2Response)
275 id = login->m_saml2Response->getID();
276 else if (login->m_saml1Response)
277 id = login->m_saml1Response->getResponseID();
280 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
282 if (request->m_saml2Request)
283 id = request->m_saml2Request->getID();
286 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
288 if (logout->m_saml2Request)
289 id = logout->m_saml2Request->getID();
290 else if (logout->m_saml2Response)
291 id = logout->m_saml2Response->getID();
296 auto_ptr_char temp(id);
303 bool _InResponseTo(const TransactionLog::Event& e, ostream& os) {
304 const XMLCh* id = nullptr;
305 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
307 if (login->m_saml2Response)
308 id = login->m_saml2Response->getInResponseTo();
309 else if (login->m_saml1Response)
310 id = login->m_saml1Response->getInResponseTo();
313 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
314 if (logout && logout->m_saml2Response) {
315 id = logout->m_saml2Response->getInResponseTo();
319 auto_ptr_char temp(id);
326 bool _StatusCode(const TransactionLog::Event& e, ostream& os) {
327 const saml1p::Status* s1 = nullptr;
328 const saml2p::Status* s2 = nullptr;
329 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
331 if (login->m_saml2Response)
332 s2 = login->m_saml2Response->getStatus();
333 else if (login->m_saml1Response)
334 s1 = login->m_saml1Response->getStatus();
337 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
338 if (logout && logout->m_saml2Response)
339 s2 = logout->m_saml2Response->getStatus();
342 if (s2 && s2->getStatusCode() && s2->getStatusCode()->getValue()) {
343 auto_ptr_char temp(s2->getStatusCode()->getValue());
344 if (temp.get() && *temp.get()) {
349 else if (s1 && s1->getStatusCode() && s1->getStatusCode()->getValue()) {
350 os << s1->getStatusCode()->getValue()->toString();
354 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
356 const char* s = x->getProperty("statusCode");
365 bool _SubStatusCode(const TransactionLog::Event& e, ostream& os) {
366 const saml1p::Status* s1 = nullptr;
367 const saml2p::Status* s2 = nullptr;
368 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
370 if (login->m_saml2Response)
371 s2 = login->m_saml2Response->getStatus();
372 else if (login->m_saml1Response)
373 s1 = login->m_saml1Response->getStatus();
376 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
377 if (logout && logout->m_saml2Response)
378 s2 = logout->m_saml2Response->getStatus();
381 if (s2 && s2->getStatusCode() && s2->getStatusCode()->getStatusCode()) {
382 auto_ptr_char temp(s2->getStatusCode()->getStatusCode()->getValue());
383 if (temp.get() && *temp.get()) {
388 else if (s1 && s1->getStatusCode() && s1->getStatusCode()->getStatusCode()) {
389 if (s1->getStatusCode()->getStatusCode()->getValue()) {
390 os << s1->getStatusCode()->getValue()->toString();
395 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
397 const char* s = x->getProperty("statusCode2");
406 bool _StatusMessage(const TransactionLog::Event& e, ostream& os) {
407 const XMLCh* msg = nullptr;
408 const saml1p::Status* s1 = nullptr;
409 const saml2p::Status* s2 = nullptr;
410 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
412 if (login->m_saml2Response)
413 s2 = login->m_saml2Response->getStatus();
414 else if (login->m_saml1Response)
415 s1 = login->m_saml1Response->getStatus();
418 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
419 if (logout && logout->m_saml2Response)
420 s2 = logout->m_saml2Response->getStatus();
423 if (s2 && s2->getStatusMessage())
424 msg = s2->getStatusMessage()->getMessage();
425 else if (s1 && s1->getStatusMessage())
426 msg = s1->getStatusMessage()->getMessage();
429 auto_ptr_char temp(msg);
430 if (temp.get() && *temp.get()) {
436 const XMLToolingException* x = dynamic_cast<const XMLToolingException*>(e.m_exception);
438 const char* s = x->getProperty("statusMessage");
449 bool _AssertionIssueInstant(const TransactionLog::Event& e, ostream& os) {
451 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
453 if (login->m_saml2AuthnStatement) {
454 const saml2::Assertion* a = dynamic_cast<const saml2::Assertion*>(login->m_saml2AuthnStatement->getParent());
455 if (a && a->getIssueInstant())
456 t = a->getIssueInstantEpoch();
458 else if (login->m_saml1AuthnStatement) {
459 const saml1::Assertion* a = dynamic_cast<const saml1::Assertion*>(login->m_saml1AuthnStatement->getParent());
460 if (a && a->getIssueInstant())
461 t = a->getIssueInstantEpoch();
466 #ifndef HAVE_GMTIME_R
467 struct tm* ptime=localtime(&t);
470 struct tm* ptime=localtime_r(&t, &res);
473 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
478 bool _ProtocolIssueInstant(const TransactionLog::Event& e, ostream& os) {
480 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
482 if (login->m_saml2Response && login->m_saml2Response->getIssueInstant())
483 t = login->m_saml2Response->getIssueInstantEpoch();
484 else if (login->m_saml1Response && login->m_saml1Response->getIssueInstant())
485 t = login->m_saml1Response->getIssueInstantEpoch();
488 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
490 if (request->m_saml2Request && request->m_saml2Request->getIssueInstant())
491 t = request->m_saml2Request->getIssueInstantEpoch();
494 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
496 if (logout->m_saml2Request && logout->m_saml2Request->getIssueInstant())
497 t = logout->m_saml2Request->getIssueInstantEpoch();
498 else if (logout->m_saml2Response && logout->m_saml2Response->getIssueInstant())
499 t = logout->m_saml2Response->getIssueInstantEpoch();
505 #ifndef HAVE_GMTIME_R
506 struct tm* ptime=localtime(&t);
509 struct tm* ptime=localtime_r(&t, &res);
512 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
517 bool _AuthnInstant(const TransactionLog::Event& e, ostream& os) {
519 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
521 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getAuthnInstant())
522 t = login->m_saml2AuthnStatement->getAuthnInstantEpoch();
523 else if (login->m_saml1AuthnStatement && login->m_saml1AuthnStatement->getAuthenticationInstant())
524 t = login->m_saml1AuthnStatement->getAuthenticationInstantEpoch();
528 #ifndef HAVE_GMTIME_R
529 struct tm* ptime=localtime(&t);
532 struct tm* ptime=localtime_r(&t, &res);
535 strftime(timebuf,32,"%Y-%m-%dT%H:%M:%S",ptime);
540 bool _SessionIndex(const TransactionLog::Event& e, ostream& os) {
541 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
543 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getSessionIndex()) {
544 auto_ptr_char ix(login->m_saml2AuthnStatement->getSessionIndex());
545 if (ix.get() && *ix.get()) {
552 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
553 if (logout && logout->m_saml2Request && !logout->m_saml2Request->getSessionIndexs().empty()) {
554 const vector<saml2p::SessionIndex*>& indexes = logout->m_saml2Request->getSessionIndexs();
555 for (vector<saml2p::SessionIndex*>::const_iterator i = indexes.begin(); i != indexes.end(); ++i) {
556 auto_ptr_char ix((*i)->getSessionIndex());
557 if (ix.get() && *ix.get()) {
558 if (i != indexes.begin())
569 bool _SessionID(const TransactionLog::Event& e, ostream& os) {
570 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
572 if (!logout->m_sessions.empty()) {
573 for (vector<string>::const_iterator s = logout->m_sessions.begin(); s != logout->m_sessions.end(); ++s) {
574 if (s != logout->m_sessions.begin())
580 else if (logout->m_session) {
581 os << logout->m_session->getID();
585 else if (e.m_sessionID) {
592 bool _REMOTE_USER(const TransactionLog::Event& e, ostream& os) {
593 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
594 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
595 if (e.m_app && ((login && login->m_attributes) || (logout && logout->m_session))) {
596 const vector<string>& ids = e.m_app->getRemoteUserAttributeIds();
597 const vector<shibsp::Attribute*>& attrs = (login ? *login->m_attributes : logout->m_session->getAttributes());
598 for (vector<string>::const_iterator id = ids.begin(); id != ids.end(); ++id) {
599 for (vector<shibsp::Attribute*>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
600 if (*id == (*a)->getId() && (*a)->valueCount() > 0) {
601 os << (*a)->getSerializedValues().front();
610 bool _REMOTE_ADDR(const TransactionLog::Event& e, ostream& os) {
612 string s = e.m_request->getRemoteAddr();
621 bool _AuthnContext(const TransactionLog::Event& e, ostream& os) {
622 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
624 if (login->m_saml2AuthnStatement && login->m_saml2AuthnStatement->getAuthnContext()) {
625 const AuthnContext* ctx = login->m_saml2AuthnStatement->getAuthnContext();
626 if (ctx->getAuthnContextClassRef()) {
627 auto_ptr_char ref(ctx->getAuthnContextClassRef()->getReference());
633 else if (ctx->getAuthnContextDeclRef()) {
634 auto_ptr_char ref(ctx->getAuthnContextDeclRef()->getReference());
640 else if (ctx->getAuthnContextDecl()) {
641 os << "(full declaration)";
645 else if (login->m_saml1AuthnStatement && login->m_saml1AuthnStatement->getAuthenticationMethod()) {
646 auto_ptr_char ac(login->m_saml1AuthnStatement->getAuthenticationMethod());
656 bool _UserAgent(const TransactionLog::Event& e, ostream& os) {
657 return _Header(e, os, "User-Agent");
660 bool _ApplicationID(const TransactionLog::Event& e, ostream& os) {
662 os << e.m_app->getId();
668 bool _SP_(const TransactionLog::Event& e, ostream& os) {
670 const PropertySet* props = e.m_app->getRelyingParty(e.m_peer);
672 pair<bool,const char*> entityid = props->getString("entityID");
673 if (entityid.first) {
674 os << entityid.second;
682 bool _IDP(const TransactionLog::Event& e, ostream& os) {
684 auto_ptr_char entityid(e.m_peer->getEntityID());
685 if (entityid.get()) {
686 os << entityid.get();
691 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
692 if (logout && logout->m_session) {
693 os << logout->m_session->getEntityID();
700 bool _Protocol(const TransactionLog::Event& e, ostream& os) {
708 bool _Binding(const TransactionLog::Event& e, ostream& os) {
716 bool _NameID(const TransactionLog::Event& e, ostream& os) {
717 if (e.m_nameID && e.m_nameID->getName()) {
718 auto_ptr_char temp(e.m_nameID->getName());
719 if (temp.get() && *temp.get()) {
725 const AuthnRequestEvent* request = dynamic_cast<const AuthnRequestEvent*>(&e);
727 if (request->m_saml2Request && request->m_saml2Request->getSubject()) {
728 const saml2::NameID* n = request->m_saml2Request->getSubject()->getNameID();
730 auto_ptr_char temp(n->getName());
731 if (temp.get() && *temp.get()) {
739 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
741 const saml2::NameID* n = nullptr;
742 if (logout->m_session)
743 n = logout->m_session->getNameID();
744 else if (logout->m_saml2Request)
745 n = logout->m_saml2Request->getNameID();
747 auto_ptr_char temp(n->getName());
748 if (temp.get() && *temp.get()) {
759 bool _Attributes(const TransactionLog::Event& e, ostream& os) {
760 const vector<shibsp::Attribute*>* attrs = nullptr;
761 const LoginEvent* login = dynamic_cast<const LoginEvent*>(&e);
763 attrs = login->m_attributes;
766 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
767 if (logout && logout->m_session)
768 attrs = &logout->m_session->getAttributes();
770 if (attrs && !attrs->empty()) {
771 map<string,size_t> valcounts;
772 for (vector<shibsp::Attribute*>::const_iterator a = attrs->begin(); a != attrs->end(); ++a) {
773 valcounts[(*a)->getId()] += (*a)->valueCount();
775 for (map<string,size_t>::const_iterator c = valcounts.begin(); c != valcounts.end(); ++c) {
776 if (c != valcounts.begin())
778 os << c->first << '(' << c->second << ')';
785 bool _Logout(const TransactionLog::Event& e, ostream& os) {
786 const LogoutEvent* logout = dynamic_cast<const LogoutEvent*>(&e);
788 switch (logout->m_logoutType) {
789 case LogoutEvent::LOGOUT_EVENT_INVALID:
792 case LogoutEvent::LOGOUT_EVENT_LOCAL:
795 case LogoutEvent::LOGOUT_EVENT_GLOBAL:
798 case LogoutEvent::LOGOUT_EVENT_PARTIAL:
807 TransactionLog::Event::Event()
808 : m_exception(nullptr),
811 m_sessionID(nullptr),
817 m_handlers["e"] = _ExceptionMessage;
818 m_handlers["E"] = _ExceptionType;
819 m_handlers["S"] = _StatusCode;
820 m_handlers["SS"] = _SubStatusCode;
821 m_handlers["SM"] = _StatusMessage;
822 m_handlers["URL"] = _URL;
823 m_handlers["URI"] = _URI;
824 m_handlers["s"] = _SessionID;
825 m_handlers["a"] = _REMOTE_ADDR;
826 m_handlers["UA"] = _UserAgent;
827 m_handlers["app"] = _ApplicationID;
828 m_handlers["SP"] = _SP_;
829 m_handlers["IDP"] = _IDP;
830 m_handlers["p"] = _Protocol;
831 m_handlers["b"] = _Binding;
832 m_handlers["n"] = _NameID;
835 TransactionLog::Event::~Event()
839 bool TransactionLog::Event::write(ostream& out, const char* field, const char* absent) const
841 if (!field || *field++ != '%') {
845 if (*field == '%' || *field == '\0') {
849 map<string,handler_fn>::const_iterator h = m_handlers.find(field);
850 if ((h != m_handlers.end() && !h->second(*this, out)) || (h == m_handlers.end() && !_Header(*this, out, field))) {
858 LoginEvent::LoginEvent()
859 : m_saml2AuthnStatement(nullptr),
860 m_saml2Response(nullptr),
861 m_saml1AuthnStatement(nullptr),
862 m_saml1Response(nullptr),
863 m_attributes(nullptr)
865 m_handlers["u"] = _REMOTE_USER;
866 m_handlers["i"] = _AssertionID;
867 m_handlers["I"] = _ProtocolID;
868 m_handlers["II"] = _InResponseTo;
869 m_handlers["d"] = _AssertionIssueInstant;
870 m_handlers["D"] = _ProtocolIssueInstant;
871 m_handlers["t"] = _AuthnInstant;
872 m_handlers["x"] = _SessionIndex;
873 m_handlers["ac"] = _AuthnContext;
874 m_handlers["attr"] = _Attributes;
877 const char* LoginEvent::getType() const
882 LoginEvent::~LoginEvent()
886 LogoutEvent::LogoutEvent()
887 : m_logoutType(LOGOUT_EVENT_UNKNOWN),
888 m_saml2Request(nullptr),
889 m_saml2Response(nullptr),
892 m_handlers["L"] = _Logout;
893 m_handlers["u"] = _REMOTE_USER;
894 m_handlers["I"] = _ProtocolID;
895 m_handlers["II"] = _InResponseTo;
896 m_handlers["D"] = _ProtocolIssueInstant;
897 m_handlers["x"] = _SessionIndex;
900 LogoutEvent::~LogoutEvent()
904 const char* LogoutEvent::getType() const
907 return "Logout.Request";
908 else if (m_saml2Response)
909 return "Logout.Response";
913 AuthnRequestEvent::AuthnRequestEvent() : m_saml2Request(nullptr)
915 m_handlers["I"] = _ProtocolID;
916 m_handlers["D"] = _ProtocolIssueInstant;
919 AuthnRequestEvent::~AuthnRequestEvent()
923 const char* AuthnRequestEvent::getType() const
925 return "AuthnRequest";