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')); }); } } }