mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-04-21 07:22:20 +02:00
WIP Extend SSO implementation with proper naming, add basic tests, rename ENV key from OAUTH_ to SSO_ (#174 #194)
This commit is contained in:
parent
96be6ca0f9
commit
a9d92e8309
@ -24,10 +24,10 @@ class SocialiteController extends Controller
|
||||
|
||||
// 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 !== $provider) {
|
||||
if ($user->sso_provider !== null && $user->sso_provider !== $provider) {
|
||||
abort(403, trans('auth.sso_wrong_provider', [
|
||||
'currentProvider' => $provider,
|
||||
'userProvider' => $user->sso_provider,
|
||||
'currentProvider' => trans('auth.sso.' . $provider),
|
||||
'userProvider' => trans('auth.sso.' . $user->sso_provider),
|
||||
]));
|
||||
}
|
||||
|
||||
@ -67,8 +67,12 @@ class SocialiteController extends Controller
|
||||
|
||||
protected function authorizeOauthRequest(string $provider): void
|
||||
{
|
||||
if (config('auth.oauth.enabled') !== true || !in_array($provider, config('auth.oauth.providers'))) {
|
||||
abort(403, 'Login unauthorized');
|
||||
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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
"spatie/laravel-settings": "^3.2.3",
|
||||
"symfony/http-client": "^6.0",
|
||||
"symfony/mailgun-mailer": "^6.0",
|
||||
"kovah/laravel-socialite-oidc": "^0.1"
|
||||
"kovah/laravel-socialite-oidc": "^0.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.2",
|
||||
@ -50,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"
|
||||
|
72
composer.lock
generated
72
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": "fabba9ddaed0892766b3f3c46a30493e",
|
||||
"content-hash": "82aaed0f0c23a2de44145e73eaa9431b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-crt-php",
|
||||
@ -1928,16 +1928,16 @@
|
||||
},
|
||||
{
|
||||
"name": "kovah/laravel-socialite-oidc",
|
||||
"version": "v0.1",
|
||||
"version": "v0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Kovah/laravel-socialite-oidc.git",
|
||||
"reference": "5bb9f107ec742505d15f09fafd519b4ce2512bc6"
|
||||
"reference": "aca47884e996c964a490d91a3038cde5a4965cd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Kovah/laravel-socialite-oidc/zipball/5bb9f107ec742505d15f09fafd519b4ce2512bc6",
|
||||
"reference": "5bb9f107ec742505d15f09fafd519b4ce2512bc6",
|
||||
"url": "https://api.github.com/repos/Kovah/laravel-socialite-oidc/zipball/aca47884e996c964a490d91a3038cde5a4965cd4",
|
||||
"reference": "aca47884e996c964a490d91a3038cde5a4965cd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1983,7 +1983,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Kovah/laravel-socialite-oidc/issues",
|
||||
"source": "https://github.com/Kovah/laravel-socialite-oidc/tree/v0.1"
|
||||
"source": "https://github.com/Kovah/laravel-socialite-oidc/tree/v0.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1991,7 +1991,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-17T22:50:54+00:00"
|
||||
"time": "2024-09-18T21:45:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laracasts/flash",
|
||||
@ -10386,38 +10386,43 @@
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/collision",
|
||||
"version": "v6.4.0",
|
||||
"version": "v7.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nunomaduro/collision.git",
|
||||
"reference": "f05978827b9343cba381ca05b8c7deee346b6015"
|
||||
"reference": "49ec67fa7b002712da8526678abd651c09f375b2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/f05978827b9343cba381ca05b8c7deee346b6015",
|
||||
"reference": "f05978827b9343cba381ca05b8c7deee346b6015",
|
||||
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2",
|
||||
"reference": "49ec67fa7b002712da8526678abd651c09f375b2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"filp/whoops": "^2.14.5",
|
||||
"php": "^8.0.0",
|
||||
"symfony/console": "^6.0.2"
|
||||
"filp/whoops": "^2.15.3",
|
||||
"nunomaduro/termwind": "^1.15.1",
|
||||
"php": "^8.1.0",
|
||||
"symfony/console": "^6.3.4"
|
||||
},
|
||||
"conflict": {
|
||||
"laravel/framework": ">=11.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^6.4.1",
|
||||
"laravel/framework": "^9.26.1",
|
||||
"laravel/pint": "^1.1.1",
|
||||
"nunomaduro/larastan": "^1.0.3",
|
||||
"nunomaduro/mock-final-classes": "^1.1.0",
|
||||
"orchestra/testbench": "^7.7",
|
||||
"phpunit/phpunit": "^9.5.23",
|
||||
"spatie/ignition": "^1.4.1"
|
||||
"brianium/paratest": "^7.3.0",
|
||||
"laravel/framework": "^10.28.0",
|
||||
"laravel/pint": "^1.13.3",
|
||||
"laravel/sail": "^1.25.0",
|
||||
"laravel/sanctum": "^3.3.1",
|
||||
"laravel/tinker": "^2.8.2",
|
||||
"nunomaduro/larastan": "^2.6.4",
|
||||
"orchestra/testbench-core": "^8.13.0",
|
||||
"pestphp/pest": "^2.23.2",
|
||||
"phpunit/phpunit": "^10.4.1",
|
||||
"sebastian/environment": "^6.0.1",
|
||||
"spatie/laravel-ignition": "^2.3.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "6.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider"
|
||||
@ -10425,6 +10430,9 @@
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"./src/Adapters/Phpunit/Autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"NunoMaduro\\Collision\\": "src/"
|
||||
}
|
||||
@ -10470,7 +10478,7 @@
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-03T12:54:54+00:00"
|
||||
"time": "2023-10-11T15:45:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -11097,12 +11105,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Roave/SecurityAdvisories.git",
|
||||
"reference": "39a2e3360d55163461cbb72e5d7c872b6c8b11a4"
|
||||
"reference": "a7b092bec53b91832e9c5c389ce966b50a8d6e8b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/39a2e3360d55163461cbb72e5d7c872b6c8b11a4",
|
||||
"reference": "39a2e3360d55163461cbb72e5d7c872b6c8b11a4",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a7b092bec53b91832e9c5c389ce966b50a8d6e8b",
|
||||
"reference": "a7b092bec53b91832e9c5c389ce966b50a8d6e8b",
|
||||
"shasum": ""
|
||||
},
|
||||
"conflict": {
|
||||
@ -11215,7 +11223,7 @@
|
||||
"cuyz/valinor": "<0.12",
|
||||
"czim/file-handling": "<1.5|>=2,<2.3",
|
||||
"czproject/git-php": "<4.0.3",
|
||||
"damienharper/auditor-bundle": "<6",
|
||||
"damienharper/auditor-bundle": "<5.2.6",
|
||||
"dapphp/securimage": "<3.6.6",
|
||||
"darylldoyle/safe-svg": "<1.9.10",
|
||||
"datadog/dd-trace": ">=0.30,<0.30.2",
|
||||
@ -11445,7 +11453,7 @@
|
||||
"mantisbt/mantisbt": "<2.26.2",
|
||||
"marcwillmann/turn": "<0.3.3",
|
||||
"matyhtf/framework": "<3.0.6",
|
||||
"mautic/core": "<4.4.12|>=5.0.0.0-alpha,<5.0.4",
|
||||
"mautic/core": "<4.4.13|>=5.0.0.0-alpha,<5.1.1",
|
||||
"mautic/core-lib": ">=1.1.3,<4.4.13|>=5.0.0.0-alpha,<5.1.1",
|
||||
"mdanter/ecc": "<2",
|
||||
"mediawiki/core": "<1.36.2",
|
||||
@ -11914,7 +11922,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-18T18:05:47+00:00"
|
||||
"time": "2024-09-18T21:04:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
@ -20,12 +20,12 @@ return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| OAuth Settings
|
||||
| Single Sign On Settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'oauth' => [
|
||||
'enabled' => env('OAUTH_ENABLED', false),
|
||||
'sso' => [
|
||||
'enabled' => env('SSO_ENABLED', false),
|
||||
'regular_login_disabled' => env('REGULAR_LOGIN_DISABLED', false),
|
||||
'providers' => [
|
||||
'auth0',
|
||||
|
@ -34,104 +34,104 @@ return [
|
||||
// OAuth and SSO
|
||||
|
||||
'auth0' => [
|
||||
'enabled' => env('OAUTH_AUTH0_ENABLED', false),
|
||||
'base_url' => env('OAUTH_AUTH0_BASE_URL'),
|
||||
'client_id' => env('OAUTH_AUTH0_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_AUTH0_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/auth0/callback',
|
||||
'enabled' => env('SSO_AUTH0_ENABLED', false),
|
||||
'base_url' => env('SSO_AUTH0_BASE_URL'),
|
||||
'client_id' => env('SSO_AUTH0_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_AUTH0_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/auth0/callback',
|
||||
],
|
||||
|
||||
'authentik' => [
|
||||
'enabled' => env('OAUTH_AUTHENTIK_ENABLED', false),
|
||||
'base_url' => env('OAUTH_AUTHENTIK_BASE_URL'),
|
||||
'client_id' => env('OAUTH_AUTHENTIK_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_AUTHENTIK_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/authentik/callback',
|
||||
'enabled' => env('SSO_AUTHENTIK_ENABLED', false),
|
||||
'base_url' => env('SSO_AUTHENTIK_BASE_URL'),
|
||||
'client_id' => env('SSO_AUTHENTIK_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_AUTHENTIK_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/authentik/callback',
|
||||
],
|
||||
|
||||
'azure' => [
|
||||
'enabled' => env('OAUTH_AZURE_ENABLED', false),
|
||||
'client_id' => env('OAUTH_AZURE_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_AZURE_CLIENT_SECRET'),
|
||||
'tenant' => env('OAUTH_AZURE_TENANT_ID'),
|
||||
'enabled' => env('SSO_AZURE_ENABLED', false),
|
||||
'client_id' => env('SSO_AZURE_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_AZURE_CLIENT_SECRET'),
|
||||
'tenant' => env('SSO_AZURE_TENANT_ID'),
|
||||
'proxy' => env('PROXY'),
|
||||
'redirect' => '/auth/oauth/azure/callback',
|
||||
'redirect' => '/auth/sso/azure/callback',
|
||||
],
|
||||
|
||||
'cognito' => [
|
||||
'enabled' => env('OAUTH_COGNITO_ENABLED', false),
|
||||
'host' => env('OAUTH_COGNITO_HOST'),
|
||||
'client_id' => env('OAUTH_COGNITO_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_COGNITO_CLIENT_SECRET'),
|
||||
'redirect' => env('OAUTH_COGNITO_CALLBACK_URL'),
|
||||
'scope' => explode(',', env('OAUTH_COGNITO_LOGIN_SCOPE', '')),
|
||||
'logout_uri' => env('OAUTH_COGNITO_SIGN_OUT_URL'),
|
||||
'enabled' => env('SSO_COGNITO_ENABLED', false),
|
||||
'host' => env('SSO_COGNITO_HOST'),
|
||||
'client_id' => env('SSO_COGNITO_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_COGNITO_CLIENT_SECRET'),
|
||||
'redirect' => env('SSO_COGNITO_CALLBACK_URL'),
|
||||
'scope' => explode(',', env('SSO_COGNITO_LOGIN_SCOPE', '')),
|
||||
'logout_uri' => env('SSO_COGNITO_SIGN_OUT_URL'),
|
||||
],
|
||||
|
||||
'fusionauth' => [
|
||||
'enabled' => env('OAUTH_FUSIONAUTH_ENABLED', false),
|
||||
'base_url' => env('OAUTH_FUSIONAUTH_BASE_URL'),
|
||||
'client_id' => env('OAUTH_FUSIONAUTH_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_FUSIONAUTH_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/fusionauth/callback',
|
||||
'enabled' => env('SSO_FUSIONAUTH_ENABLED', false),
|
||||
'base_url' => env('SSO_FUSIONAUTH_BASE_URL'),
|
||||
'client_id' => env('SSO_FUSIONAUTH_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_FUSIONAUTH_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/fusionauth/callback',
|
||||
],
|
||||
|
||||
'google' => [
|
||||
'enabled' => env('OAUTH_GOOGLE_ENABLED', false),
|
||||
'client_id' => env('OAUTH_GOOGLE_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_GOOGLE_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/{provider}/callback',
|
||||
'enabled' => env('SSO_GOOGLE_ENABLED', false),
|
||||
'client_id' => env('SSO_GOOGLE_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_GOOGLE_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/{provider}/callback',
|
||||
],
|
||||
|
||||
'github' => [
|
||||
'enabled' => env('OAUTH_GITHUB_ENABLED', false),
|
||||
'client_id' => env('OAUTH_GITHUB_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_GITHUB_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/github/callback',
|
||||
'enabled' => env('SSO_GITHUB_ENABLED', false),
|
||||
'client_id' => env('SSO_GITHUB_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_GITHUB_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/github/callback',
|
||||
],
|
||||
|
||||
'gitlab' => [
|
||||
'enabled' => env('OAUTH_GITLAB_ENABLED', false),
|
||||
'host' => env('OAUTH_GITLAB_HOST'),
|
||||
'client_id' => env('OAUTH_GITLAB_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_GITLAB_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/gitlab/callback',
|
||||
'enabled' => env('SSO_GITLAB_ENABLED', false),
|
||||
'host' => env('SSO_GITLAB_HOST'),
|
||||
'client_id' => env('SSO_GITLAB_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_GITLAB_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/gitlab/callback',
|
||||
],
|
||||
|
||||
'keycloak' => [
|
||||
'enabled' => env('OAUTH_KEYCLOAK_ENABLED', false),
|
||||
'client_id' => env('OAUTH_KEYCLOAK_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_KEYCLOAK_CLIENT_SECRET'),
|
||||
'realms' => env('OAUTH_KEYCLOAK_REALM'),
|
||||
'redirect' => '/auth/oauth/keycloak/callback',
|
||||
'enabled' => env('SSO_KEYCLOAK_ENABLED', false),
|
||||
'client_id' => env('SSO_KEYCLOAK_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_KEYCLOAK_CLIENT_SECRET'),
|
||||
'realms' => env('SSO_KEYCLOAK_REALM'),
|
||||
'redirect' => '/auth/sso/keycloak/callback',
|
||||
],
|
||||
|
||||
'oidc' => [
|
||||
'enabled' => env('OAUTH_OIDC_ENABLED', false),
|
||||
'base_url' => env('OAUTH_OIDC_BASE_URL'),
|
||||
'client_id' => env('OAUTH_OIDC_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_OIDC_CLIENT_SECRET'),
|
||||
'scopes' => env('OAUTH_OIDC_SCOPES'),
|
||||
'redirect' => '/auth/oauth/oidc/callback',
|
||||
'enabled' => env('SSO_OIDC_ENABLED', false),
|
||||
'base_url' => env('SSO_OIDC_BASE_URL'),
|
||||
'client_id' => env('SSO_OIDC_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_OIDC_CLIENT_SECRET'),
|
||||
'scopes' => env('SSO_OIDC_SCOPES'),
|
||||
'redirect' => '/auth/sso/oidc/callback',
|
||||
],
|
||||
|
||||
'okta' => [
|
||||
'enabled' => env('OAUTH_OKTA_ENABLED', false),
|
||||
'base_url' => env('OAUTH_OKTA_BASE_URL'),
|
||||
'client_id' => env('OAUTH_OKTA_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_OKTA_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/oauth/okta/callback',
|
||||
'enabled' => env('SSO_OKTA_ENABLED', false),
|
||||
'base_url' => env('SSO_OKTA_BASE_URL'),
|
||||
'client_id' => env('SSO_OKTA_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_OKTA_CLIENT_SECRET'),
|
||||
'redirect' => '/auth/sso/okta/callback',
|
||||
],
|
||||
|
||||
'zitadel' => [
|
||||
'enabled' => env('OAUTH_ZITADEL_ENABLED', false),
|
||||
'client_id' => env('OAUTH_ZITADEL_CLIENT_ID'),
|
||||
'client_secret' => env('OAUTH_ZITADEL_CLIENT_SECRET'),
|
||||
'base_url' => env('OAUTH_ZITADEL_BASE_URL'),
|
||||
'organization_id' => env('OAUTH_ZITADEL_ORGANIZATION_ID'),
|
||||
'project_id' => env('OAUTH_ZITADEL_PROJECT_ID'),
|
||||
'post_logout_redirect_uri' => env('OAUTH_ZITADEL_POST_LOGOUT_REDIRECT_URI', '/'),
|
||||
'redirect' => '/auth/oauth/zitadel/callback',
|
||||
'enabled' => env('SSO_ZITADEL_ENABLED', false),
|
||||
'client_id' => env('SSO_ZITADEL_CLIENT_ID'),
|
||||
'client_secret' => env('SSO_ZITADEL_CLIENT_SECRET'),
|
||||
'base_url' => env('SSO_ZITADEL_BASE_URL'),
|
||||
'organization_id' => env('SSO_ZITADEL_ORGANIZATION_ID'),
|
||||
'project_id' => env('SSO_ZITADEL_PROJECT_ID'),
|
||||
'post_logout_redirect_uri' => env('SSO_ZITADEL_POST_LOGOUT_REDIRECT_URI', '/'),
|
||||
'redirect' => '/auth/sso/zitadel/callback',
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -18,6 +18,7 @@ return [
|
||||
|
||||
'failed' => 'These credentials do not match our records.',
|
||||
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
|
||||
'unauthorized' => 'Login unauthorized. Please contact your administrator.',
|
||||
|
||||
'confirm_title' => 'Confirmation required',
|
||||
'confirm' => 'Please confirm this action using your current password.',
|
||||
@ -51,6 +52,7 @@ return [
|
||||
'api_tokens.revoke_confirm' => 'Do you really want to revoke this token? This step cannot be undone and the token cannot be recovered.',
|
||||
'api_tokens.revoke_successful' => 'The token was revoked successfully.',
|
||||
|
||||
'sso_provider_disabled' => 'The selected SSO provider is not available. Please choose another one.',
|
||||
'sso_wrong_provider' => 'Unable to login with :currentProvider. Please use :userProvider to login, or contact your administrator for help.',
|
||||
|
||||
'sso' => [
|
||||
|
@ -8,10 +8,10 @@
|
||||
<div class="alert alert-info small">@lang('linkace.demo_login_hint')</div>
|
||||
@endif
|
||||
@include('partials.alerts')
|
||||
@if(config('auth.oauth.regular_login_disabled') !== true)
|
||||
@if(config('auth.sso.regular_login_disabled') !== true)
|
||||
@include('auth.login-form')
|
||||
@endif
|
||||
@if(config('auth.oauth.enabled') === true)
|
||||
@if(config('auth.sso.enabled') === true)
|
||||
@include('auth.oauth')
|
||||
@endif
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<div class="card {{ config('auth.oauth.regular_login_disabled') ? '' : 'mt-4' }}">
|
||||
<div class="card {{ config('auth.sso.regular_login_disabled') ? '' : 'mt-4' }}">
|
||||
<div class="card-body">
|
||||
<h2 class="h6">@lang('linkace.login_with')</h2>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
@foreach(config('auth.oauth.providers') as $provider)
|
||||
@foreach(config('auth.sso.providers') as $provider)
|
||||
@if(config('services.'.$provider.'.enabled') === true)
|
||||
<a href="{{ route('auth.oauth.redirect', ['provider' => $provider]) }}" class="btn btn-outline-primary">
|
||||
<a href="{{ route('auth.sso.redirect', ['provider' => $provider]) }}" class="btn btn-outline-primary">
|
||||
<x-dynamic-component :component="'icon.brand.'.$provider" class="me-1"/> @lang('auth.sso.'.$provider)
|
||||
</a>
|
||||
@endif
|
||||
|
@ -71,8 +71,8 @@ Route::get('auth/accept-invite', [RegistrationController::class, 'acceptInvitati
|
||||
Route::post('auth/register', [RegistrationController::class, 'register'])
|
||||
->name('auth.register');
|
||||
|
||||
Route::get('/auth/oauth/{provider}/redirect', [SocialiteController::class, 'redirect'])->name('auth.oauth.redirect');
|
||||
Route::any('/auth/oauth/{provider}/callback', [SocialiteController::class, 'callback'])->name('auth.oauth.callback');
|
||||
Route::get('/auth/sso/{provider}/redirect', [SocialiteController::class, 'redirect'])->name('auth.sso.redirect');
|
||||
Route::any('/auth/sso/{provider}/callback', [SocialiteController::class, 'callback'])->name('auth.sso.callback');
|
||||
|
||||
Route::group(['middleware' => 'auth:sanctum'], function () {
|
||||
Route::get('links/feed', [FeedController::class, 'links'])->name('links.feed');
|
||||
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use PHPUnit\Runner\AfterLastTestHook;
|
||||
use PHPUnit\Runner\BeforeFirstTestHook;
|
||||
|
||||
class Bootstrap implements BeforeFirstTestHook, AfterLastTestHook
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bootstrap The Test Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify console commands that execute once before your test is
|
||||
| run. You are free to add your own additional commands or logic into
|
||||
| this file as needed in order to help your test suite run quicker.
|
||||
|
|
||||
*/
|
||||
|
||||
use CreatesApplication;
|
||||
|
||||
public function executeBeforeFirstTest(): void
|
||||
{
|
||||
$console = $this->createApplication()->make(Kernel::class);
|
||||
|
||||
$commands = [
|
||||
'config:cache',
|
||||
'event:cache',
|
||||
];
|
||||
|
||||
foreach ($commands as $command) {
|
||||
$console->call($command);
|
||||
}
|
||||
}
|
||||
|
||||
public function executeAfterLastTest(): void
|
||||
{
|
||||
array_map('unlink', glob('bootstrap/cache/*.phpunit.php'));
|
||||
}
|
||||
}
|
162
tests/Controller/SocialiteControllerTest.php
Normal file
162
tests/Controller/SocialiteControllerTest.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Controller;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Laravel\Socialite\SocialiteServiceProvider;
|
||||
use Laravel\Socialite\Two\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SocialiteControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function testRedirect(): void
|
||||
{
|
||||
$this->app->register(SocialiteServiceProvider::class);
|
||||
Socialite::shouldReceive('driver->redirect')->once()->andReturn(redirect()->to('https://sso-provider.com/auth'));
|
||||
|
||||
// SSO disabled
|
||||
config()->set('auth.sso.enabled', false);
|
||||
$this->get('auth/sso/auth0/redirect')->assertStatus(403)->assertSee('Login unauthorized');
|
||||
|
||||
// SSO enabled but wrong provider
|
||||
config()->set('auth.sso.enabled', true);
|
||||
$this->get('auth/sso/hello/redirect')->assertStatus(403)->assertSee('Login unauthorized');
|
||||
|
||||
// SSO enabled but disabled provider
|
||||
$this->get('auth/sso/auth0/redirect')->assertStatus(403)->assertSee('The selected SSO provider is not available.');
|
||||
|
||||
// SSO and corresponding driver enabled
|
||||
config()->set('services.auth0.enabled', true);
|
||||
$this->get('auth/sso/auth0/redirect')->assertRedirect('https://sso-provider.com/auth');
|
||||
}
|
||||
|
||||
public function testRegularSsoLogin(): void
|
||||
{
|
||||
$ssoUser = new User();
|
||||
$ssoUser->setToken('XF3hkrEeyYkLnTf1fKX');
|
||||
$ssoUser->map([
|
||||
'id' => 'sso-user-sub-123',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'name' => 'SSO User',
|
||||
'nickname' => 'SSOUser',
|
||||
'given_name' => 'SSO',
|
||||
'family_name' => 'User',
|
||||
]);
|
||||
|
||||
$this->app->register(SocialiteServiceProvider::class);
|
||||
Socialite::shouldReceive('driver->user')->once()->andReturn($ssoUser);
|
||||
|
||||
config()->set('auth.sso.enabled', true);
|
||||
config()->set('services.auth0.enabled', true);
|
||||
|
||||
$this->get('auth/sso/auth0/callback')->assertRedirect('dashboard');
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'name' => 'SSOUser',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'sso_id' => 'sso-user-sub-123',
|
||||
'sso_token' => 'XF3hkrEeyYkLnTf1fKX',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testLoginWithExistingSsoUser(): void
|
||||
{
|
||||
$ssoUser = new User();
|
||||
$ssoUser->setToken('XF3hkrEeyYkLnTf1fKX');
|
||||
$ssoUser->map([
|
||||
'id' => 'sso-user-sub-123',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'name' => 'SSO User',
|
||||
'nickname' => 'SSOUser',
|
||||
'given_name' => 'SSO',
|
||||
'family_name' => 'User',
|
||||
]);
|
||||
|
||||
\App\Models\User::factory()->create([
|
||||
'name' => 'MrPurpleHat',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'sso_id' => 'sso-user-sub-123',
|
||||
]);
|
||||
|
||||
$this->app->register(SocialiteServiceProvider::class);
|
||||
Socialite::shouldReceive('driver->user')->once()->andReturn($ssoUser);
|
||||
|
||||
config()->set('auth.sso.enabled', true);
|
||||
config()->set('services.auth0.enabled', true);
|
||||
|
||||
$this->get('auth/sso/auth0/callback')->assertRedirect('dashboard');
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'name' => 'SSOUser',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'sso_id' => 'sso-user-sub-123',
|
||||
'sso_token' => 'XF3hkrEeyYkLnTf1fKX',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testLoginWithExistingSsoUserWrongProvider(): void
|
||||
{
|
||||
$ssoUser = new User();
|
||||
$ssoUser->setToken('XF3hkrEeyYkLnTf1fKX');
|
||||
$ssoUser->map([
|
||||
'id' => 'sso-user-sub-123',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'name' => 'SSO User',
|
||||
'nickname' => 'SSOUser',
|
||||
'given_name' => 'SSO',
|
||||
'family_name' => 'User',
|
||||
]);
|
||||
|
||||
\App\Models\User::factory()->create([
|
||||
'name' => 'MrPurpleHat',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'sso_id' => 'oidc123456',
|
||||
'sso_provider' => 'oidc',
|
||||
]);
|
||||
|
||||
$this->app->register(SocialiteServiceProvider::class);
|
||||
Socialite::shouldReceive('driver->user')->once()->andReturn($ssoUser);
|
||||
|
||||
config()->set('auth.sso.enabled', true);
|
||||
config()->set('services.auth0.enabled', true);
|
||||
|
||||
$this->get('auth/sso/auth0/callback')->assertStatus(403)->assertSee('Unable to login with Auth0. Please use OIDC to login');
|
||||
}
|
||||
|
||||
public function testLoginWithExistingEmail(): void
|
||||
{
|
||||
$ssoUser = new User();
|
||||
$ssoUser->setToken('XF3hkrEeyYkLnTf1fKX');
|
||||
$ssoUser->map([
|
||||
'id' => 'sso-user-sub-123',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'name' => 'SSO User',
|
||||
'nickname' => 'SSOUser',
|
||||
'given_name' => 'SSO',
|
||||
'family_name' => 'User',
|
||||
]);
|
||||
|
||||
\App\Models\User::factory()->create([
|
||||
'name' => 'MrPurpleHat',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
]);
|
||||
|
||||
$this->app->register(SocialiteServiceProvider::class);
|
||||
Socialite::shouldReceive('driver->user')->once()->andReturn($ssoUser);
|
||||
|
||||
config()->set('auth.sso.enabled', true);
|
||||
config()->set('services.auth0.enabled', true);
|
||||
|
||||
$this->get('auth/sso/auth0/callback')->assertRedirect('dashboard');
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'name' => 'SSOUser',
|
||||
'email' => 'sso-user@linkace.org',
|
||||
'sso_id' => 'sso-user-sub-123',
|
||||
'sso_token' => 'XF3hkrEeyYkLnTf1fKX',
|
||||
]);
|
||||
}
|
||||
}
|
@ -3,17 +3,16 @@
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
||||
trait CreatesApplication
|
||||
{
|
||||
/**
|
||||
* Creates the application.
|
||||
*
|
||||
* @return \Illuminate\Foundation\Application
|
||||
*/
|
||||
public function createApplication(): \Illuminate\Foundation\Application
|
||||
public function createApplication(): Application
|
||||
{
|
||||
$app = require __DIR__ . '/../bootstrap/app.php';
|
||||
$app = require __DIR__.'/../bootstrap/app.php';
|
||||
|
||||
$app->make(Kernel::class)->bootstrap();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user