Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare to update all #77

Merged
merged 33 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM robsontenorio/laravel


28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/ubuntu
{
"name": "Laravel Keycloak Guard",
"remoteUser": "appuser",
"workspaceFolder": "/var/www/app",
"workspaceMount": "source=${localWorkspaceFolder},target=/var/www/app,type=bind",
"build": {
"dockerfile": "Dockerfile"
},
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"[php]": {
"editor.defaultFormatter": "junstyle.php-cs-fixer",
"editor.formatOnSave": true
},
"php-cs-fixer.executablePath": "/var/www/app/vendor/bin/php-cs-fixer",
"php-cs-fixer.config": "/var/www/app/.php-cs-fixer.php",
"php-cs-fixer.onsave": true
},
"remoteEnv": {
"PHP_CS_FIXER_IGNORE_ENV": "1"
},
"extensions": [
"bmewburn.vscode-intelephense-client",
"junstyle.php-cs-fixer"
]
}
54 changes: 54 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Test package

on: [push, pull_request]

jobs:
build-and-test:
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}
runs-on: ubuntu-latest
strategy:
matrix:
php: [8.0, 8.1]
laravel: [8.*, 9.*]
stability: [prefer-lowest, prefer-stable]
include:
- laravel: 8.*
testbench: 6.*
collision: 5.*
- laravel: 9.*
testbench: 7.*
collision: 6.*
exclude:
- laravel: 8.*
stability: prefer-lowest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.composer/cache/files
key: dependencies-composer-${{ hashFiles('composer.json') }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
# extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nunomaduro/collision:${{ matrix.collision }}" --dev --no-interaction --no-update --ansi
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --ansi

- name: Execute tests
run: composer test:coverage

- name: Upload to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODE_COV_TOKEN }}
files: .coverage/clover.xml
verbose: true
9 changes: 3 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
build
composer.lock
docs
vendor
.php_cs.cache
coverage
.phpunit.result.cache
docker-compose.yml
.php-cs-fixer.cache
.coverage/
.phpunit.result.cache
55 changes: 55 additions & 0 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use PhpCsFixer\Config;
use PhpCsFixer\Finder;

$rules = [
'@PSR12' => true,
'no_unused_imports' => true,
'braces' => true,
'array_indentation' => true,
'whitespace_after_comma_in_array' => true,
'binary_operator_spaces' => true,
'no_extra_blank_lines' => true,
'method_chaining_indentation' => true,
'concat_space' => [
'spacing' => 'none',
],
'ordered_imports' => [
'sort_algorithm' =>
'alpha',
],
'class_attributes_separation' => [
'elements' => [
'method' => 'one',
],
],
'blank_line_before_statement' => [
'statements' => [
'if',
'break',
'continue',
'return',
'throw',
'try'
],
],
];

$finder = Finder::create()
->in([
__DIR__ . '/src',
__DIR__ . '/config',
__DIR__ . '/tests',
])
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true)
;

return (new Config())
->setFinder($finder)
->setRules($rules)
->setRiskyAllowed(true)
->setUsingCache(true);
23 changes: 0 additions & 23 deletions .travis.yml

This file was deleted.

119 changes: 74 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
&nbsp;
<img src="https://img.shields.io/packagist/v/robsontenorio/laravel-keycloak-guard.svg" />
<img src="https://img.shields.io/packagist/dt/robsontenorio/laravel-keycloak-guard.svg" />
<img src="https://codecov.io/gh/robsontenorio/laravel-keycloak-guard/branch/master/graph/badge.svg?token=8ZpDarpss1"/>

</p>

Expand Down Expand Up @@ -80,37 +81,16 @@ For facades, uncomment ```$app->withFacades();``` in your boostrap app file ```b

## Keycloak Guard

The Keycloak Guard configuration can be handled from Laravel `.env` file. ⚠️ Be sure all strings **are trimmed.**

⚠️ When editing `.env` make sure all strings **are trimmed.**

Optionally you can publish the config file.
```bash
# Publish config file

```
php artisan vendor:publish --provider="KeycloakGuard\KeycloakGuardServiceProvider"
```


```php
<?php

return [
'realm_public_key' => env('KEYCLOAK_REALM_PUBLIC_KEY', null),

'load_user_from_database' => env('KEYCLOAK_LOAD_USER_FROM_DATABASE', true),

'user_provider_custom_retrieve_method' => null,

'user_provider_credential' => env('KEYCLOAK_USER_PROVIDER_CREDENTIAL', 'username'),

'token_principal_attribute' => env('KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE', 'preferred_username'),

'append_decoded_token' => env('KEYCLOAK_APPEND_DECODED_TOKEN', false),

'allowed_resources' => env('KEYCLOAK_ALLOWED_RESOURCES', null)
];

```

