Skip to content

Commit

Permalink
Merge branch 'feature/openid-support' of https://github.com/indykonin…
Browse files Browse the repository at this point in the history
…g/2FAuth into indykoning-feature/openid-support
  • Loading branch information
Bubka committed Dec 6, 2023
2 parents 874f108 + 160f55f commit a407f47
Show file tree
Hide file tree
Showing 13 changed files with 419 additions and 3 deletions.
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ WEBAUTHN_ID=null

WEBAUTHN_USER_VERIFICATION=preferred

### OpenID settings ###

# OPENID_AUTHORIZE_URL=
# OPENID_TOKEN_URL=
# OPENID_USERINFO_URL=
# OPENID_CLIENT_ID=
# OPENID_CLIENT_SECRET=


# Use this setting to declare trusted proxied.
# Supported:
Expand Down
44 changes: 44 additions & 0 deletions app/Http/Controllers/Auth/SocialiteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App\Http\Controllers\Auth;

use App\Facades\Settings;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;

class SocialiteController extends Controller
{
public function redirect(Request $request, $driver)
{
return Socialite::driver($driver)->redirect();
}

public function callback(Request $request, $driver)
{
$socialiteUser = Socialite::driver($driver)->user();

/** @var User $user */
$user = User::firstOrNew([
'email' => $socialiteUser->getEmail(),
], [
'name' => $socialiteUser->getName(),
'password' => bcrypt(Str::random()),
]);

if (!$user->exists && Settings::get('disableRegistrationSso')) {
return response(401);
}

$user->last_seen_at = Carbon::now()->format('Y-m-d H:i:s');
$user->save();

Auth::guard()->login($user, true);

return redirect('/accounts?authenticated');
}
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/SinglePageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function index()
$isTestingApp = config('2fauth.config.isTestingApp') ? 'true' : 'false';
$lang = App::getLocale();
$locales = collect(config('2fauth.locales'))->toJson(); /** @phpstan-ignore-line */
$openidAuth = config('services.openid.client_secret') ? true : false;

// if (Auth::user()->preferences)

Expand All @@ -35,6 +36,7 @@ public function index()
'appConfig' => collect([
'proxyAuth' => $proxyAuth,
'proxyLogoutUrl' => $proxyLogoutUrl,
'openidAuth' => $openidAuth,
'subdirectory' => $subdir,
])->toJson(),
'defaultPreferences' => $defaultPreferences,
Expand Down
5 changes: 5 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
use App\Listeners\DissociateTwofaccountFromGroup;
use App\Listeners\ReleaseRadar;
use App\Listeners\ResetUsersPreference;
use App\Providers\Socialite\RegisterOpenId;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Manager\SocialiteWasCalled;

class EventServiceProvider extends ServiceProvider
{
Expand All @@ -37,6 +39,9 @@ class EventServiceProvider extends ServiceProvider
ScanForNewReleaseCalled::class => [
ReleaseRadar::class,
],
SocialiteWasCalled::class => [
RegisterOpenId::class,
],
];

/**
Expand Down
90 changes: 90 additions & 0 deletions app/Providers/Socialite/OpenId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace App\Providers\Socialite;

use GuzzleHttp\RequestOptions;
use InvalidArgumentException;
use SocialiteProviders\Manager\OAuth2\AbstractProvider;
use SocialiteProviders\Manager\OAuth2\User;
use SocialiteProviders\Manager\SocialiteWasCalled;

class OpenId extends AbstractProvider
{
public const IDENTIFIER = 'OPENID';

/**
* {@inheritdoc}
*/
protected $scopes = ['openid profile email'];

/**
* {@inheritdoc}
*/
public static function additionalConfigKeys()
{
return ['token_url', 'authorize_url', 'userinfo_url'];
}

/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase($this->getConfig('authorize_url'), $state);
}

/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return $this->getConfig('token_url');
}

/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get($this->getConfig('userinfo_url'), [
RequestOptions::HEADERS => [
'Authorization' => 'Bearer '.$token,
],
]);

return json_decode((string) $response->getBody(), true);
}

/**
* {@inheritdoc}
*/
protected function refreshToken($refreshToken)
{
return $this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::FORM_PARAMS => [
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
],
]);
}

/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'email' => $user['email'] ?? null,
'email_verified' => $user['email_verified'] ?? null,
'name' => $user['name'] ?? null,
'given_name' => $user['given_name'] ?? null,
'family_name' => $user['family_name'] ?? null,
'preferred_username' => $user['preferred_username'] ?? null,
'nickname' => $user['nickname'] ?? null,
'groups' => $user['groups'] ?? null,
'id' => $user['sub'],
]);
}
}
13 changes: 13 additions & 0 deletions app/Providers/Socialite/RegisterOpenId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Providers\Socialite;

use SocialiteProviders\Manager\SocialiteWasCalled;

class RegisterOpenId
{
public function __invoke(SocialiteWasCalled $socialiteWasCalled)
{
$socialiteWasCalled->extendSocialite('openid', OpenId::class);
}
}
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
"laragear/webauthn": "^1.2.0",
"laravel/framework": "^10.10",
"laravel/passport": "^11.2",
"laravel/socialite": "^5.10",
"laravel/tinker": "^2.8",
"laravel/ui": "^4.2",
"paragonie/constant_time_encoding": "^2.6",
"socialiteproviders/manager": "^4.4",
"spatie/eloquent-sortable": "^4.0.1",
"spomky-labs/otphp": "^11.0"
},
Expand Down
Loading

0 comments on commit a407f47

Please sign in to comment.