├── LICENSE ├── README.md ├── migrations └── m150614_112046_oauth.php └── oauth ├── AccessTokenStorage.php ├── AuthCodeStorage.php ├── ClientStorage.php ├── RefreshTokenStorage.php ├── ScopeStorage.php └── SessionStorage.php /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Alexander Makarov 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of yii2-league-oauth2-server nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yii2-league-oauth2-server 2 | Yii 2.0 implementation of PHP league OAuth2 server interfaces 3 | -------------------------------------------------------------------------------- /migrations/m150614_112046_oauth.php: -------------------------------------------------------------------------------- 1 | createTable('oauth_client', [ 13 | 'id' => Schema::TYPE_STRING . ' PRIMARY KEY', 14 | 'secret' => Schema::TYPE_STRING . ' NOT NULL', 15 | 'name' => Schema::TYPE_STRING . ' NOT NULL', 16 | ], $this->tableOptions); 17 | 18 | $this->createTable('oauth_client_redirect_uri', [ 19 | 'id' => Schema::TYPE_PK, 20 | 'client_id' => Schema::TYPE_STRING . ' NOT NULL', 21 | 'redirect_uri' => Schema::TYPE_STRING . ' NOT NULL', 22 | ], $this->tableOptions); 23 | 24 | $this->addForeignKey('fk-oauth_client_redirect_uri-client_id', 'oauth_client_redirect_uri', 'client_id', 'oauth_client', 'id', 'CASCADE'); 25 | 26 | $this->createTable('oauth_scope', [ 27 | 'id' => Schema::TYPE_STRING . ' PRIMARY KEY', 28 | 'description' => Schema::TYPE_STRING . ' NOT NULL', 29 | ], $this->tableOptions); 30 | 31 | $this->db->schema->refresh(); 32 | 33 | $this->insert('oauth_scope', [ 34 | 'id' => 'basic', 35 | 'description' => 'Basic details about your account', 36 | ]); 37 | 38 | $this->insert('oauth_scope', [ 39 | 'id' => 'email', 40 | 'description' => 'Your email address', 41 | ]); 42 | 43 | $this->insert('oauth_scope', [ 44 | 'id' => 'photo', 45 | 'description' => 'Your photo', 46 | ]); 47 | 48 | 49 | $this->createTable('oauth_session', [ 50 | 'id' => Schema::TYPE_BIGPK, 51 | 'owner_type' => Schema::TYPE_STRING . ' NOT NULL', 52 | 'owner_id' => Schema::TYPE_STRING . ' NOT NULL', 53 | 'client_id' => Schema::TYPE_STRING . ' NOT NULL', 54 | 'client_redirect_uri' => Schema::TYPE_STRING, 55 | ], $this->tableOptions); 56 | 57 | $this->addForeignKey('fk-oauth_session-client_id', 'oauth_session', 'client_id', 'oauth_client', 'id', 'CASCADE'); 58 | 59 | $this->createTable('oauth_access_token', [ 60 | 'access_token' => Schema::TYPE_STRING . ' PRIMARY KEY', 61 | 'session_id' => Schema::TYPE_BIGINT . ' NOT NULL', 62 | 'expire_time' => Schema::TYPE_INTEGER . ' NOT NULL', 63 | ], $this->tableOptions); 64 | 65 | $this->addForeignKey('fk-oauth_access_token-session_id', 'oauth_access_token', 'session_id', 'oauth_session', 'id', 'CASCADE'); 66 | 67 | 68 | $this->createTable('oauth_refresh_token', [ 69 | 'refresh_token' => Schema::TYPE_STRING . ' PRIMARY KEY', 70 | 'expire_time' => Schema::TYPE_INTEGER . ' NOT NULL', 71 | 'access_token' => Schema::TYPE_STRING . ' NOT NULL', 72 | ], $this->tableOptions); 73 | $this->addForeignKey('fk-oauth_refresh_token-access_token', 'oauth_refresh_token', 'access_token', 'oauth_access_token', 'access_token', 'CASCADE'); 74 | 75 | 76 | $this->createTable('oauth_auth_code', [ 77 | 'auth_code' => Schema::TYPE_STRING . ' PRIMARY KEY', 78 | 'session_id' => Schema::TYPE_BIGINT . ' NOT NULL', 79 | 'expire_time' => Schema::TYPE_INTEGER . ' NOT NULL', 80 | 'client_redirect_uri' => Schema::TYPE_STRING . ' NOT NULL', 81 | ], $this->tableOptions); 82 | 83 | $this->addForeignKey('fk-oauth_auth_code-session_id', 'oauth_auth_code', 'session_id', 'oauth_session', 'id', 'CASCADE'); 84 | 85 | $this->createTable('oauth_access_token_scope', [ 86 | 'id' => Schema::TYPE_BIGPK, 87 | 'access_token' => Schema::TYPE_STRING . ' NOT NULL', 88 | 'scope' => Schema::TYPE_STRING . ' NOT NULL', 89 | ], $this->tableOptions); 90 | 91 | $this->addForeignKey('fk-oauth_access_token_scope-access_token', 'oauth_access_token_scope', 'access_token', 'oauth_access_token', 'access_token', 'CASCADE'); 92 | $this->addForeignKey('fk-oauth_access_token_scope-scope', 'oauth_access_token_scope', 'scope', 'oauth_scope', 'id', 'CASCADE'); 93 | 94 | $this->createTable('oauth_auth_code_scope', [ 95 | 'id' => Schema::TYPE_PK, 96 | 'auth_code' => Schema::TYPE_STRING . ' NOT NULL', 97 | 'scope' => Schema::TYPE_STRING . ' NOT NULL', 98 | ], $this->tableOptions); 99 | 100 | $this->addForeignKey('fk-oauth_auth_code_scope-auth_code', 'oauth_auth_code_scope', 'auth_code', 'oauth_auth_code', 'auth_code', 'CASCADE'); 101 | $this->addForeignKey('fk-oauth_auth_code_scope-scope', 'oauth_auth_code_scope', 'scope', 'oauth_scope', 'id', 'CASCADE'); 102 | 103 | $this->createTable('oauth_session_scope', [ 104 | 'id' => Schema::TYPE_BIGPK, 105 | 'session_id' => Schema::TYPE_BIGINT . ' NOT NULL', 106 | 'scope' => Schema::TYPE_STRING . ' NOT NULL', 107 | ], $this->tableOptions); 108 | 109 | $this->addForeignKey('fk-oauth_session_scope-session_id', 'oauth_session_scope', 'session_id', 'oauth_session', 'id', 'CASCADE'); 110 | $this->addForeignKey('fk-oauth_session_scope-scope', 'oauth_session_scope', 'scope', 'oauth_scope', 'id', 'CASCADE'); 111 | } 112 | 113 | public function down() 114 | { 115 | $this->dropTable('oauth_session_scope'); 116 | $this->dropTable('oauth_auth_code_scope'); 117 | $this->dropTable('oauth_access_token_scope'); 118 | $this->dropTable('oauth_auth_code'); 119 | $this->dropTable('oauth_refresh_token'); 120 | $this->dropTable('oauth_access_token'); 121 | $this->dropTable('oauth_session'); 122 | $this->dropTable('oauth_scope'); 123 | $this->dropTable('oauth_client_redirect_uri'); 124 | $this->dropTable('oauth_client'); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /oauth/AccessTokenStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_access_token') 20 | ->where(['access_token' => $token]) 21 | ->all(); 22 | 23 | if (count($result) === 1) { 24 | $token = (new AccessTokenEntity($this->server)) 25 | ->setId($result[0]['access_token']) 26 | ->setExpireTime($result[0]['expire_time']); 27 | 28 | return $token; 29 | } 30 | 31 | return; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function getScopes(AccessTokenEntity $token) 38 | { 39 | $result = (new Query()) 40 | ->from('oauth_access_token_scope') 41 | ->select(['oauth_scope.id', 'oauth_scope.description']) 42 | ->leftJoin('oauth_scope', 'oauth_access_token_scope.scope = oauth_scope.id') 43 | ->where('access_token', $token->getId()) 44 | ->all(); 45 | 46 | $response = []; 47 | 48 | if (count($result) > 0) { 49 | foreach ($result as $row) { 50 | $scope = (new ScopeEntity($this->server))->hydrate([ 51 | 'id' => $row['id'], 52 | 'description' => $row['description'], 53 | ]); 54 | $response[] = $scope; 55 | } 56 | } 57 | 58 | return $response; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function create($token, $expireTime, $sessionId) 65 | { 66 | \Yii::$app->db->createCommand()->insert('oauth_access_token', [ 67 | 'access_token' => $token, 68 | 'session_id' => $sessionId, 69 | 'expire_time' => $expireTime, 70 | ])->execute(); 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | public function associateScope(AccessTokenEntity $token, ScopeEntity $scope) 77 | { 78 | \Yii::$app->db->createCommand()->insert('oauth_access_token_scope', [ 79 | 'access_token' => $token->getId(), 80 | 'scope' => $scope->getId(), 81 | ])->execute(); 82 | } 83 | 84 | /** 85 | * {@inheritdoc} 86 | */ 87 | public function delete(AccessTokenEntity $token) 88 | { 89 | \Yii::$app->db->createCommand() 90 | ->delete('oauth_access_token', ['access_token' => $token->getId()]) 91 | ->execute(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /oauth/AuthCodeStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_auth_code') 20 | ->where(['auth_code' => $code]) 21 | ->andWhere('expire_time >= ' . time()) 22 | ->all(); 23 | 24 | if (count($result) === 1) { 25 | $token = new AuthCodeEntity($this->server); 26 | $token->setId($result[0]['auth_code']); 27 | $token->setRedirectUri($result[0]['client_redirect_uri']); 28 | $token->setExpireTime($result[0]['expire_time']); 29 | 30 | return $token; 31 | } 32 | 33 | return; 34 | } 35 | 36 | public function create($token, $expireTime, $sessionId, $redirectUri) 37 | { 38 | \Yii::$app->db->createCommand()->insert('oauth_auth_code', [ 39 | 'auth_code' => $token, 40 | 'client_redirect_uri' => $redirectUri, 41 | 'session_id' => $sessionId, 42 | 'expire_time' => $expireTime, 43 | ])->execute(); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getScopes(AuthCodeEntity $token) 50 | { 51 | $result = (new Query()) 52 | ->from('oauth_auth_code_scope') 53 | ->select(['oauth_scope.id', 'oauth_scope.description']) 54 | ->leftJoin('oauth_scope', 'oauth_auth_code_scope.scope = oauth_scope.id') 55 | ->where(['auth_code' => $token->getId()]) 56 | ->all(); 57 | 58 | $response = []; 59 | 60 | if (count($result) > 0) { 61 | foreach ($result as $row) { 62 | $scope = (new ScopeEntity($this->server))->hydrate([ 63 | 'id' => $row['id'], 64 | 'description' => $row['description'], 65 | ]); 66 | $response[] = $scope; 67 | } 68 | } 69 | 70 | return $response; 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | public function associateScope(AuthCodeEntity $token, ScopeEntity $scope) 77 | { 78 | \Yii::$app->db->createCommand()->insert('oauth_auth_code_scope', [ 79 | 'auth_code' => $token->getId(), 80 | 'scope' => $scope->getId(), 81 | ])->execute(); 82 | } 83 | 84 | /** 85 | * {@inheritdoc} 86 | */ 87 | public function delete(AuthCodeEntity $token) 88 | { 89 | \Yii::$app->db->createCommand()->delete('oauth_auth_code', ['auth_code' => $token->getId()])->execute(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /oauth/ClientStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_client') 20 | ->select('oauth_client.*') 21 | ->where(['oauth_client.id' => $clientId]); 22 | 23 | 24 | if ($clientSecret !== null) { 25 | $query->andWhere(['oauth_client.secret' => $clientSecret]); 26 | } 27 | 28 | if ($redirectUri) { 29 | $query->leftJoin('oauth_client_redirect_uri', 'oauth_client.id = oauth_client_redirect_uri.client_id') 30 | ->addSelect(['oauth_client.*', 'oauth_client_redirect_uri.*']) 31 | ->andWhere(['oauth_client_redirect_uri.redirect_uri' => $redirectUri]); 32 | } 33 | 34 | $result = $query->all(); 35 | 36 | if (count($result) === 1) { 37 | $client = new ClientEntity($this->server); 38 | $client->hydrate([ 39 | 'id' => $result[0]['id'], 40 | 'name' => $result[0]['name'], 41 | ]); 42 | 43 | return $client; 44 | } 45 | 46 | return; 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function getBySession(SessionEntity $session) 53 | { 54 | $result = (new Query()) 55 | ->from('oauth_client') 56 | ->select(['oauth_client.id', 'oauth_client.name']) 57 | ->leftJoin('oauth_session', 'oauth_client.id = oauth_session.client_id') 58 | ->where(['oauth_session.id' => $session->getId()]) 59 | ->all(); 60 | 61 | if (count($result) === 1) { 62 | $client = new ClientEntity($this->server); 63 | $client->hydrate([ 64 | 'id' => $result[0]['id'], 65 | 'name' => $result[0]['name'], 66 | ]); 67 | 68 | return $client; 69 | } 70 | 71 | return; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /oauth/RefreshTokenStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_refresh_token') 19 | ->where(['refresh_token' => $token]) 20 | ->all(); 21 | 22 | if (count($result) === 1) { 23 | $token = (new RefreshTokenEntity($this->server)) 24 | ->setId($result[0]['refresh_token']) 25 | ->setExpireTime($result[0]['expire_time']) 26 | ->setAccessTokenId($result[0]['access_token']); 27 | 28 | return $token; 29 | } 30 | 31 | return; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function create($token, $expireTime, $accessToken) 38 | { 39 | \Yii::$app->db->createCommand()->insert('oauth_refresh_token', [ 40 | 'refresh_token' => $token, 41 | 'access_token' => $accessToken, 42 | 'expire_time' => $expireTime, 43 | ])->execute(); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function delete(RefreshTokenEntity $token) 50 | { 51 | \Yii::$app->db->createCommand()->delete('oauth_refresh_token', ['refresh_token' => $token->getId()])->execute(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /oauth/ScopeStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_scope') 19 | ->where(['id' => $scope]) 20 | ->all(); 21 | 22 | if (count($result) === 0) { 23 | return; 24 | } 25 | 26 | return (new ScopeEntity($this->server))->hydrate([ 27 | 'id' => $result[0]['id'], 28 | 'description' => $result[0]['description'], 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /oauth/SessionStorage.php: -------------------------------------------------------------------------------- 1 | from('oauth_session') 22 | ->select(['oauth_session.id', 'oauth_session.owner_type', 'oauth_session.owner_id', 'oauth_session.client_id', 'oauth_session.client_redirect_uri']) 23 | ->leftJoin('oauth_access_token', 'oauth_access_token.session_id = oauth_session.id') 24 | ->where(['oauth_access_tokens.access_token' => $accessToken->getId()]) 25 | ->all(); 26 | 27 | if (count($result) === 1) { 28 | $session = new SessionEntity($this->server); 29 | $session->setId($result[0]['id']); 30 | $session->setOwner($result[0]['owner_type'], $result[0]['owner_id']); 31 | 32 | return $session; 33 | } 34 | 35 | return; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getByAuthCode(AuthCodeEntity $authCode) 42 | { 43 | $result = (new Query()) 44 | ->from('oauth_session') 45 | ->select(['oauth_session.id', 'oauth_session.owner_type', 'oauth_session.owner_id', 'oauth_session.client_id', 'oauth_session.client_redirect_uri']) 46 | ->leftJoin('oauth_auth_code', 'oauth_auth_code.session_id = oauth_session.id') 47 | ->where('oauth_auth_code.auth_code', $authCode->getId()) 48 | ->all(); 49 | 50 | if (count($result) === 1) { 51 | $session = new SessionEntity($this->server); 52 | $session->setId($result[0]['id']); 53 | $session->setOwner($result[0]['owner_type'], $result[0]['owner_id']); 54 | 55 | return $session; 56 | } 57 | 58 | return; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function getScopes(SessionEntity $session) 65 | { 66 | $result = (new Query()) 67 | ->from('oauth_session') 68 | ->select('oauth_scope.*') 69 | ->leftJoin('oauth_session_scope', 'oauth_session.id = oauth_session_scope.session_id') 70 | ->leftJoin('oauth_scope', 'oauth_scope.id = oauth_session_scope.scope') 71 | ->where(['oauth_session.id' => $session->getId()]) 72 | ->all(); 73 | 74 | $scopes = []; 75 | 76 | foreach ($result as $scope) { 77 | $scopes[] = (new ScopeEntity($this->server))->hydrate([ 78 | 'id' => $scope['id'], 79 | 'description' => $scope['description'], 80 | ]); 81 | } 82 | 83 | return $scopes; 84 | } 85 | 86 | /** 87 | * {@inheritdoc} 88 | */ 89 | public function create($ownerType, $ownerId, $clientId, $clientRedirectUri = null) 90 | { 91 | Yii::$app->db->createCommand()->insert('oauth_session', [ 92 | 'owner_type' => $ownerType, 93 | 'owner_id' => $ownerId, 94 | 'client_id' => $clientId, 95 | ]); 96 | 97 | $id = Yii::$app->db->getLastInsertID(); 98 | return $id; 99 | } 100 | 101 | /** 102 | * {@inheritdoc} 103 | */ 104 | public function associateScope(SessionEntity $session, ScopeEntity $scope) 105 | { 106 | Yii::$app->db->createCommand()->insert('oauth_session_scope', [ 107 | 'session_id' => $session->getId(), 108 | 'scope' => $scope->getId(), 109 | ]); 110 | } 111 | } 112 | --------------------------------------------------------------------------------