Skip to content

Commit

Permalink
Merge pull request #7 from frankperez87/feature/ftp/add-phpstan-and-b…
Browse files Browse the repository at this point in the history
…adges

Add PHPStan and Composer Scripts.
  • Loading branch information
frankperez87 authored Dec 12, 2022
2 parents c80c07c + 9dfd0a4 commit 1d1139c
Show file tree
Hide file tree
Showing 19 changed files with 164 additions and 106 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/fix-php-code-style-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ name: Fix PHP code style issues

on:
push:
branches: [main]
paths:
- "**.php"
pull_request:
branches: [main]
paths:
- "**.php"

Expand All @@ -10,10 +15,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
- uses: actions/checkout@v3

- name: Fix PHP code style issues
uses: aglipanci/[email protected]
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ name: PHPStan

on:
push:
branches: [main]
paths:
- "**.php"
- "phpstan.neon.dist"
pull_request:
branches: [main]
paths:
- "**.php"
- "phpstan.neon.dist"
Expand Down
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
vendor
composer.lock
.idea
.phpunit.result.cache
build
composer.lock
coverage
phpunit.xml
phpstan.neon
testbench.yaml
vendor
node_modules
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Okta SAML SSO for Laravel

This package provide a simple to use implementation for implementing Okta SAML Login to the app. The package assists in receiving the SAML Response and Getting the
[![Latest Version on Packagist](https://img.shields.io/packagist/v/pochocho/okta-saml-sso.svg?style=flat-square)](https://packagist.org/packages/pochocho/okta-saml-sso)
[![GitHub Tests Action Status](https://img.shields.io/github/workflow/status/pochocho/okta-saml-sso/run-tests?label=tests)](https://github.com/pochocho/okta-saml-sso/actions?query=workflow%3Arun-tests+branch%3Amain)
[![GitHub Code Style Action Status](https://img.shields.io/github/workflow/status/pochocho/okta-saml-sso/Fix%20PHP%20code%20style%20issues?label=code%20style)](https://github.com/pochocho/okta-saml-sso/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain)
[![Total Downloads](https://img.shields.io/packagist/dt/pochocho/okta-saml-sso.svg?style=flat-square)](https://packagist.org/packages/pochocho/okta-saml-sso)

This package provide a simple to use implementation for implementing Okta SAML Login to the app. The package assists in receiving the SAML Response and Getting the

# Installation

Expand All @@ -17,7 +21,6 @@ Generate your certificate, if you want to generate a self signed certificate, yo
openssl req -x509 -newkey rsa:2048 -nodes -keyout oktasso.key -out oktasso.crt -days 365
```


# Creating and Configuring Okta App

Create your Okta app, Select SAML 2.0 as the Sign-in Method.
Expand All @@ -30,7 +33,6 @@ in the form the `Single sign on URL` refers to url in your app that Okta will se

On this form you can also set the `Attribute Statements` and map them to profile fields. This package assumes snake_case naming conventions on the attributes (e.g first_name, las_name, email, etc)


## configuration

The following values must be set in hour `.env`
Expand All @@ -47,9 +49,9 @@ php artisan vendor:publish --tag=okta-saml-sso

The package assumes that a cert and key file exist at the root directory of the project, named oktasso.crt and oktasso.key:

- `OKTA_CERTIFICATE_PATH` path to the certificate file
- `OKTA_KEY_PATH` path to the key file
- `OKTA_ATTRIBUTE_STATEMENTS` Comma separated list of attribute statements setup in Okta (default value: `'first_name','last_name','email','groups'`)
- `OKTA_CERTIFICATE_PATH` path to the certificate file
- `OKTA_KEY_PATH` path to the key file
- `OKTA_ATTRIBUTE_STATEMENTS` Comma separated list of attribute statements setup in Okta (default value: `'first_name','last_name','email','groups'`)

If your application does not use the User model for authentication, you can configure the model with the `OKTA_AUTHENTICATABLE_MODEL` key on the env.

Expand All @@ -70,14 +72,11 @@ Register the `SsoAuthenticate` Middleware in the Http Kernel. You can either sub
```php
'auth' => \Pochocho\OktaSamlSso\Http\Middleware\SsoAuthenticate::class,
```

Add the new middleware to your auth protected routes, try loading a proteted route and you should be redirected to the Okta login flow.

## Custom

You can implement your own controller and use the `OktaSaml` class to handle the assertions from the Okta SAML Response. The class provides two methods one for un-encrypted SAML Responses `$oktaSaml->getEntity()` and another for encrypted responses `$oktaSaml->getEncryptedEntity()`.

The OktaSaml Class is bound to the IoC Container and can be resolved through dependency injection or by using `app()->make(Pochocho\OktaSamlSso\OktaSaml::class);`




16 changes: 15 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"Pochocho\\OktaSamlSso\\Tests\\": "tests/"
}
},
"scripts": {
"analyze": "vendor/bin/phpstan analyse",
"test": "vendor/bin/phpunit",
"format": "vendor/bin/pint"
},
"authors": [
{
"name": "pochocho",
Expand All @@ -32,6 +37,15 @@
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"orchestra/testbench": "^7.15"
"orchestra/testbench": "^7.15",
"laravel/pint": "^1.2",
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/extension-installer": "^1.2"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
}
}
}
10 changes: 5 additions & 5 deletions config/okta-saml-sso.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@
'credential_paths' => [
'certificate' => env('OKTA_CERTIFICATE_PATH', base_path('oktasso.crt')),
'key' => env('OKTA_KEY_PATH', base_path('oktasso.key')),
'idp_certificate' => env('OKTA_IDP_KEY_PATH', base_path('idp.cert'))
'idp_certificate' => env('OKTA_IDP_KEY_PATH', base_path('idp.cert')),
],

'single_signon_url' => env('OKTA_SIGNON_URL'),

'authenticatable_model' => env('OKTA_AUTHENTICATABLE_MODEL', "App\Models\User"),

'authenticate_action' => Pochocho\OktaSamlSso\Events\SamlUserAuthenticated\SamlUserAuthenticated::class,
'authenticate_action' => Pochocho\OktaSamlSso\Actions\SamlUserAuthenticated::class,

'login_redirect_route' => env("LOGIN_REDIRECT_ROUTE"),
'login_redirect_route' => env('LOGIN_REDIRECT_ROUTE'),

'webhooks' => [
'enabled' => env('OKTA_WEBHOOK_ENABLED', false),
'route_path' => env('OKTA_WEBHOOK_PATH', '/okta-webhook'),
'authorization' => [
'header' => env('OKTA_WEBHOOK_AUTH_HEADER', 'x-auth-key'),
'secret' => env('OKTA_WEBHOOK_AUTH_SECRET'),
]
]
],
],
];
36 changes: 36 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
parameters:
ignoreErrors:
-
message: "#^Access to an undefined property Pochocho\\\\OktaSamlSso\\\\OktaEntity\\:\\:\\$email\\.$#"
count: 1
path: src/Actions/SamlUserAuthenticated.php

-
message: "#^Access to an undefined property Pochocho\\\\OktaSamlSso\\\\OktaEntity\\:\\:\\$first_name\\.$#"
count: 1
path: src/Actions/SamlUserAuthenticated.php

-
message: "#^Access to an undefined property Pochocho\\\\OktaSamlSso\\\\OktaEntity\\:\\:\\$last_name\\.$#"
count: 1
path: src/Actions/SamlUserAuthenticated.php

-
message: "#^Method Pochocho\\\\OktaSamlSso\\\\Http\\\\Middleware\\\\SsoAuthenticate\\:\\:redirectTo\\(\\) should return string\\|null but return statement is missing\\.$#"
count: 1
path: src/Http/Middleware/SsoAuthenticate.php

-
message: "#^Property Pochocho\\\\OktaSamlSso\\\\OktaSaml\\:\\:\\$config is never read, only written\\.$#"
count: 1
path: src/OktaSaml.php

-
message: "#^Access to an undefined property Illuminate\\\\Contracts\\\\Foundation\\\\Application\\:\\:\\$config\\.$#"
count: 1
path: src/OktaSamlSsoServiceProvider.php

-
message: "#^Access to an undefined property Illuminate\\\\Contracts\\\\Foundation\\\\Application\\:\\:\\$request\\.$#"
count: 1
path: src/OktaSamlSsoServiceProvider.php
10 changes: 10 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
includes:
- phpstan-baseline.neon

parameters:
level: 4
paths:
- src
- config
tmpDir: build/phpstan
checkMissingIterableValueType: false
6 changes: 3 additions & 3 deletions routes/okta-webhooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
config('okta-saml-sso.webhooks.route_path'),
[
OktaWebhookController::class,
'oktaVerification'
'oktaVerification',
]
);

Route::post(
config('okta-saml-sso.webhooks.route_path'),
[
OktaWebhookController::class,
'processWebhook'
'processWebhook',
]
);
);
3 changes: 1 addition & 2 deletions src/Actions/SamlUserAuthenticated.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

namespace Pochocho\OktaSamlSso\Actions;

use App\Models\User;
use Pochocho\OktaSamlSso\OktaEntity;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Pochocho\OktaSamlSso\OktaEntity;

class SamlUserAuthenticated
{
Expand Down
5 changes: 2 additions & 3 deletions src/Events/OktaWebhookReceived.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ class OktaWebhookReceived
* @return void
*/
public function __construct(
public array $eventMeta,
public array $eventMeta,
public array $eventData
)
{
) {
}
}
21 changes: 9 additions & 12 deletions src/Http/Controllers/OktaWebhookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,26 @@
use Pochocho\OktaSamlSso\Events\OktaWebhookReceived;
use Pochocho\OktaSamlSso\Http\Requests\OktaWebhookRequest;

class OktaWebhookController {


public function oktaVerification(OktaWebhookRequest $request){

if($request->hasHeader('x-okta-verification-challenge')){
class OktaWebhookController
{
public function oktaVerification(OktaWebhookRequest $request)
{
if ($request->hasHeader('x-okta-verification-challenge')) {
return response()->json(
[
'verification' => $request->header('x-okta-verification-challenge'),
]
);
}

}

public function processWebhook(OktaWebhookRequest $request){

public function processWebhook(OktaWebhookRequest $request)
{
$eventMeta = $request->except('data');
$eventData = $request->only('data');

if(isset($eventData['data'])){
if (isset($eventData['data'])) {
event(new OktaWebhookReceived($eventMeta, $eventData['data']));
}
}

}
}
3 changes: 2 additions & 1 deletion src/Http/Requests/OktaWebhookRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public function authorize()
return $authCode === config('okta-saml-sso.webhooks.authorization.secret');
}

public function rules(){
public function rules()
{
return [];
}
}
23 changes: 12 additions & 11 deletions src/OktaDeserializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Pochocho\OktaSamlSso;

use DateTime;
use LightSaml\Credential\KeyHelper;
use LightSaml\Credential\X509Certificate;
use LightSaml\Credential\X509Credential;
Expand Down Expand Up @@ -44,10 +43,10 @@ public function deserialize($samlResponse)

$this->validateSignature($this->response->getSignature());

if (!empty($this->credentials)) {
if (! empty($this->credentials)) {
return $this->decryptAssertions();
}

$assertion = $this->response->getFirstAssertion();

$this->validateConditions($assertion->getConditions());
Expand All @@ -62,22 +61,23 @@ private function getPublicKey()
);
}

private function validateSignature(SignatureXmlReader $signature){
private function validateSignature(SignatureXmlReader $signature)
{
try {
$validSignature = $signature->validate($this->getPublicKey());
} catch (LightSamlSecurityException $e) {
abort(400, "Invalid Request");
abort(400, 'Invalid Request');
}

if (!$validSignature) {
abort(400, "Invalid SAML Signature");
if (! $validSignature) {
abort(400, 'Invalid SAML Signature');
}
}

private function validateConditions(Conditions $conditions){
if($conditions->getNotOnOrAfterTimestamp() <= time()){
abort(400, "Expipred Request");
private function validateConditions(Conditions $conditions)
{
if ($conditions->getNotOnOrAfterTimestamp() <= time()) {
abort(400, 'Expipred Request');
}
}

Expand All @@ -86,6 +86,7 @@ private function decryptAssertions()
$decryptDeserializeContext = new DeserializationContext();
/** @var \LightSaml\Model\Assertion\EncryptedAssertionReader $reader */
$reader = $this->response->getFirstEncryptedAssertion();

return $reader->decryptMultiAssertion([$this->credentials], $decryptDeserializeContext);
}
}
Loading

0 comments on commit 1d1139c

Please sign in to comment.