mirror of
https://github.com/Bubka/2FAuth.git
synced 2024-12-26 00:50:12 +01:00
Merge branch 'feature/openid-support' of https://github.com/indykoning/2FAuth into indykoning-feature/openid-support
This commit is contained in:
commit
a407f4742e
@ -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:
|
||||
|
44
app/Http/Controllers/Auth/SocialiteController.php
Normal file
44
app/Http/Controllers/Auth/SocialiteController.php
Normal file
@ -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');
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
||||
@ -35,6 +36,7 @@ public function index()
|
||||
'appConfig' => collect([
|
||||
'proxyAuth' => $proxyAuth,
|
||||
'proxyLogoutUrl' => $proxyLogoutUrl,
|
||||
'openidAuth' => $openidAuth,
|
||||
'subdirectory' => $subdir,
|
||||
])->toJson(),
|
||||
'defaultPreferences' => $defaultPreferences,
|
||||
|
@ -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
|
||||
{
|
||||
@ -37,6 +39,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
ScanForNewReleaseCalled::class => [
|
||||
ReleaseRadar::class,
|
||||
],
|
||||
SocialiteWasCalled::class => [
|
||||
RegisterOpenId::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
90
app/Providers/Socialite/OpenId.php
Normal file
90
app/Providers/Socialite/OpenId.php
Normal file
@ -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
app/Providers/Socialite/RegisterOpenId.php
Normal file
13
app/Providers/Socialite/RegisterOpenId.php
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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"
|
||||
},
|
||||
|
222
composer.lock
generated
222
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "88245443209e7afe41d4a37b26f07c65",
|
||||
"content-hash": "8ab04001cb3cb872bf0848236af3fc20",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
@ -2310,6 +2310,76 @@
|
||||
},
|
||||
"time": "2023-07-14T13:56:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/socialite",
|
||||
"version": "v5.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/socialite.git",
|
||||
"reference": "f376b6eda9084899e37ac08bafd64a95edf9c6c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/f376b6eda9084899e37ac08bafd64a95edf9c6c0",
|
||||
"reference": "f376b6eda9084899e37ac08bafd64a95edf9c6c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0",
|
||||
"league/oauth1-client": "^1.10.1",
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^8.0|^9.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Socialite\\SocialiteServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Socialite": "Laravel\\Socialite\\Facades\\Socialite"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Socialite\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.",
|
||||
"homepage": "https://laravel.com",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"oauth"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/socialite/issues",
|
||||
"source": "https://github.com/laravel/socialite"
|
||||
},
|
||||
"time": "2023-10-30T22:09:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
"version": "v2.8.2",
|
||||
@ -3028,6 +3098,82 @@
|
||||
],
|
||||
"time": "2023-08-05T12:09:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/oauth1-client",
|
||||
"version": "v1.10.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/oauth1-client.git",
|
||||
"reference": "d6365b901b5c287dd41f143033315e2f777e1167"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167",
|
||||
"reference": "d6365b901b5c287dd41f143033315e2f777e1167",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*",
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"guzzlehttp/psr7": "^1.7|^2.0",
|
||||
"php": ">=7.1||>=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-simplexml": "*",
|
||||
"friendsofphp/php-cs-fixer": "^2.17",
|
||||
"mockery/mockery": "^1.3.3",
|
||||
"phpstan/phpstan": "^0.12.42",
|
||||
"phpunit/phpunit": "^7.5||9.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-simplexml": "For decoding XML-based responses."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev",
|
||||
"dev-develop": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\OAuth1\\Client\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Corlett",
|
||||
"email": "bencorlett@me.com",
|
||||
"homepage": "http://www.webcomm.com.au",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "OAuth 1.0 Client Library",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"SSO",
|
||||
"authorization",
|
||||
"bitbucket",
|
||||
"identity",
|
||||
"idp",
|
||||
"oauth",
|
||||
"oauth1",
|
||||
"single sign on",
|
||||
"trello",
|
||||
"tumblr",
|
||||
"twitter"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/oauth1-client/issues",
|
||||
"source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.1"
|
||||
},
|
||||
"time": "2022-04-15T14:02:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"version": "8.5.4",
|
||||
@ -4930,6 +5076,80 @@
|
||||
],
|
||||
"time": "2023-04-15T23:01:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v4.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Manager.git",
|
||||
"reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/df5e45b53d918ec3d689f014d98a6c838b98ed96",
|
||||
"reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0",
|
||||
"laravel/socialite": "~5.0",
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^6.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"SocialiteProviders\\Manager\\ServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Manager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andy Wendt",
|
||||
"email": "andy@awendt.com"
|
||||
},
|
||||
{
|
||||
"name": "Anton Komarev",
|
||||
"email": "a.komarev@cybercog.su"
|
||||
},
|
||||
{
|
||||
"name": "Miguel Piedrafita",
|
||||
"email": "soy@miguelpiedrafita.com"
|
||||
},
|
||||
{
|
||||
"name": "atymic",
|
||||
"email": "atymicq@gmail.com",
|
||||
"homepage": "https://atymic.dev"
|
||||
}
|
||||
],
|
||||
"description": "Easily add new or override built-in providers in Laravel Socialite.",
|
||||
"homepage": "https://socialiteproviders.com",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"manager",
|
||||
"oauth",
|
||||
"providers",
|
||||
"socialite"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/socialiteproviders/manager/issues",
|
||||
"source": "https://github.com/socialiteproviders/manager"
|
||||
},
|
||||
"time": "2023-08-27T23:46:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/eloquent-sortable",
|
||||
"version": "4.0.2",
|
||||
|
@ -71,6 +71,7 @@
|
||||
'lastRadarScan' => 0,
|
||||
'latestRelease' => false,
|
||||
'disableRegistration' => false,
|
||||
'disableRegistrationSso' => false,
|
||||
],
|
||||
|
||||
/*
|
||||
@ -104,4 +105,4 @@
|
||||
'getOtpOnRequest' => true,
|
||||
],
|
||||
|
||||
];
|
||||
];
|
||||
|
11
config/services/openid.php
Normal file
11
config/services/openid.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'token_url' => env('OPENID_TOKEN_URL'),
|
||||
'authorize_url' => env('OPENID_AUTHORIZE_URL'),
|
||||
'userinfo_url' => env('OPENID_USERINFO_URL'),
|
||||
|
||||
'client_id' => env('OPENID_CLIENT_ID'),
|
||||
'client_secret' => env('OPENID_CLIENT_SECRET'),
|
||||
'redirect' => '/socialite/callback/openid',
|
||||
];
|
@ -78,6 +78,12 @@ services:
|
||||
# authentication checks. That means your proxy is fully responsible of the authentication process, 2FAuth will
|
||||
# trust him as long as headers are presents.
|
||||
- AUTHENTICATION_GUARD=web-guard
|
||||
# OpenId settings
|
||||
# - OPENID_AUTHORIZE_URL=
|
||||
# - OPENID_TOKEN_URL=
|
||||
# - OPENID_USERINFO_URL=
|
||||
# - OPENID_CLIENT_ID=
|
||||
# - OPENID_CLIENT_SECRET=
|
||||
# Name of the HTTP headers sent by the reverse proxy that identifies the authenticated user at proxy level.
|
||||
# Check your proxy documentation to find out how these headers are named (i.e 'REMOTE_USER', 'REMOTE_EMAIL', etc...)
|
||||
# (only relevant when AUTHENTICATION_GUARD is set to 'reverse-proxy-guard')
|
||||
|
@ -115,6 +115,11 @@
|
||||
{{ $t('auth.login_and_password') }}
|
||||
</a>
|
||||
</p>
|
||||
<p v-if="appSettings.openidAuth">{{ $t('auth.sign_in_using') }}
|
||||
<a id="lnkSignWithOpenID" class="is-link" href="/socialite/redirect/openid">
|
||||
OpenID
|
||||
</a>
|
||||
</p>
|
||||
<p v-if="appSettings.disableRegistration == false" class="mt-4">
|
||||
{{ $t('auth.forms.dont_have_account_yet') }}
|
||||
<RouterLink id="lnkRegister" :to="{ name: 'register' }" class="is-link">
|
||||
@ -143,6 +148,11 @@
|
||||
{{ $t('auth.webauthn.security_device') }}
|
||||
</a>
|
||||
</p>
|
||||
<p v-if="appSettings.openidAuth">{{ $t('auth.sign_in_using') }}
|
||||
<a id="lnkSignWithOpenID" class="is-link" href="/socialite/redirect/openid">
|
||||
OpenID
|
||||
</a>
|
||||
</p>
|
||||
<p v-if="appSettings.disableRegistration == false" class="mt-4">
|
||||
{{ $t('auth.forms.dont_have_account_yet') }}
|
||||
<RouterLink id="lnkRegister" :to="{ name: 'register' }" class="is-link">
|
||||
@ -153,4 +163,4 @@
|
||||
</FormWrapper>
|
||||
<!-- footer -->
|
||||
<VueFooter/>
|
||||
</template>
|
||||
</template>
|
||||
|
@ -5,6 +5,7 @@
|
||||
use App\Http\Controllers\Auth\PasswordController;
|
||||
use App\Http\Controllers\Auth\RegisterController;
|
||||
use App\Http\Controllers\Auth\ResetPasswordController;
|
||||
use App\Http\Controllers\Auth\SocialiteController;
|
||||
use App\Http\Controllers\Auth\UserController;
|
||||
use App\Http\Controllers\Auth\WebAuthnDeviceLostController;
|
||||
use App\Http\Controllers\Auth\WebAuthnLoginController;
|
||||
@ -47,6 +48,9 @@
|
||||
Route::group(['middleware' => ['guest', 'throttle:10,1']], function () {
|
||||
Route::post('user/login', [LoginController::class, 'login'])->name('user.login');
|
||||
Route::post('webauthn/login', [WebAuthnLoginController::class, 'login'])->name('webauthn.login');
|
||||
|
||||
Route::get('/socialite/redirect/{driver}', [SocialiteController::class, 'redirect'])->name('socialite.redirect');
|
||||
Route::get('/socialite/callback/{driver}', [SocialiteController::class, 'callback'])->name('socialite.callback');
|
||||
});
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user