✔️ **realm_public_key**

*Required.*
Expand Down Expand Up @@ -139,14 +119,16 @@ If using this feature, obviously, values defined for `user_provider_credential`

✔️ **user_provider_credential**

*Required. Default is `username`.*
*Required.
Default is `username`.*


The field from "users" table that contains the user unique identifier (eg. username, email, nickname). This will be confronted against `token_principal_attribute` attribute, while authenticating.

✔️ **token_principal_attribute**

*Required. Default is `preferred_username`.*
*Required.
Default is `preferred_username`.*

The property from JWT token that contains the user identifier.
This will be confronted against `user_provider_credential` attribute, while authenticating.
Expand All @@ -159,10 +141,38 @@ Appends to the authenticated user the full decoded JWT token (`$user->token`). U

✔️ **allowed_resources**

*Required*
*Required*.

Usually you API should handle one *resource_access*. But, if you handle multiples, just use a comma separated list of allowed resources accepted by API. This attribute will be confronted against `resource_access` attribute from JWT token, while authenticating.

✔️ **ignore_resouces_validation**

*Default is `false`*.

Disables entirely resources validation. It will **ignore** *allowed_resources* configuration.

✔️ **leeway**

*Default is `0`*.

You can add a leeway to account for when there is a clock skew times between the signing and verifying servers. If you are facing issues like *"Cannot handle token prior to <DATE>"* try to set it `60` (seconds).

✔️ **input_key**

*Default is `null`.*

By default this package **always** will look at first for a `Bearer` token. Additionally, if this option is eneable it will try to get token from this custom request param.

```php
// keycloak.php
'input_key' => 'api_token'

// If there is no Bearer token on request it will use `api_token` request param
GET $this->get("/foo/secret?api_token=xxxxx")
POST $this->post("/foo/secret", ["api_token" => "xxxxx"])
```


## Laravel Auth

Changes on `config/auth.php`
Expand All @@ -176,8 +186,12 @@ Changes on `config/auth.php`
....

'guards' => [
'api' => [
'driver' => 'keycloak', # <-- Set the API guard driver to "keycloak"
# <!-----
# Make sure your "api" guard looks like this.
# Newer Laravel versions just removed this config block.
# ---->
'api' => [
'driver' => 'keycloak',
'provider' => 'users',
],
],
Expand Down Expand Up @@ -218,30 +232,34 @@ $router->group(['middleware' => 'auth'], function () {

# API

Simple Keycloak Guard implements `Illuminate\Contracts\Auth\Guard`. So, all Laravel default methods will be available. Ex: `Auth::user()` returns the authenticated user.
Simple Keycloak Guard implements `Illuminate\Contracts\Auth\Guard`. So, all Laravel default methods will be available.

### Default methods:
## Default Laravel methods

- check()
- guest()
- user()
- id()
- validate()
- setUser()
- `check()`
- `guest()`
- `user()`
- `id()`
- `validate()`
- `setUser()`


### Keycloak Guard methods:
## Keycloak Guard methods

- token()
`token()`
*Returns full decoded JWT token from authenticated user.*

Ex: `Auth::token()` returns full decoded JWT token from authenticated user
```php
$token = Auth::token() // or Auth::user()->token()
```
<br>

- hasRole('some-resource', 'some-role'): Check if the authenticated user has especific role into a resource.
`hasRole('some-resource', 'some-role')`
*Check if authenticated user has a role on resource_access*

Ex:
Whit this payload:
```php
// Example decoded payload

```
'resource_access' => [
'myapp-backend' => [
'roles' => [
Expand All @@ -257,12 +275,23 @@ Whit this payload:
]
]
```
```
```php
Auth::hasRole('myapp-backend', 'myapp-backend-role1') // true
Auth::hasRole('myapp-frontend', 'myapp-frontend-role1') // true
Auth::hasRole('myapp-backend', 'myapp-frontend-role1') // false
```

# Contribute

You can run this project on VSCODE with Remote Container. Make sure you will use internal VSCODE terminal (inside running container).

```bash
composer install
composer test
composer test:coverage
```


# Contact

Twitter [@robsontenorio](https://twitter.com/robsontenorio)
Loading