Skip to content

Commit

Permalink
Merge pull request #847 from Kovah/2.x-174-sso
Browse files Browse the repository at this point in the history
SSO login via OAuth / OIDC
  • Loading branch information
Kovah authored Sep 19, 2024
2 parents 25a915f + 347b979 commit e66bd3f
Show file tree
Hide file tree
Showing 45 changed files with 2,500 additions and 577 deletions.
2 changes: 2 additions & 0 deletions app/Http/Controllers/Setup/AccountController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers\Setup;

use App\Actions\Fortify\CreateNewUser;
use App\Enums\Role;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
Expand All @@ -27,6 +28,7 @@ public function index(): View
protected function register(Request $request): RedirectResponse
{
$user = (new CreateNewUser())->create($request->input());
$user->assignRole(Role::ADMIN);

Auth::login($user, true);

Expand Down
78 changes: 78 additions & 0 deletions app/Http/Controllers/SocialiteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace App\Http\Controllers;

use App\Actions\Settings\SetDefaultSettingsForUser;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;

class SocialiteController extends Controller
{
public function redirect(string $provider)
{
$this->authorizeOauthRequest($provider);

return Socialite::driver($provider)->redirect();
}

public function callback(string $provider)
{
$this->authorizeOauthRequest($provider);

$authUser = Socialite::driver($provider)->user();

// If a user with the provided email address already exists, register the oauth login
if ($user = User::where('email', $authUser->getEmail())->first()) {
if ($user->sso_provider !== null && $user->sso_provider !== $provider) {
abort(403, trans('auth.sso_wrong_provider', [
'currentProvider' => trans('auth.sso_provider.' . $provider),
'userProvider' => trans('auth.sso_provider.' . $user->sso_provider),
]));
}

$user->update([
'name' => $authUser->getNickname(),
'sso_id' => $authUser->id,
'sso_provider' => $provider,
'sso_token' => $authUser->token ?? null,
'sso_token_secret' => $authUser->tokenSecret ?? null,
'sso_refresh_token' => $authUser->refreshToken ?? null,
]);
} else {
// otherwise, either update an existing oauth user or register a new user
$user = User::updateOrCreate([
'email' => $authUser->getEmail(),
'sso_id' => $authUser->getId(),
'sso_provider' => $provider,
], [
'name' => $authUser->getNickname(),
'email' => $authUser->getEmail(),
'sso_id' => $authUser->getId(),
'sso_provider' => $provider,
'sso_token' => $authUser->token ?? null,
'sso_token_secret' => $authUser->tokenSecret ?? null,
'sso_refresh_token' => $authUser->refreshToken ?? null,
]);

if ($user->wasRecentlyCreated) {
(new SetDefaultSettingsForUser($user))->up();
}
}

Auth::login($user);

return redirect()->route('dashboard');
}

protected function authorizeOauthRequest(string $provider): void
{
if (config('auth.sso.enabled') !== true || !in_array($provider, config('auth.sso.providers'))) {
abort(403, trans('auth.unauthorized'));
}

if (config('services.' . $provider . '.enabled') !== true) {
abort(403, trans('auth.sso_provider_disabled'));
}
}
}
2 changes: 1 addition & 1 deletion app/Http/Middleware/VerifyCsrfToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ class VerifyCsrfToken extends Middleware
* @var array
*/
protected $except = [
//
'auth/oauth/oidc/callback'
];
}
18 changes: 18 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
* @property string $email
* @property string $password
* @property string|null $remember_token
* @property string|null $sso_id
* @property string|null $sso_provider
* @property string|null $sso_token
* @property string|null $sso_token_secret
* @property string|null $sso_refresh_token
* @property string|null $two_factor_recovery_codes
* @property string|null $two_factor_secret
* @property Carbon|null $created_at
Expand All @@ -43,11 +48,19 @@ class User extends Authenticatable implements Auditable
'email',
'password',
'blocked_at',
'sso_id',
'sso_provider',
'sso_token',
'sso_token_secret',
'sso_refresh_token',
];

protected $hidden = [
'password',
'remember_token',
'sso_token',
'sso_token_secret',
'sso_refresh_token',
];

protected $casts = [
Expand Down Expand Up @@ -112,4 +125,9 @@ public function isSystemUser(): bool
{
return $this->id === 0;
}

public function isSsoUser(): bool
{
return $this->sso_id !== null;
}
}
12 changes: 12 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Listeners\SavingSettingsListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Manager\SocialiteWasCalled;
use Spatie\LaravelSettings\Events\SavingSettings;

class EventServiceProvider extends ServiceProvider
Expand All @@ -20,6 +21,17 @@ class EventServiceProvider extends ServiceProvider
SavingSettings::class => [
SavingSettingsListener::class,
],
SocialiteWasCalled::class => [
\SocialiteProviders\Auth0\Auth0ExtendSocialite::class . '@handle',
\SocialiteProviders\Authentik\AuthentikExtendSocialite::class . '@handle',
\SocialiteProviders\Azure\AzureExtendSocialite::class . '@handle',
\SocialiteProviders\Cognito\CognitoExtendSocialite::class . '@handle',
\SocialiteProviders\FusionAuth\FusionAuthExtendSocialite::class . '@handle',
\SocialiteProviders\Keycloak\KeycloakExtendSocialite::class . '@handle',
\SocialiteProviders\OIDC\OIDCExtendSocialite::class.'@handle',
\SocialiteProviders\Okta\OktaExtendSocialite::class . '@handle',
//\SocialiteProviders\Zitadel\ZitadelExtendSocialite::class . '@handle', // @TODO enabling this leads to SocialiteProviders\Zitadel\ZitadelExtendSocialite does not exist exception
],
];

/**
Expand Down
18 changes: 14 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"type": "project",
"require": {
"php": "^8.1 | ^8.2 | ^8.3",
"ext-pdo": "*",
"ext-ftp": "*",
"ext-dom": "*",
"ext-ftp": "*",
"ext-pdo": "*",
"composer/semver": "^3.3.1",
"doctrine/dbal": "^3.7",
"guzzlehttp/guzzle": "^7.0",
Expand All @@ -16,6 +16,7 @@
"laravel/fortify": "^1.7",
"laravel/framework": "^v10.43",
"laravel/sanctum": "^v3.3",
"laravel/socialite": "^5.16",
"league/csv": "^9.6",
"league/flysystem-aws-s3-v3": "^3.0",
"league/flysystem-ftp": "^3.0",
Expand All @@ -26,12 +27,21 @@
"rap2hpoutre/laravel-log-viewer": "^2.2",
"sentry/sentry-laravel": "^4.2.0",
"shaarli/netscape-bookmark-parser": "dev-master",
"socialiteproviders/auth0": "^4.2",
"socialiteproviders/authentik": "^5.2",
"socialiteproviders/cognito": "*",
"socialiteproviders/fusionauth": "^5.0",
"socialiteproviders/keycloak": "^5.3",
"socialiteproviders/microsoft-azure": "^5.2",
"socialiteproviders/okta": "^4.4",
"socialiteproviders/zitadel": "*",
"spatie/laravel-activitylog": "^4.5",
"spatie/laravel-backup": "^8.1.2",
"spatie/laravel-permission": "^6.3.0",
"spatie/laravel-settings": "^3.2.3",
"symfony/http-client": "^6.0",
"symfony/mailgun-mailer": "^6.0"
"symfony/mailgun-mailer": "^6.0",
"kovah/laravel-socialite-oidc": "^0.2.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.2",
Expand All @@ -40,7 +50,7 @@
"fakerphp/faker": "^1.12",
"laravel/tinker": "^2.2",
"mockery/mockery": "^1.3",
"nunomaduro/collision": "^6.1",
"nunomaduro/collision": "^v7.10",
"phpunit/phpunit": "^10.0",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5"
Expand Down
Loading

0 comments on commit e66bd3f

Please sign in to comment.