|
2 | 2 |
|
3 | 3 | namespace SimpleSAML\Module\oidc\Controller; |
4 | 4 |
|
| 5 | +use CirrusIdentity\SSP\Utils\MetricLogger; |
5 | 6 | use Exception; |
6 | 7 | use SimpleSAML\Error\BadRequest; |
7 | 8 | use SimpleSAML\Module\oidc\Factories\TemplateFactory; |
@@ -66,66 +67,93 @@ public function __invoke(ServerRequest $request): Response |
66 | 67 | // (FCL has challenges with User Agents Blocking Access to Third-Party Content: |
67 | 68 | // https://openid.net/specs/openid-connect-frontchannel-1_0.html#ThirdPartyContent) |
68 | 69 |
|
69 | | - $logoutRequest = $this->authorizationServer->validateLogoutRequest($request); |
| 70 | + try { |
| 71 | + $logoutRequest = $this->authorizationServer->validateLogoutRequest($request); |
70 | 72 |
|
71 | | - // Set indication that the logout is initiated using OIDC protocol. This will be checked in the |
72 | | - // logoutHandler() method. |
73 | | - $this->sessionService->setIsOidcInitiatedLogout(true); |
| 73 | + // Set indication that the logout is initiated using OIDC protocol. This will be checked in the |
| 74 | + // logoutHandler() method. |
| 75 | + $this->sessionService->setIsOidcInitiatedLogout(true); |
74 | 76 |
|
75 | | - // Indication if any there was a call to logout action on any auth source at all... |
76 | | - $wasLogoutActionCalled = false; |
| 77 | + // Indication if any there was a call to logout action on any auth source at all... |
| 78 | + $wasLogoutActionCalled = false; |
77 | 79 |
|
78 | | - $sidClaim = null; |
| 80 | + $sidClaim = null; |
79 | 81 |
|
80 | | - // If id_token_hint was provided, resolve session ID |
81 | | - $idTokenHint = $logoutRequest->getIdTokenHint(); |
82 | | - if ($idTokenHint !== null) { |
83 | | - $sidClaim = $idTokenHint->claims()->get('sid'); |
84 | | - } |
| 82 | + // If id_token_hint was provided, resolve session ID |
| 83 | + $idTokenHint = $logoutRequest->getIdTokenHint(); |
| 84 | + if ($idTokenHint !== null) { |
| 85 | + $sidClaim = $idTokenHint->claims()->get('sid'); |
| 86 | + } |
85 | 87 |
|
86 | | - // Check if RP is requesting logout for session that previously existed (not this current session). |
87 | | - // Claim 'sid' from 'id_token_hint' logout parameter indicates for which session should logout be |
88 | | - // performed (sid is session ID used when ID token was issued during authn). If the requested |
89 | | - // sid is different from the current session ID, try to find the requested session. |
90 | | - if ( |
91 | | - $sidClaim !== null && |
92 | | - $this->sessionService->getCurrentSession()->getSessionId() !== $sidClaim |
93 | | - ) { |
94 | | - try { |
95 | | - if (($sidSession = $this->sessionService->getSessionById($sidClaim)) !== null) { |
96 | | - $sidSessionValidAuthorities = $sidSession->getAuthorities(); |
97 | | - |
98 | | - if (! empty($sidSessionValidAuthorities)) { |
99 | | - $wasLogoutActionCalled = true; |
100 | | - // Create a SessionLogoutTicket so that the sid is available in the static logoutHandler() |
101 | | - $this->sessionLogoutTicketStoreBuilder->getInstance()->add($sidClaim); |
102 | | - // Initiate logout for every valid auth source for the requested session. |
103 | | - foreach ($sidSessionValidAuthorities as $authSourceId) { |
104 | | - $sidSession->doLogout($authSourceId); |
| 88 | + // Check if RP is requesting logout for session that previously existed (not this current session). |
| 89 | + // Claim 'sid' from 'id_token_hint' logout parameter indicates for which session should logout be |
| 90 | + // performed (sid is session ID used when ID token was issued during authn). If the requested |
| 91 | + // sid is different from the current session ID, try to find the requested session. |
| 92 | + if ( |
| 93 | + $sidClaim !== null && |
| 94 | + $this->sessionService->getCurrentSession()->getSessionId() !== $sidClaim |
| 95 | + ) { |
| 96 | + try { |
| 97 | + if (($sidSession = $this->sessionService->getSessionById($sidClaim)) !== null) { |
| 98 | + $sidSessionValidAuthorities = $sidSession->getAuthorities(); |
| 99 | + |
| 100 | + if (! empty($sidSessionValidAuthorities)) { |
| 101 | + $wasLogoutActionCalled = true; |
| 102 | + // Create a SessionLogoutTicket so that the sid is available in the static logoutHandler() |
| 103 | + $this->sessionLogoutTicketStoreBuilder->getInstance()->add($sidClaim); |
| 104 | + // Initiate logout for every valid auth source for the requested session. |
| 105 | + foreach ($sidSessionValidAuthorities as $authSourceId) { |
| 106 | + $sidSession->doLogout($authSourceId); |
| 107 | + } |
105 | 108 | } |
106 | 109 | } |
| 110 | + } catch (Throwable $exception) { |
| 111 | + $this->loggerService->warning( |
| 112 | + sprintf('Logout: could not get session with ID %s, error: %s', $sidClaim, $exception->getMessage()) |
| 113 | + ); |
107 | 114 | } |
108 | | - } catch (Throwable $exception) { |
109 | | - $this->loggerService->warning( |
110 | | - sprintf('Logout: could not get session with ID %s, error: %s', $sidClaim, $exception->getMessage()) |
111 | | - ); |
112 | 115 | } |
113 | | - } |
114 | 116 |
|
115 | | - $currentSessionValidAuthorities = $this->sessionService->getCurrentSession()->getAuthorities(); |
116 | | - if (! empty($currentSessionValidAuthorities)) { |
117 | | - $wasLogoutActionCalled = true; |
118 | | - // Initiate logout for every valid auth source for the current session. |
119 | | - foreach ($this->sessionService->getCurrentSession()->getAuthorities() as $authSourceId) { |
120 | | - $this->sessionService->getCurrentSession()->doLogout($authSourceId); |
| 117 | + $currentSessionValidAuthorities = $this->sessionService->getCurrentSession()->getAuthorities(); |
| 118 | + if (! empty($currentSessionValidAuthorities)) { |
| 119 | + $wasLogoutActionCalled = true; |
| 120 | + // Initiate logout for every valid auth source for the current session. |
| 121 | + foreach ($this->sessionService->getCurrentSession()->getAuthorities() as $authSourceId) { |
| 122 | + $this->sessionService->getCurrentSession()->doLogout($authSourceId); |
| 123 | + } |
121 | 124 | } |
122 | | - } |
123 | 125 |
|
124 | | - // Set indication for OIDC initiated logout back to false, so that the logoutHandler() method does not |
125 | | - // run for other logout initiated actions, like (currently) re-authentication... |
126 | | - $this->sessionService->setIsOidcInitiatedLogout(false); |
127 | | - |
128 | | - return $this->resolveResponse($logoutRequest, $wasLogoutActionCalled); |
| 126 | + // Set indication for OIDC initiated logout back to false, so that the logoutHandler() method does not |
| 127 | + // run for other logout initiated actions, like (currently) re-authentication... |
| 128 | + $this->sessionService->setIsOidcInitiatedLogout(false); |
| 129 | + |
| 130 | + MetricLogger::getInstance()->logMetric( |
| 131 | + 'oidc', |
| 132 | + 'logout', |
| 133 | + [ |
| 134 | + 'sessionId' => $this->sessionService->getCurrentSession()->getSessionId(), |
| 135 | + 'sessionTrackID' => $this->sessionService->getCurrentSession()->getTrackID(), |
| 136 | + 'sidClaim' => $sidClaim, |
| 137 | + 'idTokenHint' => $idTokenHint |
| 138 | + ] |
| 139 | + ); |
| 140 | + |
| 141 | + return $this->resolveResponse($logoutRequest, $wasLogoutActionCalled); |
| 142 | + } catch (Exception $e) { |
| 143 | + MetricLogger::getInstance()->logMetric( |
| 144 | + 'oidc', |
| 145 | + 'error', |
| 146 | + [ |
| 147 | + 'message' => $e->getMessage(), |
| 148 | + 'oidc' => [ |
| 149 | + 'endpoint' => 'logout', |
| 150 | + ] |
| 151 | + |
| 152 | + ] |
| 153 | + ); |
| 154 | + |
| 155 | + throw $e; |
| 156 | + } |
129 | 157 | } |
130 | 158 |
|
131 | 159 | /** |
|
0 commit comments