Adam Pippin
3 years ago
10 changed files with 336 additions and 11 deletions
@ -0,0 +1,34 @@ |
|||||
|
# authkit2 |
||||
|
|
||||
|
Drop-in OIDC single-sign-on solution for PHP and Laravel projects. |
||||
|
|
||||
|
## Purpose |
||||
|
|
||||
|
Provide a low-impact way to integrate new and existing Laravel projects with a |
||||
|
single-sign-on solution providing identities for users and software across an |
||||
|
entire ecosystem of projects. |
||||
|
|
||||
|
## Features |
||||
|
|
||||
|
* Drop-in, almost zero-config solution. |
||||
|
* Integrates with existing Laravel user and authentication systems. |
||||
|
* Exposes core functionality in a framework-agnostic way to allow use outside |
||||
|
of Laravel. |
||||
|
|
||||
|
## Getting Started |
||||
|
|
||||
|
These documents generally reference Keycloak as the OpenID Connect (OIDC) |
||||
|
provider, however it should ostensibly work with any provider. |
||||
|
|
||||
|
### Laravel |
||||
|
|
||||
|
* [Installation](docs/LARAVEL_INSTALL.md) |
||||
|
* [Configuration](docs/LARAVEL_CONFIG.md) |
||||
|
* [Usage](docs/LARAVEL_USAGE.md) |
||||
|
|
||||
|
### Other |
||||
|
|
||||
|
* [Installation](docs/OTHER_INSTALL.md) |
||||
|
* [Usage](docs/OTHER_USAGE.md) |
||||
|
|
||||
|
|
@ -0,0 +1,57 @@ |
|||||
|
# authkit2 - Laravel Configuration |
||||
|
|
||||
|
How to configure authkit2 in your Laravel project. |
||||
|
|
||||
|
This requires that you have [installed](LARAVEL_INSTALL.md) authkit2. |
||||
|
|
||||
|
# Credentials |
||||
|
|
||||
|
There are two ways to configure the OIDC client: |
||||
|
|
||||
|
* With a JSON configuration file |
||||
|
* With environment variables |
||||
|
|
||||
|
## JSON Configuration |
||||
|
|
||||
|
In Keycloak, under `Clients -> Your Client -> Installation`, you can select the |
||||
|
"Keycloak OIDC JSON" and receive a configuration file in a format such as: |
||||
|
|
||||
|
```js |
||||
|
{ |
||||
|
"realm": "Test", |
||||
|
"auth-server-url": "http://localhost:8080/auth/", |
||||
|
"ssl-required": "external", |
||||
|
"resource": "test", |
||||
|
"credentials": { |
||||
|
"secret": "a0ee4936-ef77-4e4b-87f3-8b4a2706d53a" |
||||
|
}, |
||||
|
"confidential-port": 0 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
Put this file in your application at `storage/app/auth.json`. You're done! |
||||
|
|
||||
|
## Environment Variables |
||||
|
|
||||
|
* `AUTHKIT_CLIENT_ID`: Client ID (`resource` in the above JSON) |
||||
|
* `AUTHKIT_CLIENT_SECRET`: Client Secret (`credentials.secret` in the above JSON) |
||||
|
* `AUTHKIT_ENDPOINT`: URL to the OIDC provider |
||||
|
|
||||
|
# Customization |
||||
|
|
||||
|
There are several other customizable values that are not initially exposed. If |
||||
|
you want to customize these values, you can publish the default configuration |
||||
|
and customize it. |
||||
|
|
||||
|
To publish the configuration, from your project's folder: |
||||
|
``` |
||||
|
$ php artisan vendor:publish --tag authkit2_config |
||||
|
``` |
||||
|
|
||||
|
You can then edit the configuration at: `config/authkit.php` |
||||
|
|
||||
|
Documentation for those options exists in the comments alongside them. |
||||
|
|
||||
|
# Next Steps |
||||
|
|
||||
|
See [Usage](LARAVEL_USAGE.md). |
@ -0,0 +1,61 @@ |
|||||
|
# authkit2 - Laravel Installation |
||||
|
|
||||
|
How to set up authkit2 in your Laravel project. |
||||
|
|
||||
|
# Install |
||||
|
|
||||
|
Add the authkit2 repository to your composer.json, e.g.,: |
||||
|
|
||||
|
```js |
||||
|
"repositories": [ |
||||
|
{ |
||||
|
"type": "path", |
||||
|
"url": "../path/to/authkit2/repo/" |
||||
|
} |
||||
|
] |
||||
|
``` |
||||
|
|
||||
|
// TODO: Update to VCS for release. |
||||
|
|
||||
|
Then install the package with composer: |
||||
|
|
||||
|
```js |
||||
|
$ composer require cmg/authkit2 |
||||
|
``` |
||||
|
|
||||
|
Laravel will automatically discover and register the appropriate service |
||||
|
providers. |
||||
|
|
||||
|
# Migrations |
||||
|
|
||||
|
There are two sets of migrations: |
||||
|
|
||||
|
* New Project: Removes the `password` and `email_verified_at` columns from the |
||||
|
users table. |
||||
|
* Existing Project: Makes the `password` column nullable. |
||||
|
|
||||
|
Both migrations are based around the default Laravel user table. If your table |
||||
|
is heavily customized, you will need to modify the migrations before running |
||||
|
them. |
||||
|
|
||||
|
## New Project |
||||
|
|
||||
|
In your project folder, run: |
||||
|
|
||||
|
``` |
||||
|
$ php artisan vendor:publish --tag=authkit2_migrate_fresh_project |
||||
|
$ php artisan migrate |
||||
|
``` |
||||
|
|
||||
|
## Existing Project |
||||
|
|
||||
|
In your project folder, run: |
||||
|
|
||||
|
``` |
||||
|
$ php artisan vendor:publish --tag=authkit2_migrate_existing_project |
||||
|
$ php artisan migrate |
||||
|
``` |
||||
|
|
||||
|
# Next Steps |
||||
|
|
||||
|
See [Configuration](LARAVEL_CONFIG.md). |
@ -0,0 +1,113 @@ |
|||||
|
# authkit2 - Laravel Usage |
||||
|
|
||||
|
How to use authkit2 in your Laravel project. |
||||
|
|
||||
|
This requires that you have [installed](LARAVEL_INSTALL.md) and |
||||
|
[configured](LARAVEL_CONFIG.md) authkit2. |
||||
|
|
||||
|
# Basic Usage |
||||
|
|
||||
|
For basic usage in a new application there's nothing more to do. authkit2 |
||||
|
integrates with the default Laravel authentication system and will work out of |
||||
|
the box to sign users in and out of your application. |
||||
|
|
||||
|
You can explicitly trigger a login or logout by redirecting to: |
||||
|
|
||||
|
* `/auth/login` and |
||||
|
* `/auth/logout` |
||||
|
|
||||
|
|
||||
|
# Events |
||||
|
|
||||
|
Your application will be notified of logins, logins, and new users (to your |
||||
|
application) through [Laravel Events](https://laravel.com/docs/master/events). |
||||
|
|
||||
|
* `UserRegistration` |
||||
|
* `UserLogin` |
||||
|
* `UserLogout` |
||||
|
|
||||
|
## UserRegistration |
||||
|
|
||||
|
This event is fired when a user authenticated that has _not_ previously |
||||
|
authenticated through the OIDC provider. The event is passed the fields |
||||
|
returned by the OIDC provider (e.g., email, name). |
||||
|
|
||||
|
If a listener is registered, it is expected to return an instance of your User |
||||
|
model, initialized and saves, that will be tied to the OIDC ID the user has |
||||
|
authenticated with. |
||||
|
|
||||
|
For example, a minimal implementation to recreate the default behaviour would |
||||
|
be: |
||||
|
|
||||
|
```php |
||||
|
public function handle($event) |
||||
|
{ |
||||
|
$user = new \App\Models\User(); |
||||
|
$user->name = $event->fields['name']; |
||||
|
$user->email = $event->fields['email']; |
||||
|
$user->save(); |
||||
|
return $user; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
If you wanted an implementation to help migrate existing users to OIDC users, |
||||
|
something like the following may work: |
||||
|
|
||||
|
```php |
||||
|
public function handle($event) |
||||
|
{ |
||||
|
// Try and load an existing user with the given email address |
||||
|
$user = \App\Models\User::where('email', $event->fields['email'])->first(); |
||||
|
|
||||
|
if (!isset($user)) |
||||
|
{ |
||||
|
// If that user wasn't found, this is an entirely new user |
||||
|
$user = new \App\Models\User(); |
||||
|
$user->name = $event->fields['name']; |
||||
|
$user->email = $event->fields['email']; |
||||
|
$user->save(); |
||||
|
return $user; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// If the user was found, then we can tie them to the OIDC |
||||
|
// user. |
||||
|
$user->name = $event->fields['name']; |
||||
|
$user->email = $event->fields['email']; |
||||
|
// Clear the user's password to prevent non-OIDC logins going |
||||
|
// forward. |
||||
|
$user->password = null; |
||||
|
$user->save(); |
||||
|
return $user; |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## UserLogin |
||||
|
|
||||
|
This event is fired when a user is authenticated (whether an existing user, or |
||||
|
after a UserRegistration event). The event is passed the user model and the |
||||
|
fields returned by the OIDC provider (e.g., email, name). |
||||
|
|
||||
|
If a listener is registered, it is expected to update the user model with any |
||||
|
updated fields returned by the OIDC provider. |
||||
|
|
||||
|
For example, a minimal implementation to recreate the default behaviour would |
||||
|
be: |
||||
|
|
||||
|
```php |
||||
|
public function handle($event) |
||||
|
{ |
||||
|
$user = $event->user; |
||||
|
$user->name = $event->fields['name']; |
||||
|
$user->email = $event->fields['email']; |
||||
|
$user->save(); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## UserLogout |
||||
|
|
||||
|
This event is fired when the user tries to log out of your application. The |
||||
|
event is fired _before_ the user is logged out of the Laravel authentication |
||||
|
system or redirected to the OIDC provider to logout. |
||||
|
|
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace authkit2\Events; |
||||
|
|
||||
|
/** |
||||
|
* Notification for a user along with their info provided by OIDC provider |
||||
|
*/ |
||||
|
class UserInfoEvent extends UserEvent |
||||
|
{ |
||||
|
/** |
||||
|
* Additional fields returned during login |
||||
|
* |
||||
|
* @var mixed |
||||
|
*/ |
||||
|
public $fields; |
||||
|
|
||||
|
/** |
||||
|
* Initialize new event |
||||
|
* |
||||
|
* @param mixed $user |
||||
|
* @param array<string,string> $fields |
||||
|
*/ |
||||
|
public function __construct($user, array $fields) |
||||
|
{ |
||||
|
parent::__construct($user); |
||||
|
$this->fields = $fields; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue