Giter Site home page Giter Site logo

yii2-oauth2-server's Introduction

Yii2 OAuth 2.0 Server

Build Status

Description

This extension provides simple implementation of Oauth 2.0 specification using Yii2 framework.

Installation

The preferred way to install this extension is through composer.

To install, either run

$ php composer.phar require conquer/oauth2 "*"

or add

"conquer/oauth2": "*"

to the require section of your composer.json file.

Migrations are available from migrations folder.

To add migrations to your application, edit the console config file to configure a namespaced migration:

'controllerMap' => [
    // ...
    'migrate' => [
        'class' => 'yii\console\controllers\MigrateController',
        'migrationPath' => null,
        'migrationNamespaces' => [
            // ...
            'conquer\oauth2\migrations',
        ],
    ],
],

Then issue the migrate/up command:

yii migrate/up

You also need to specify message translation source for this package:

'components' => [
    'i18n' => [
        'translations' => [
            'conquer/oauth2' => [
                'class' => \yii\i18n\PhpMessageSource::class,
                'basePath' => '@conquer/oauth2/messages',
            ],
        ],
    ]
],

Usage

OAuth 2.0 Authorization usage

namespace app\controllers;

use app\models\LoginForm;

class AuthController extends \yii\web\Controller
{
    public function behaviors()
    {
        return [
            /** 
             * Checks oauth2 credentions and try to perform OAuth2 authorization on logged user.
             * AuthorizeFilter uses session to store incoming oauth2 request, so 
             * you can do additional steps, such as third party oauth authorization (Facebook, Google ...)  
             */
            'oauth2Auth' => [
                'class' => \conquer\oauth2\AuthorizeFilter::className(),
                'only' => ['index'],
            ],
        ];
    }
    public function actions()
    {
        return [
            /**
             * Returns an access token.
             */
            'token' => [
                'class' => \conquer\oauth2\TokenAction::classname(),
            ],
            /**
             * OPTIONAL
             * Third party oauth providers also can be used.
             */
            'back' => [
                'class' => \yii\authclient\AuthAction::className(),
                'successCallback' => [$this, 'successCallback'],
            ],
        ];
    }
    /**
     * Display login form, signup or something else.
     * AuthClients such as Google also may be used
     */
    public function actionIndex()
    {
        $model = new LoginForm();
        if ($model->load(\Yii::$app->request->post()) && $model->login()) {
            if ($this->isOauthRequest) {
                $this->finishAuthorization();
            } else {
                return $this->goBack();
            }
        } else {
            return $this->render('index', [
                'model' => $model,
            ]);
        }
    }
    /**
     * OPTIONAL
     * Third party oauth callback sample
     * @param OAuth2 $client
     */
    public function successCallback($client)
    {
        switch ($client::className()) {
            case GoogleOAuth::className():
                // Do login with automatic signup                
                break;
            ...
            default:
                break;
        }
        /**
         * If user is logged on, redirects to oauth client with success,
         * or redirects error with Access Denied
         */
        if ($this->isOauthRequest) {
            $this->finishAuthorization();
        }
    }
    
}

Api controller sample

class ApiController extends \yii\rest\Controller
{
    public function behaviors()
    {
        return [
            /** 
             * Performs authorization by token
             */
            'tokenAuth' => [
                'class' => \conquer\oauth2\TokenAuth::className(),
            ],
        ];
    }
    /**
     * Returns username and email
     */
    public function actionIndex()
    {
        $user = \Yii::$app->user->identity;
        return [
            'username' => $user->username,
            'email' =>  $user->email,
        ];
    }
}

Sample client config

return [
...
   'components' => [
       'authClientCollection' => [
            'class' => 'yii\authclient\Collection',
            'clients' => [
                'myserver' => [
                    'class' => 'yii\authclient\OAuth2',
                    'clientId' => 'unique client_id',
                    'clientSecret' => 'client_secret',
                    'tokenUrl' => 'http://myserver.local/auth/token',
                    'authUrl' => 'http://myserver.local/auth/index',
                    'apiBaseUrl' => 'http://myserver.local/api',
                ],
            ],
        ],
];

If you want to use Resource Owner Password Credentials Grant, implement \conquer\oauth2\OAuth2IdentityInterface.

use conquer\oauth2\OAuth2IdentityInterface;

class User extends ActiveRecord implements IdentityInterface, OAuth2IdentityInterface
{
    ...
    
    /**
     * Finds user by username
     *
     * @param string $username
     * @return static|null
     */
    public static function findIdentityByUsername($username)
    {
        return static::findOne(['username' => $username]);
    }
    
    /**
     * Validates password
     *
     * @param string $password password to validate
     * @return bool if password provided is valid for current user
     */
    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }
    
    ...
}

