conquer / oauth2
The Oauth2 Server extension for the Yii2 framework
Package info
github.com/borodulin/yii2-oauth2-server
Type:yii2-extension
pkg:composer/conquer/oauth2
Requires
- php: ^7.4 || ^8.0
- jakeasmith/http_build_url: >=1.0.1
- yiisoft/yii2: ^2.0.14
Requires (Dev)
- ext-pdo_sqlite: *
- codeception/codeception: ^4.2 || ^5.0
- codeception/module-asserts: ^2.0 || ^3.0
- yiisoft/yii2-coding-standards: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Description
This extension provides simple implementation of Oauth 2.0 specification using Yii2 framework.
Requirements
- PHP 7.4 or 8.x
- Yii 2.0
Installation
Install the extension via Composer:
composer require conquer/oauth2:^1.8
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',
],
],
]
],
Upgrading to 2.0
Version 2.0 fixes several security issues and makes the server follow RFC 6749 / OAuth 2.0 Security BCP more strictly:
- Run the new migration (
yii migrate/up) — it adds PKCE columns tooauth2_authorization_code. redirect_urisent by clients must be exactly equal to a registered URI. Register every callback URI of a client inoauth2_client.redirect_uri, separated by whitespace.- The
authorization_codegrant requiresclient_secret. Public clients (SPA, mobile) must use PKCE instead: sendcode_challenge(+code_challenge_method=S256) to the authorization endpoint andcode_verifierto the token endpoint. - If
oauth2_client.grant_typeis filled, only the listed grant types are allowed for the client. - The implicit grant is disabled by default. Set
'allowImplicit' => trueonAuthorizeFilterif you still need it.
Upgrading to 2.1
- The token endpoint accepts only
POSTrequests with parameters in the body. If some clients still useGET, set'allowGet' => trueonTokenActionuntil they are fixed. - Clients may authenticate with HTTP Basic (
Authorization: Basic base64(client_id:client_secret)).
User consent
AuthorizeFilter finishes the authorization as soon as the user is logged in. If your server serves third-party
clients, show a consent page first: override AuthorizeFilter::afterAction() (or call
finishAuthorization() yourself) only after the user has approved the requested scopes.
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.