Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,8 @@ OIDC_CLIENT_ID=deming
OIDC_CLIENT_SECRET=deming
OIDC_BASE_URL=http://auth.lan
OIDC_SUFFIX=""
OIDC_USE_ID_TOKEN=false # true pour décoder le JWT
OIDC_JWT_ALG=RS256 # RS256 ou HS256. utile uniquement avec OIDC_USE_ID_TOKEN=true
OIDC_JWT_SECRET_OR_KEY="" # secret pour HS256 ou clé au format PEM pour RS256
OIDC_REDIRECT_URI=${APP_URL}auth/callback/oidc
APP_VERSION=2025.08.13
53 changes: 52 additions & 1 deletion app/Providers/Socialite/GenericSocialiteProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
namespace App\Providers\Socialite;

use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Arr;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Log;

/**
Expand Down Expand Up @@ -96,15 +99,45 @@ protected function getTokenUrl()
return $this->getOIDCUrl() . '/token';
}

/**
* {@inheritdoc}
*/
public function user()
{
if ($this->user) {
return $this->user;
}

if ($this->hasInvalidState()) {
throw new InvalidStateException;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

$response = $this->getAccessTokenResponse($this->getCode());

$user = $this->getUserByToken(Arr::get($response, 'access_token'), Arr::get($response, 'id_token'));

return $this->userInstance($response, $user);
}


/**
* @param string $token
*
* @throws GuzzleException
*
* @return array|mixed
*/
protected function getUserByToken($token)
protected function getUserByToken($token, $idToken = null)
{
$useIdToken = config('services.oidc.use_id_token', false);

if ($useIdToken) {
if (!$idToken) {
throw new \Exception('OIDC_USE_ID_TOKEN=true but id_token not received');
}
return $this->decodeIdToken($idToken);
}

$base_url = $this->getOIDCUrl() . '/userinfo';
// If userinfo endpoint set, use it instead
if (config('services.oidc.userinfo_endpoint')) {
Expand Down Expand Up @@ -140,4 +173,22 @@ protected function mapUserToObject(array $user)
}
return (new User())->setRaw($user)->map($socialite_user);
}

protected function decodeIdToken($idToken)
{
$alg = config('services.oidc.jwt_alg', 'RS256');
$key = config('services.oidc.jwt_secret_or_key');

if (!$key) {
throw new \Exception('JWT secret or public key not configured');
}

try {
$decoded = JWT::decode($idToken, new Key($key, $alg));
} catch (\Exception $e) {
throw new \Exception('Failed to decode ID token: '.$e->getMessage(), 0, $e);
}

return json_decode(json_encode($decoded), true);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"license": "GPLv3",
"require": {
"php": "^8.2",
"firebase/php-jwt": "^7.0",
"directorytree/ldaprecord-laravel": "^3.4",
"erusev/parsedown": "^1.7",
"laravel/framework": "^11.9",
Expand Down
3 changes: 3 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
'authorize_endpoint' => env('OIDC_AUTHORIZE_ENDPOINT', null),
'token_endpoint' => env('OIDC_TOKEN_ENDPOINT', null),
'userinfo_endpoint' => env('OIDC_USERINFO_ENDPOINT', null),
'use_id_token' => env('OIDC_USE_ID_TOKEN', false),
'jwt_alg' => env('OIDC_JWT_ALG', 'RS256'),
'jwt_secret_or_key' => env('OIDC_JWT_SECRET_OR_KEY', ''),
'map_user_attr' => [
'id' => 'sub',
'name' => 'name',
Expand Down