You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.1 KiB

<?php
declare(strict_types=1);
namespace authkit2\Providers;
use Illuminate\Support\ServiceProvider;
use \authkit2\Authkit2;
/**
* Authentication provider to perform setup for authentication processes
*/
class AuthnServiceProvider extends ServiceProvider
{
/**
* Register the additional service providers the authentication process depends on
*
* @return void
*/
public function register(): void
{
$this->app->singleton(\authkit2\Oidc\Flows\ServiceAccountFlow::class, function($app) {
return new \authkit2\Oidc\Flows\ServiceAccountFlow(Authkit2::get_client());
});
$this->app->singleton(\authkit2\Oidc\Flows\UserFlow::class, function($app) {
return new \authkit2\Oidc\Flows\UserFlow(Authkit2::get_client());
});
}
/**
* Initialize and register all authentication resources
*
* @return void
*/
public function boot(): void
{
// register our observer on the user model so we can dynamically add/remove
// the token object + client
$user_model = config('auth.providers.users.model');
$user_model::observe(\authkit2\Observers\UserObserver::class);
// Register all authentication routes
$this->bootRoutes();
// Load keycloak configuration and set in Laravel config()
$this->bootConfig();
}
/**
* Register all authentication routes
* If not already cached, generate and register the URL the SSO service
* should redirect back to.
*
* @return void
*/
protected function bootRoutes(): void
{
// Load routes
\Route::group(config('authkit.authn.routing'), function() {
$this->loadRoutesFrom(__DIR__.'/../../routes/web.php');
});
// Figure out where the route is after booting
if (!config()->has('authkit.authn.openid.redirect_uri'))
{
$this->app->booted(static function() {
// TODO: For some reason route($name) isn't working here. We're
// just looking through the routes manually for now...
foreach (\Route::getRoutes() as $route)
{
if ($route->getName() === 'login.callback')
{
config(['authkit.authn.openid.redirect_uri' => url($route->uri())]);
return;
}
}
throw new \Exception('Route [login.callback] not found');
});
}
}
/**
* Generate any missing config values for keycloak by reading JSON
* auth config
*
* @return void
*/
protected function bootConfig(): void
{
// We check if the values are available because they may have
// previously been generated and cached by Laravel in which case
// we can save some work.
if (!(config()->has('authkit.authn.openid.client_id') &&
config()->has('authkit.authn.openid.client_secret') &&
config()->has('authkit.authn.openid.endpoint')))
{
// Figure out where to load the config from
$disk = config('authkit.authn.config.disk');
$path = config('authkit.authn.config.path');
if (!\Storage::disk($disk)->exists($path))
{
// If it doesn't exist, skip the loading.
$config_json = [];
}
else
{
$config_raw = \Storage::disk($disk)->get($path);
$config_json = json_decode($config_raw, true);
if (!isset($config_json))
{
throw new \Exception("Could not parse authentication configuration at $disk:$path");
}
}
config([
'authkit.authn.openid.client_id' => env('AUTHKIT_CLIENT_ID', $config_json['resource'] ?? null),
'authkit.authn.openid.client_secret' => env('AUTHKIT_CLIENT_SECRET', $config_json['credentials']['secret'] ?? null),
'authkit.authn.openid.endpoint' => env('AUTHKIT_ENDPOINT', isset($config_json['auth-server-url']) && isset($config_json['realm']) ? $config_json['auth-server-url'].'realms/'.$config_json['realm'] : null)
]);
}
// Don't even try and init authkit unless configuration is present, prevents erroring out when
// running a composer require/composer install without credentials present.
if (config('authkit.authn.openid.client_id') != null && config('authkit.authn.openid.client_secret') != null && config('authkit.authn.openid.endpoint') != null)
{
$this->app->booted(function($app) {
Authkit2::configure(config('authkit.authn.openid.client_id'), config('authkit.authn.openid.client_secret'), config('authkit.authn.openid.endpoint'));
});
}
}
}