Warning

As official documentation says:

Since this access token request utilizes the resource owner's password, the authorization server MUST protect the endpoint against brute force attacks (e.g., using rate-limitation or generating alerts).

It's strongly recommended to rate limits on token endpoint. Fortunately, Yii2 have instruments to do this.

For further information see Yii2 Ratelimiter

License

conquer/oauth2 is released under the MIT License. See the bundled LICENSE for details.

yii2-oauth2-server's People

Contributors

alexeevdv avatar atakajlo avatar borodulin avatar gerysk avatar karakum avatar noam148 avatar

Stargazers

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

Watchers

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

yii2-oauth2-server's Issues

Successful login

Hello, I want to save user ip and some other details after successful login but when I use Yii::$app->user->id I get null. how can I get user id in after action ?

<?php
public function afterAction($action, $result)
{
        $result = parent::afterAction($action, $result);

        if($action->id === 'token') {
            $loginLogModel = new LastLoginLog();
            $loginLogModel->user_id = Yii::$app->user->id;
            $loginLogModel->ip = '127.0.0.1';
            $loginLogModel->user_agent = 'Chrome';
            $loginLogModel->os = 'Android';
            $loginLogModel->created = time();

            if (!$loginLogModel->save()) {
                print_r($loginLogModel->errors);
                die;
            }
        }

        return $result;
}

Thanks.

Google Sign In

Hi, first of all thank you so much for your good library. I implemented your library and every thing is fine.
Now I want to use Google sign in with your OAuth2 library and get access token after successful login by Goggle sign in.

I use Google sign in for my purpose and I verify the generated code by Google_Client library.

How can I get access token after successful login by google sign in ? I don't have any idea about it and in your example I haven't found about it.

My code:

<?php
class AuthController extends Controller
{
   public function actions()
   {
        return [
            /**
             * Returns an access token.
             */
            'token' => [
                'class' => TokenAction::classname(),
            ],
        ];
   }

   public function actionGoogle()
   {
        $data['ok'] = false;

        $post  = Yii::$app->request->getBodyParams();
        $token = $post['token'] ?? null;

        $client  = new Google_Client(['client_id' => Yii::$app->params['googleSignInClientId']]);
        $payload = $client->verifyIdToken($token);

        if ($payload) {
            $clientId          = $payload['aud'];
            $email             = $payload['email'];
            $emailVerified = $payload['email_verified'];
            $userId            = $payload['sub'];
            $name              = $payload['name'];


            // ================
            // I need access token here
            // ================
       }
   }
}

'Invalid or missing response type

exception 'conquer\oauth2\Exception' with message 'Invalid or missing response type' in C:\xampp\htdocs\project_folder\vendor\conquer\oauth2\AuthorizeFilter.php:51

Stack trace:
#0 C:\xampp\htdocs\project_folder\vendor\yiisoft\yii2\base\ActionFilter.php(75): conquer\oauth2\AuthorizeFilter->beforeAction(Object(yii\base\InlineAction))
#1 [internal function]: yii\base\ActionFilter->beforeFilter(Object(yii\base\ActionEvent))

How to use the client/view files?

hello Borodulin,

I configured main-local.php, but shows only a blank page.

http://localhost/oauth

if (!YII_ENV_TEST) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = 'yii\debug\Module';

$config['bootstrap'][] = 'gii';
$config['modules']['gii']['class'] = 'yii\gii\Module';
//Add this into backend/config/main-local.php
$config['modules']['gii']['generators'] = [
    'kartikgii-crud' => ['class' => 'warrence\kartikgii\crud\Generator'],
];

$config['modules']['oauth'] = 'conquer\oauth2\Module';

}

Please tell me how to use it, thank you ...

Is this extension ever tested ?

I tried to use this extension on my Yii application. Each time I do a fix inside the library I got another one. A lot of errors in namespacing. Is this library still under development?
I committed out the authorization type "token" and enabled it.

401 instead of 500 when access_token is invalid

401 exception should be thrown when provided access_token is invalid. This is what RFC gives us: https://tools.ietf.org/html/rfc6750#section-3.1

     The access token provided is expired, revoked, malformed, or
     invalid for other reasons.  The resource SHOULD respond with
     the HTTP 401 (Unauthorized) status code.  The client MAY
     request a new access token and retry the protected resource
     request.

For now just generic exception is thrown

