Skip to content

Commit

Permalink
fix(OIDC): Extend OpenIDConnectClient for better integration
Browse files Browse the repository at this point in the history
* Uses Laravel session management instead of default handler
* Checks if a well-known end_session_endpoint is available in sign out.
  If it is not available, informs the user that she/he is still logged
  in at the IDP.
  • Loading branch information
pizkaz committed Oct 16, 2024
1 parent 7e2047a commit f4ad351
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 3 deletions.
6 changes: 5 additions & 1 deletion app/Auth/OIDC/OIDCController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Jumbojett\OpenIDConnectClient;
use Jumbojett\OpenIDConnectClientException;

class OIDCController extends Controller
{
Expand Down Expand Up @@ -111,6 +111,10 @@ public function signout(Request $request)

public function signoutRedirectURL(string $logout_url)
{
if(!$this->oidc->hasEndSessionEndpoint()) {
return false;
}

$params = [
'id_token' => session('oidc_id_token'),
'logout_url' => $logout_url,
Expand Down
74 changes: 74 additions & 0 deletions app/Auth/OIDC/OpenIDConnectClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Heavily inspired by https://github.com/jumbojett/OpenID-Connect-PHP/issues/374#issuecomment-1559028131
*/

namespace App\Auth\OIDC;

use App;
use Jumbojett\OpenIDConnectClient as OpenIDConnectClientBase;
use Session;

class OpenIDConnectClient extends OpenIDConnectClientBase
{
protected function startSession(): void
{
// Nothing to do here, as Laravel does the magic
}

protected function commitSession(): void
{
Session::save();
}

/**
* @param string $key
*/
protected function getSessionKey($key): mixed
{
if (!Session::has($key)) {
return false;
}

return Session::get($key);
}

/**
* @param string $key
* @param mixed $value mixed
*/
protected function setSessionKey($key, $value): void
{
Session::put($key, $value);
}

/**
* @param string $key
*/
protected function unsetSessionKey($key): void
{
Session::remove($key);
}

/**
* Overwrite the redirect method to use Laravel abort method.
* Sometimes the error 'Cannot modify header information - headers already sent' was thrown.
* By using Laravel abort method, this error is prevented.
* @param string $url
* @return void
*/
public function redirect(string $url): void
{
App::abort(302, '', ['Location' => $url]);
}

/**
* Checks if an end_session_endpoint is available in the OIDC provider's well-known configuration.
* @return {boolean}
*/
public function hasEndSessionEndpoint(): bool
{
return (bool) $this->getProviderConfigValue('end_session_endpoint', false);
}

}
6 changes: 6 additions & 0 deletions app/Http/Controllers/api/v1/auth/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public function logout(Request $request)
{
// Redirect url after logout
$redirect = false;
// Message to display on logout, e.g. incomplete logout
$message = null;

// Logout from external authentication provider
switch (\Auth::user()->authenticator) {
Expand All @@ -73,6 +75,9 @@ public function logout(Request $request)
break;
case 'oidc':
$redirect = app(OIDCController::class)->signoutRedirectURL(url('/logout'));
if (!$redirect) {
$message = 'oidc_incomplete';
}
break;
}

Expand All @@ -81,6 +86,7 @@ public function logout(Request $request)

return response()->json([
'redirect' => $redirect,
'message' => $message
]);
}
}
1 change: 1 addition & 0 deletions lang/en/auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
'redirect' => 'Log in',
'tab_title' => 'OpenID Connect',
'title' => 'Log in with OpenID Connect',
'logout_incomplete' => 'You are still logged in at the OpenID Connect provider.',
],
'password' => 'Password',
'reset_password' => 'Reset password',
Expand Down
4 changes: 3 additions & 1 deletion resources/js/components/MainNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ async function logout () {
return;
}
await router.push({ name: 'logout' });
const message = response.data.message || null;
await router.push({ name: 'logout', query: { message } });
loadingStore.setLoadingFinished();
}
Expand Down
3 changes: 2 additions & 1 deletion resources/js/views/Logout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<template #title> {{ $t('auth.logout') }} </template>
<template #content>
<Message v-if="props.message==null" severity="success" :closable="false" >{{ $t('auth.logout_success') }}</Message>
<Message v-if="props.message === 'session_expired'" severity="warning" :closable="false">{{ $t('auth.session_expired') }}</Message>
<Message v-if="props.message === 'session_expired'" severity="warn" :closable="false">{{ $t('auth.session_expired') }}</Message>
<Message v-if="props.message === 'oidc_incomplete'" severity="warn" :closable="false">{{ $t('auth.oidc.logout_incomplete') }}</Message>
</template>
<template #footer>
<Button
Expand Down

0 comments on commit f4ad351

Please sign in to comment.