GithubHelp home page GithubHelp logo

hosannahighertech / yii2-oauth2-server Goto Github PK

View Code? Open in Web Editor NEW
15.0 4.0 14.0 22 KB

Yii2 Wrapper around https://github.com/bshaffer/oauth2-server-php , a fork of Filsh/yii2-oauth2-server

License: MIT License

PHP 100.00%

yii2-oauth2-server's Introduction

Yii2 Oauth2 Server

A wrapper for implementing an OAuth2 Server(https://github.com/bshaffer/oauth2-server-php). This is a fork of https://github.com/Filsh/yii2-oauth2-server. I decided to fork it after a long standing issue of branches not being resolved at original repo. There is no guarantee that the two will remain compartible so check out things to see if there is anything broke while transiting.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist hosannahighertech/yii2-oauth2-server "*"

or add

"hosannahighertech/yii2-oauth2-server": "1.0.*"

to the require section of your composer.json.

To use this extension, simply add the following code in your application configuration:

'bootstrap' => ['oauth2'],
'modules' => [
    'oauth2' => [
        'class' => 'filsh\yii2\oauth2server\Module',
        'tokenParamName' => 'accessToken',
        'tokenAccessLifetime' => 3600 * 24,
        'storageMap' => [
            'user_credentials' => 'common\models\User',
        ],
        'grantTypes' => [
            'user_credentials' => [
                'class' => 'OAuth2\GrantType\UserCredentials',
            ],
            'refresh_token' => [
                'class' => 'OAuth2\GrantType\RefreshToken',
                'always_issue_new_refresh_token' => true
            ]
        ]
    ]
]

Configure User class

common\models\User - user model implementing an interface \OAuth2\Storage\UserCredentialsInterface, so the oauth2 credentials data stored in user table. Make sure you implement:

  1. public function checkUserCredentials($username, $password) which Checks the supplied username and password for validity and returns TRUE if the username and password are valid, and FALSE if it isn't.

  2. public function getUserDetails($username) which returns array of the associated "user_id" and optional "scope" values something like this:

[ 
    "user_id"  => USER_ID,    // REQUIRED user_id to be stored with the authorization code or access token
    "scope"    => SCOPE       // OPTIONAL space-separated list of restricted scopes
] 

Additional OAuth2 Flags:

enforceState - Flag that switch that state controller should allow to use "state" param in the "Authorization Code" Grant Type

allowImplicit - Flag that switch that controller should allow the "implicit" grant type

The next step your shold run migration

 yii migrate --migrationPath=@vendor/hosannahighertech/yii2-oauth2-server/migrations

this migration create the oauth2 database scheme and insert test user credentials testclient:testpass for http://fake/

add url rule to urlManager

'urlManager' => [
    'rules' => [
        'POST oauth2/<action:\w+>' => 'oauth2/rest/<action>',
        ...
    ]
]

Usage

To use this extension, simply add the behaviors for your base controller:

use yii\helpers\ArrayHelper;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
use filsh\yii2\oauth2server\filters\ErrorToExceptionFilter;
use filsh\yii2\oauth2server\filters\auth\CompositeAuth;

class Controller extends \yii\rest\Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return ArrayHelper::merge(parent::behaviors(), [
            'authenticator' => [
                'class' => CompositeAuth::className(),
                'authMethods' => [
                    ['class' => HttpBearerAuth::className()],
                    ['class' => QueryParamAuth::className(), 'tokenParam' => 'accessToken'],
                ]
            ],
            'exceptionFilter' => [
                'class' => ErrorToExceptionFilter::className()
            ],
        ]);
    }
}

Create action authorize in site controller for Authorization Code

https://api.mysite.com/authorize?response_type=code&client_id=TestClient&redirect_uri=https://fake/

/**
 * SiteController
 */
class SiteController extends Controller
{
    /**
     * @return mixed
     */
    public function actionAuthorize()
    {
        if (Yii::$app->getUser()->getIsGuest())
            return $this->redirect('login');
    
        /** @var $module \filsh\yii2\oauth2server\Module */
        $module = Yii::$app->getModule('oauth2');
        $response = $module->handleAuthorizeRequest(!Yii::$app->getUser()->getIsGuest(), Yii::$app->getUser()->getId());
    
        /** @var object $response \OAuth2\Response */
        Yii::$app->getResponse()->format = \yii\web\Response::FORMAT_JSON;
    
        return $response->getParameters();
    }
}

For More on Requests and responses as well as explanations for Oauth Grant types see excellet tutorial by Jenkov here: http://tutorials.jenkov.com/oauth2/