throw new Exception('The access token provided is invalid.', Exception::INVALID_GRANT);

It could be handled and rethrowed again... but it require TokenAuth filter extending. Since it is extension for Yii2 it should throw \yii\web\UnauthorizedHttpException in first place

How to implement scope?

Hi Borodulin,
How to implement scope in client config? I do not see it in the document. Could you explain it for me, such as when scope is "email username .."

TokenAuth is unable to find access token

Hi Experts,

We have migrated from version 1.5.4 to 1.7.1 and found functionality of extracting access_token from request is broken and we started getting error "The access token was not found"

When we debugged the code, we found that error was from AccessTokenExtractor::extract() method and it was not able to find access_token in the request whereas access_token was present in the request. Further digging deeper we found that AccessTokenExtractor does not have the request itself because its constructor is expecting the request as parameter whereas the createObject is not passing the request in to constructor.

in TokenAuth.php file following is the code for creating object of AccessTokenExtractor
$tokenExtractor = Yii::createObject(AccessTokenExtractor::class);

Where as constructor code is
`class AccessTokenExtractor
{
/**
* @var Request
*/
private $_request;

/**
 * AccessTokenExtractor constructor.
 * @param Request $request
 */
public function __construct(Request $request)
{
    $this->_request = $request;
}`

Since request is not passed to constructor so $_request is actually undefined/null. So ofcourse access_token could not be fetched from $_request

After updating code to following, it worked and access_token could be extracted.
$tokenExtractor = Yii::createObject(AccessTokenExtractor::class, [\Yii::$app->request]);

My biggest worry is that what kind of testing is performed on this version, how such a basic test can fail on a release version. Without access_token no request can be sent. So still can not believe such basic level bug. Am I missing something here? We hope some explanation will be provided as with such basic issue in the release version we are loosing confidence to upgrade.

Also please let me know is it possible to use version 1.5.4 with latest Yii2. Since we upgraded Yii2 to latest, we thought to update all components including oauth2 server. If its not tested fully we would like to use stable 1.5.4 version with latest Yii2.

Authorization Basic should be ignored

https://github.com/borodulin/yii2-oauth2-server/blob/master/TokenAuth.php#L108 reads the Authorization header. It will then be used to check how many methods are being used, exactly one is required or an Exception is thrown.

https://github.com/borodulin/yii2-oauth2-server/blob/master/TokenAuth.php#L122 then checks if the Authorization header has Bearer. This check should happen earlier and the header should be ignored if it's not Bearer.

This an issue for me at moment because I was using a password-protected test server. The Authorization Basic header was not intended to authenticate the user but to allow making requests to that server in general. The user authentication token was in GET. I've had to remove password protection from my test server to temporarily fix the issue.

External IDPs

Hi,

We are planning to use this as oAuth server. Wanted to understand if we this can be configured to use against external IDPs? For example, 1 tenant has their users on Okta and another is on auth0. One of the client has their own internal IDP and wants to expose it through SAML. How can we support them? Can you share some sample code?

Any quick help will be highly appreciated.

Thanks!

a problem with content type with a post request

a exception here TokenAuth.php when use POST
if ($request->contentType != 'application/x-www-form-urlencoded') { throw new Exception('The content type for POST requests must be "application/x-www-form-urlencoded"'); }

find contentType is application/x-www-form-urlencoded; charset=UTF-8

client_secret ever used for normal operation?

If I'm reading the code correctly, the client_secret is only used when using the refresh_token grant type. Not when using the authorization_code grant type. Is this correct? Isn't the main difference between implicit and authorization code that the requester supplies a client_secret?

Need How to use DOCS

I am planning to implement oAuth in my project. I downloaded your code but I cant understand the code.Please provide good DOCS for implementing yii2-oauth2-server.

Wrong Scope filled in the response for token request grant_type : "authorization_code"

I believe scope returned should be $authCode->scope instead of $this->scope. Response is returned with null scope whereas Authorization Code table has valid scope

`--- a/vendor/conquer/oauth2/granttypes/Authorization.php
+++ b/vendor/conquer/oauth2/granttypes/Authorization.php
@@ -105,7 +105,7 @@ class Authorization extends BaseModel
'access_token' => $acessToken->access_token,
'expires_in' => $this->accessTokenLifetime,
'token_type' => $this->tokenType,

  •        'scope' => $this->scope,
    
  •        'scope' => $authCode->scope,
           'refresh_token' => $refreshToken->refresh_token,
       ];
    
    }`

All exceptions are 500

All HTTP errors are 500, therefore always triggering internal server error while they should be 4xx series errors

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.