Skip to content

Commit cc10d1d

Browse files
committed
Merge branch 'fix/oidc-logout' into development
2 parents 0254527 + a0942ef commit cc10d1d

6 files changed

Lines changed: 86 additions & 8 deletions

File tree

.env.example.complete

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ OIDC_GROUPS_CLAIM=groups
274274
OIDC_REMOVE_FROM_GROUPS=false
275275
OIDC_EXTERNAL_ID_CLAIM=sub
276276

277+
# OIDC Logout Feature: Its value should be value of end_session_endpoint from <issuer>/.well-known/openid-configuration
278+
OIDC_END_SESSION_ENDPOINT=null
279+
280+
277281
# Disable default third-party services such as Gravatar and Draw.IO
278282
# Service-specific options will override this option
279283
DISABLE_EXTERNAL_SERVICES=false

app/Access/Controllers/OidcController.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,18 @@ public function callback(Request $request)
6363

6464
return redirect()->intended();
6565
}
66+
67+
/**
68+
* OIDC Logout Feature: Start the authorization logout flow via OIDC.
69+
*/
70+
public function logout()
71+
{
72+
try {
73+
return $this->oidcService->logout();
74+
} catch (OidcException $exception) {
75+
$this->showErrorNotification($exception->getMessage());
76+
return redirect('/logout');
77+
}
78+
}
79+
6680
}

app/Access/Oidc/OidcService.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,12 @@ protected function processAccessTokenCallback(OidcAccessToken $accessToken, Oidc
217217
$settings->keys,
218218
);
219219

220+
// OIDC Logout Feature: Temporarily save token in session
221+
$access_token_for_logout = $idTokenText;
222+
session()->put("oidctoken", $access_token_for_logout);
223+
224+
225+
220226
$returnClaims = Theme::dispatch(ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE, $idToken->getAllClaims(), [
221227
'access_token' => $accessToken->getToken(),
222228
'expires_in' => $accessToken->getExpires(),
@@ -284,4 +290,37 @@ protected function shouldSyncGroups(): bool
284290
{
285291
return $this->config()['user_to_groups'] !== false;
286292
}
293+
294+
295+
/**
296+
* OIDC Logout Feature: Initiate a logout flow.
297+
*
298+
* @throws OidcException
299+
*
300+
* @return string
301+
*/
302+
public function logout() {
303+
304+
$config = $this->config();
305+
$app_url = env('APP_URL', '');
306+
$end_session_endpoint = $config["end_session_endpoint"];
307+
308+
$oidctoken = session()->get("oidctoken");
309+
session()->invalidate();
310+
311+
if (str_contains($app_url, 'https://')) {
312+
$protocol = 'https://';
313+
} else {
314+
$protocol = 'http://';
315+
}
316+
317+
318+
319+
return redirect($end_session_endpoint.'?id_token_hint='.$oidctoken."&post_logout_redirect_uri=".$protocol.$_SERVER['HTTP_HOST']."/");
320+
321+
322+
}
323+
324+
325+
287326
}

app/Config/oidc.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,9 @@
4747
'groups_claim' => env('OIDC_GROUPS_CLAIM', 'groups'),
4848
// When syncing groups, remove any groups that no longer match. Otherwise sync only adds new groups.
4949
'remove_from_groups' => env('OIDC_REMOVE_FROM_GROUPS', false),
50+
51+
// OIDC Logout Feature: OAuth2 end_session_endpoint
52+
'end_session_endpoint' => env('OIDC_END_SESSION_ENDPOINT', null),
53+
5054
];
55+

resources/views/layouts/parts/header-user-menu.blade.php

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,28 @@
2929
</li>
3030
<li><hr></li>
3131
<li>
32-
<form action="{{ url(config('auth.method') === 'saml2' ? '/saml2/logout' : '/logout') }}"
33-
method="post">
34-
{{ csrf_field() }}
35-
<button class="icon-item" data-shortcut="logout">
36-
@icon('logout')
37-
<div>{{ trans('auth.logout') }}</div>
38-
</button>
39-
</form>
32+
<?php
33+
// OIDC Logout Feature: Use /oidc/logout if authentication method is oidc.
34+
if (config('auth.method') === 'oidc') {
35+
?>
36+
<form action="/oidc/logout"
37+
method="get">
38+
<?php
39+
// OIDC Logout Feature: Use /oidc/logout if authentication method is oidc.
40+
} else {
41+
?>
42+
<form action="{{ url(config('auth.method') === 'saml2' ? '/saml2/logout' : '/logout') }}"
43+
method="post">
44+
<?php
45+
// OIDC Logout Feature: Use /oidc/logout if authentication method is oidc.
46+
}
47+
?>
48+
{{ csrf_field() }}
49+
<button class="icon-item" data-shortcut="logout">
50+
@icon('logout')
51+
<div>{{ trans('auth.logout') }}</div>
52+
</button>
53+
</form>
4054
</li>
4155
</ul>
4256
</div>

routes/web.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@
332332
// OIDC routes
333333
Route::post('/oidc/login', [AccessControllers\OidcController::class, 'login']);
334334
Route::get('/oidc/callback', [AccessControllers\OidcController::class, 'callback']);
335+
// OIDC Logout Feature: Added to cater OIDC logout
336+
Route::get('/oidc/logout', [AccessControllers\OidcController::class, 'logout']);
335337

336338
// User invitation routes
337339
Route::get('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'showSetPassword']);

0 commit comments

Comments
 (0)