see more

Also if you set allowImplicit => true you can use Implicit Grant Type - see more

Request example:

https://api.mysite.com/authorize?response_type=token&client_id=TestClient&redirect_uri=https://fake/cb

With redirect response:

https://fake/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=bearer&expires_in=3600

JWT Tokens

If you want to get Json Web Token (JWT) instead of convetional token, you will need to set 'useJwtToken' => true in module and then define two more configurations: 'public_key' => 'app\storage\PublicKeyStorage' which is the class that implements PublickKeyInterface and 'access_token' => 'OAuth2\Storage\JwtAccessToken' which implements JwtAccessTokenInterface.php. The Oauth2 base library provides the default access_token which works great. Just use it and everything will be fine.

Here is a sample class for public key implementing PublickKeyInterface. Make sure that paths to private and public keys are correct. You can generate them with OpenSSL tool with two steps (Thanks to (Rietta)[https://rietta.com/blog/2012/01/27/openssl-generating-rsa-key-from-command/]):

  1. openssl genrsa -des3 -out privkey.pem 2048

  2. openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem

Note that you can copy contents of the files and paste the long strings in class variables. It is nasty but it works fine if that is what you want.

<?php
namespace app\security\storage;

class PublicKeyStorage implements \OAuth2\Storage\PublicKeyInterface{


    private $pbk =  null;
    private $pvk =  null; 

    public function __construct()
    {
        $pvkText =  file_get_contents(dirname(__FILE__).'/../keys/privkey.pem');        
        $this->pvk = openssl_get_privatekey($pvkText, 'YOUR_PASSPHRASE_IF_ANY');
        
        $this->pbk =  file_get_contents(dirname(__FILE__).'/../keys/pubkey.pem'); 
    }

    public function getPublicKey($client_id = null){ 
        return  $this->pbk;
    }

    public function getPrivateKey($client_id = null){
        return  $this->pvk;
    }

    public function getEncryptionAlgorithm($client_id = null){
        return "RS256";
    }

}

For more, see https://github.com/bshaffer/oauth2-server-php

yii2-oauth2-server's People

Contributors

meyergru avatar mtangoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

yii2-oauth2-server's Issues

has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Hi, I am building an Api restful using yii2, and I have installed the vendor for managing the oauth2 authentication, but I am having some troubles with the login. When I try it from insomnia everything goes great:
image

But when I try it out from my angular 7 front app, I receive the error:
Access to XMLHttpRequest at 'http://localhost:8080/oauth2/token' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Cross-Origin Read Blocking (CORB) blocked cross-origin response http://localhost:8080/oauth2/token with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.

Even if the post request returns the status code 200, the response is blocked and doesn't show.

This is my behavior function in SiteController:

 public function behaviors()
    {
        $behaviors = parent::behaviors();
        unset($behaviors['authenticator']);
        return [
            'corsFilter' => [
                'class' => \yii\filters\Cors::class,
                'cors' => [
                    // restrict access to
                    'Origin' => ['*'],
               // Allow  methods
                    'Access-Control-Request-Method' => ['POST', 'PUT', 'OPTIONS', 'GET'],
                    // Allow only headers 'X-Wsse'
                    'Access-Control-Request-Headers' => ['*'],
                    'Access-Control-Allow-Headers' => ['Content-Type'],
                    // Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser
                    //'Access-Control-Allow-Credentials' => true,
                    // Allow OPTIONS caching
                    'Access-Control-Max-Age' => 3600,
                    // Allow the X-Pagination-Current-Page header to be exposed to the browser.
                    'Access-Control-Expose-Headers' => ['*'],
                ],
            ],
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['logout'],
                'rules' => [
                    [
                        'actions' => ['logout'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'logout' => ['post'],
                ],
            ],
        ];
    }

Can someone give me a hand with this please

The grant type was not specified in the request

Hello, I have one problem. When I whant to send request on this address http://api.testk0v4.xyz/oauth2/token, I have got Error 400 with code:0 and message:"The grant type was not specified in the request".
The most intresting, that on my local site all work good, but on the VDS I have this problem, and this problem appeared today.
Please, explain what the problem is, thanks.

Performance issues

First of all, thanks. I take your option changing de repo since the previous gave many errors.
Some points:

  1. You say put the config 'public_key' => 'app\storage\PublicKeyStorage', but the class is namespaced with namespace app\security\storage;

Here the thing. I've been doing some performance debug with Google Chrome and noted that token issuance take some long time (compare with other implementations I've made with .NET)

After perform many request at the token endpoint, the minimun take 1.86s and the maximun 2.3s (in .NET this take 200ms aprox).

Then, when I tried to access a protected resource in my api, this also take a long time. My resource endpoint doesn't perform query operations (to discard this variable) in order to isolate the token verification process time.

The time of this was: maximun -> 2.5s, minimun 1.8s

I'll be thankfull if you can light me in the right direction to get better performance. My server is an Ububntu Server. Perphabs if I change the storage modes like pointed in http://bshaffer.github.io/oauth2-server-php-docs/storage/multiple/

I would like a scheman like this:

  1. Users -> PG Database (I have many users)
  2. Scopes, clients -> Memory (I have few scopes and clients)
  3. Tokens -> Memory or other storage no being PG Database. (I couldn't figured out where .NET stored tokens, but it wasn't the MS Server instance used by that api)

Best regards

Jona

expired tokens

I noticed when endpoint is issued with expired token then before action oauth server validates this token in CompositeAuth class. It ignores result from Server::verifyResourceRequest() which causes running actions using expired tokens. After action is performed then afterActio handler ErrorToException is triggered and returns 401 response which is ok.

I think this class ErrorToException should be removed and code from it should be moved to CompositeAuth to verify tokens and throw proper exception before action instead of after action.

When I visit 'oauth2/token', report the following error.

{
    "name": "Exception",
    "message": "Argument 1 passed to OAuth2\\Server::handleTokenRequest() must be an instance of OAuth2\\RequestInterface, instance of yii\\web\\Request given, called in /Users/moment/work/code/work-jy/shop-admin/vendor/filsh/yii2-oauth2-server/Server.php on line 42",
    "code": 0,
    "type": "TypeError",
    "file": "/Users/moment/work/code/work-jy/shop-admin/vendor/bshaffer/oauth2-server-php/src/OAuth2/Server.php",
    "line": 316,
    "stack-trace": [
        "#0 /Users/moment/work/code/work-jy/shop-admin/vendor/filsh/yii2-oauth2-server/Server.php(42): OAuth2\\Server->handleTokenRequest(Object(yii\\web\\Request), NULL)",
        "#1 /Users/moment/work/code/work-jy/shop-admin/vendor/filsh/yii2-oauth2-server/controllers/RestController.php(25): filsh\\yii2\\oauth2server\\Server->handleTokenRequest()",
        "#2 [internal function]: filsh\\yii2\\oauth2server\\controllers\\RestController->actionToken()",
        "#3 /Users/moment/work/code/work-jy/shop-admin/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)",
        "#4 /Users/moment/work/code/work-jy/shop-admin/vendor/yiisoft/yii2/base/Controller.php(157): yii\\base\\InlineAction->runWithParams(Array)",
        "#5 /Users/moment/work/code/work-jy/shop-admin/vendor/yiisoft/yii2/base/Module.php(528): yii\\base\\Controller->runAction('token', Array)",
        "#6 /Users/moment/work/code/work-jy/shop-admin/vendor/yiisoft/yii2/web/Application.php(103): yii\\base\\Module->runAction('oauth2/rest/tok...', Array)",
        "#7 /Users/moment/work/code/work-jy/shop-admin/vendor/yiisoft/yii2/base/Application.php(386): yii\\web\\Application->handleRequest(Object(yii\\web\\Request))",
        "#8 /Users/moment/work/code/work-jy/shop-admin/api/web/index.php(17): yii\\base\\Application->run()",
        "#9 {main}"
    ]
}
    public function handleTokenRequest(\OAuth2\RequestInterface $request = null, \OAuth2\ResponseInterface $response = null)
    {
        if($request === null) {
            $request = $this->module->getRequest();
        }
        return parent::handleTokenRequest($request, $response);
    }

An Error occurred while handling another error

Hi, I just installed the repo, following the steps in https://www.yiiframework.com/extension/hosannahighertech/yii2-oauth2-server. I am trying to make a request to a controller which use the authorization behavior described in the site, and when I passed the header Authorization with the valid access_token, everything goes great. But if I try to make the request without the header, instead of receiving the correct 401 response, I receive the following:

yii\base\UnknownPropertyException: Getting unknown property: app\models\User::username in D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Component.php:154
Stack trace:
#0 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\db\BaseActiveRecord.php(298): yii\base\Component->__get('username')
#1 D:\work\Back Projects\G-AppBack\views\layouts\main.php(50): yii\db\BaseActiveRecord->__get('username')
#2 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\View.php(348): require('D:\work\Back Pr...')
#3 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\View.php(257): yii\base\View->renderPhpFile('D:\work\Back Pr...', Array)
#4 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Controller.php(399): yii\base\View->renderFile('D:\work\Back Pr...', Array, Object(app\controllers\SiteController))
#5 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Controller.php(385): yii\base\Controller->renderContent('<div class="sit...')
#6 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\web\ErrorAction.php(139): yii\base\Controller->render('error', Array)
#7 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\web\ErrorAction.php(118): yii\web\ErrorAction->renderHtmlResponse()
#8 [internal function]: yii\web\ErrorAction->run()
#9 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Action.php(94): call_user_func_array(Array, Array)
#10 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Controller.php(157): yii\base\Action->runWithParams(Array)
#11 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Module.php(528): yii\base\Controller->runAction('error', Array)
#12 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\web\ErrorHandler.php(108): yii\base\Module->runAction('site/error')
#13 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\web\UnauthorizedHttpException))
#14 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\web\UnauthorizedHttpException))
#15 {main}
Previous exception:
yii\web\UnauthorizedHttpException: Your request was made with invalid credentials. in D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\filters\auth\AuthMethod.php:93
Stack trace:
#0 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\filters\auth\AuthMethod.php(76): yii\filters\auth\AuthMethod->handleFailure(Object(yii\web\Response))
#1 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\filters\auth\CompositeAuth.php(57): yii\filters\auth\AuthMethod->beforeAction(Object(yii\base\InlineAction))
#2 D:\work\Back Projects\G-AppBack\vendor\hosannahighertech\yii2-oauth2-server\filters\auth\CompositeAuth.php(17): yii\filters\auth\CompositeAuth->beforeAction(Object(yii\base\InlineAction))
#3 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\ActionFilter.php(77): filsh\yii2\oauth2server\filters\auth\CompositeAuth->beforeAction(Object(yii\base\InlineAction))
#4 [internal function]: yii\base\ActionFilter->beforeFilter(Object(yii\base\ActionEvent))
#5 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Component.php(627): call_user_func(Array, Object(yii\base\ActionEvent))
#6 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Controller.php(274): yii\base\Component->trigger('beforeAction', Object(yii\base\ActionEvent))
#7 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\web\Controller.php(164): yii\base\Controller->beforeAction(Object(yii\base\InlineAction))
#8 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Controller.php(155): yii\web\Controller->beforeAction(Object(yii\base\InlineAction))
#9 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Module.php(528): yii\base\Controller->runAction('index', Array)
#10 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\web\Application.php(103): yii\base\Module->runAction('user/index', Array)
#11 D:\work\Back Projects\G-AppBack\vendor\yiisoft\yii2\base\Application.php(386): yii\web\Application->handleRequest(Object(yii\web\Request))
#12 D:\work\Back Projects\G-AppBack\web\index.php(12): yii\base\Application->run()
#13 {main}

Can someone help me with this please, I would like to receive the correct error response, I don't know if I am misssing something here

I did what the documentation said, but I ran into this problem

TypeError
Argument 1 passed to filsh\yii2\oauth2server\Server::handleAuthorizeRequest() must be an instance of OAuth2\RequestInterface or null, boolean given, called in E:\www\wwwroot\passport2.sh-helpdesk.com\frontend\controllers\SiteController.php on line 71

Yii2 2.0.13 needs changes to the Module

I had a problem when using a construct like this after the upgrade to Yii2 2.0.13:

` $module = Yii::$app->getModule('oauth2');
$response = $module->getResponse();
$request = $module->getRequest();

	if (!$module->getServer()->validateAuthorizeRequest($request, $response)) {
		Yii::$app->getResponse()->format = \yii\web\Response::FORMAT_JSON;
		return $response->getParameters();
	}

`

The validateAuthorizeRequest does no longer work, because $request is an instance of the wrong type.

It appears, that in Module.php, there is a test:

public function getServer() { if(!$this->has('server')) { $storages = [];

Which should now read:

public function getServer() { if(!$this->has('server', true)) { $storages = [];

This is because the Module/ServiceLocator->has() method searches upwards per default from Yii2 2.0.13 on, which can be avoided by checkInstance = true as the second parameter.

I think that the same change should be applied to the has() call in getRequest() and getRepsonse() - and also, the member names should be changed from 'server', 'request', 'response' to 'oauth2server', 'oauth2request' and 'oauth2response' in order to discriminate them from other name spaces.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.