Skip to content

harphield/cakephp-oauth-server

 
 

Repository files navigation

OAuth2 Server for CakePHP 4

Software License Build Status

A plugin for implementing an OAuth2 server in CakePHP 4. Built on top of the PHP League's OAuth2 Server. Currently we support the following grant types: AuthCode, RefreshToken, ClientCredentials.

This repository is a fork of uafrica/oauth-server.

Requirements

  • PHP >= 7.2 with openssl extension
  • CakePHP >= 4.0
  • Database (MySQL, SQLite tested)

Installation

You can install this plugin into your CakePHP application. Your composer.json could be as follows: You need to look at this.

 ... "repositories": [ { "name": "nouris/cakephp-oauth-server", "type": "vcs", "url": "https://github.com/TakoShochou/cakephp-oauth-server" } ], "require": { "nouris/cakephp-oauth-server": "^0.8.6" }, ... 

Then, run the following command:

composer update

Load plugin

(CakePHP >= 4.0.0) Load the plugin by adding the following statement in your project's src/Application.php:

$this->addPlugin('OAuthServer');

Run database migration

The database migrations need to be run.

bin/cake migrations migrate -p OAuthServer

Generating and setup keys

Generating private and public keys (see also https://oauth2.thephpleague.com/installation/):

openssl genrsa -out config/oauth.pem 2048 openssl rsa -in config/oauth.pem -pubout -out config/oauth.pub

Generating encryption key :

vendor/bin/generate-defuse-key (COPY result hash)

Change your app.php, Add OAuthServer configuration :

 'OAuthServer' => [ 'privateKey' => CONFIG . 'oauth.pem', 'publicKey' => CONFIG . 'oauth.pub', 'encryptionKey' => 'def0000060c80a6856e8...', // <- SET encryption key FROM `vendor/bin/generate-defuse-key` ],

NOTICE: private key and encryption key is confidential. Try to set as much as possible with environment variables and not upload to the source code repository.

for Apache HTTP Server + php-fpm or php-cgi

Authorization header is not transparent in Apache HTTP Server with php-fpm. So some settings are needed.

Adding the following statement to webroot/.htaccess:

# Apache HTTP Server 2.4.13 and later and use mod_proxy / mod_proxy_fcgi CGIPassAuth on # Apache HTTP Server 2.4.12 and older SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 

And apply \OAuthServer\Middleware\AuthorizationEnvironmentMiddleware on your application:

class Application extends BaseApplication { public function middleware($middleware) { $middleware ->add(ErrorHandlerMiddleware::class) ->add(AssetMiddleware::class) // ADD THIS: bypass Authorization environment to request header ->add(\OAuthServer\Middleware\AuthorizationEnvironmentMiddleware::class) ->add(RoutingMiddleware::class); return $middleware; } }

It is recommended to insert between AssetMiddleware and RoutingMiddleware.

Configuration

It is assumed that you already have working Form based authentication using the built in CakePHP 4 authentication component. If you do not, please read the authentication chapter and Connecting Scoped Middleware

Set OAuthServer as an authentication adaptor.

use Authentication\AuthenticationService; $service = new AuthenticationService(); // OAuth authenticator $service->loadAuthenticator('OAuthServer.OAuth'); // OAuth identifier $service->loadIdentifier('OAuthServer.OAuth'); 

Change your login method to look as follows:

public function login() { $result = $this->Authentication->getResult(); // If the user is logged in send them away. if ($result->isValid()) { $target = $this->Authentication->getLoginRedirect() ?? '/home'; if ($this->request->getQuery('redir') === 'oauth') { $target = [ 'plugin' => 'OAuthServer', 'controller' => 'OAuth', 'action' => 'authorize', '?' => $this->request->getQueryParams(), ]; } return $this->redirect($target); } if ($this->request->is('post') && !$result->isValid()) { $this->Flash->error('Invalid username or password'); } }

Alternatively, if you are using the Friends Of Cake CRUD plugin, add

'login' => [ 'className' => 'OAuthServer.Login' ]

to your CRUD actions config.

Usage

The base OAuth2 path is example.com/oauth.

In order to add clients and OAuth scopes you need to create a ClientsController and a ScopesController (Which is not part of this plugin)

The simplest way is to make use of the Friends Of Cake CRUD-View plugin.

Install it by running

$ composer require friendsofcake/bootstrap-ui:dev-master $ composer require friendsofcake/crud:dev-master $ composer require friendsofcake/crud-view:dev-master

Then create a ClientsController that looks like:

<?php namespace App\Controller; use Crud\Controller\ControllerTrait; /**  * OauthClients Controller  *  * @property \OAuthServer\Model\Table\OauthClientsTable $Clients  */ class ClientsController extends AppController { use ControllerTrait; public $modelClass = 'OAuthServer.Clients'; /**  * @return void  */ public function initialize() { parent::initialize(); $this->viewClass = 'CrudView\View\CrudView'; $tables = [ 'Clients', 'Scopes' ]; $this->loadComponent('Crud.Crud', [ 'actions' => [ 'index' => [ 'className' => 'Crud.Index', 'scaffold' => [ 'tables' => $tables ] ], 'view' => [ 'className' => 'Crud.View', 'scaffold' => [ 'tables' => $tables ] ], 'edit' => [ 'className' => 'Crud.Edit', 'scaffold' => [ 'tables' => $tables, 'fields' => [ 'name', 'redirect_uri', 'parent_model', 'parent_id' => [ 'label' => 'Parent ID', 'type' => 'text' ] ] ] ], 'add' => [ 'className' => 'Crud.Add', 'scaffold' => [ 'tables' => $tables, 'fields' => [ 'name', 'redirect_uri', 'parent_model', 'parent_id' => [ 'label' => 'Parent ID', 'type' => 'text' ] ] ] ], 'delete' => [ 'className' => 'Crud.Delete', 'scaffold' => [ 'tables' => $tables ] ], ], 'listeners' => [ 'CrudView.View', 'Crud.RelatedModels', 'Crud.Redirect', 'Crud.Api' ], ]); } }

And a ScopesController that looks like:

<?php namespace App\Controller; use Crud\Controller\ControllerTrait; /**  * Scopes Controller  *  * @property \OAuthServer\Model\Table\OauthScopesTable $Scopes  */ class ScopesController extends AppController { use ControllerTrait; public $modelClass = 'OAuthServer.Scopes'; /**  * @return void  */ public function initialize() { parent::initialize(); $this->viewClass = 'CrudView\View\CrudView'; $tables = [ 'Clients', 'Scopes' ]; $this->loadComponent('Crud.Crud', [ 'actions' => [ 'index' => [ 'className' => 'Crud.Index', 'scaffold' => [ 'tables' => $tables ] ], 'view' => [ 'className' => 'Crud.View', 'scaffold' => [ 'tables' => $tables ] ], 'edit' => [ 'className' => 'Crud.Edit', 'scaffold' => [ 'tables' => $tables, 'fields' => [ 'id' => [ 'label' => 'ID', 'type' => 'text' ], 'description', ] ] ], 'add' => [ 'className' => 'Crud.Add', 'scaffold' => [ 'tables' => $tables, 'fields' => [ 'id' => [ 'label' => 'ID', 'type' => 'text' ], 'description', ] ] ], 'delete' => [ 'className' => 'Crud.Delete', 'scaffold' => [ 'tables' => $tables ] ], ], 'listeners' => [ 'CrudView.View', 'Crud.RelatedModels', 'Crud.Redirect', ], ]); } }

Customisation

The OAuth2 Server can be customised, the look for the various pages can be changed by creating templates in Template/Plugin/OAuthServer/OAuth

The server also fires a number of events that can be used to inject values into the process. The current events fired are:

  • OAuthServer.beforeAuthorize - On rendering of the approval page for the user.
  • OAuthServer.afterAuthorize - On the user authorising the client
  • OAuthServer.afterDeny - On the user denying the client

You can customise the OAuth authorise page by creating a overriding template file in src/Template/Plugin/OAuthServer/OAuth/authorize.ctp

Component/Authenticator Options

  • OAuthServer.privateKey

REQUIRED: Set your private key filepath.

The key file should be don't readable other user. (file permission is 400, 440, 600, 640, 660)

  • OAuthServer.publicKey

REQUIRED: Set your public key filepath. That generated from the above private key.

The key file should be don't readable other user. (file permission is 400, 440, 600, 640, 660)

  • OAuthServer.encryptionKey

REQUIRED: Set your encryption key string. That generated from vendor/bin/generate-defuse-key command.

  • OAuthServer.accessTokenTTL

Optional: Set access token TTL. Specify a format that can be interpreted by the DateInterval class.

default: PT1H (1 hour)

  • OAuthServer.refreshTokenTTL

Optional: Set refresh token TTL. Specify a format that can be interpreted by the DateInterval class.

default: P1M (1 month)

  • OAuthServer.authCodeTTL

Optional: Set auth code TTL. Specify a format that can be interpreted by the DateInterval class.

default: PT10M (10 minutes)

  • OAuthServer.supportedGrants

Optional: Set supported grant types. This option can be the following list: AuthCode, RefreshToken, ClientCredentials, Password.

default: ['AuthCode', 'RefreshToken', 'ClientCredentials', 'Password']

  • OAuthServer.passwordAuthenticator

Optional: Set Authenticator that use password grant. Set this if your application uses a non default authenticator.

default: Form

OAuthAuthenticate Options

  • continue

Optional: If set to true, if OAuth authentication fails, not stop processing there. Use this when you want to use only authentication information without requiring login.

default: false

  • fields.username

Optional: Specify the user's primary key field.

default: id

more configuration options see: https://book.cakephp.org/3.0/en/controllers/components/authentication.html#configuring-authentication-handlers

About

OAuth2 Server for CakePHP 4.x

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • PHP 100.0%