mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #135 from christyjacob4/master
Added Amazon & VK OAuth
This commit is contained in:
commit
c276a8b8f0
9 changed files with 334 additions and 19 deletions
|
|
@ -57,8 +57,18 @@ return [
|
|||
'enabled' => true,
|
||||
],
|
||||
'apple' => [
|
||||
'developers' => 'https://www.dropbox.com/developers/documentation',
|
||||
'developers' => 'https://developer.apple.com/',
|
||||
'icon' => 'icon-apple',
|
||||
'enabled' => false,
|
||||
],
|
||||
'amazon' => [
|
||||
'developers' => 'https://developer.amazon.com/apps-and-games/services-and-apis',
|
||||
'icon' => 'icon-amazon',
|
||||
'enabled' => true,
|
||||
],
|
||||
'vk' => [
|
||||
'developers' => 'https://vk.com/dev',
|
||||
'icon' => 'icon-vk',
|
||||
'enabled' => true,
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -730,23 +730,8 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
|
|||
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
|
||||
$validateURL = new URL();
|
||||
|
||||
if (!empty($state)) {
|
||||
try {
|
||||
$state = array_merge($defaultState, json_decode($state, true));
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('Failed to parse login state params as passed from OAuth provider');
|
||||
}
|
||||
} else {
|
||||
$state = $defaultState;
|
||||
}
|
||||
|
||||
if (!$validateURL->isValid($state['success'])) {
|
||||
throw new Exception('Invalid redirect URL for success login', 400);
|
||||
}
|
||||
|
||||
if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) {
|
||||
throw new Exception('Invalid redirect URL for failure login', 400);
|
||||
}
|
||||
// Uncomment this while testing amazon oAuth
|
||||
// $state = html_entity_decode($state);
|
||||
|
||||
$appId = $project->getAttribute('usersOauth'.ucfirst($provider).'Appid', '');
|
||||
$appSecret = $project->getAttribute('usersOauth'.ucfirst($provider).'Secret', '{}');
|
||||
|
|
@ -766,6 +751,24 @@ $utopia->get('/v1/auth/oauth/:provider/redirect')
|
|||
|
||||
$oauth = new $classname($appId, $appSecret, $callback);
|
||||
|
||||
if (!empty($state)) {
|
||||
try {
|
||||
$state = array_merge($defaultState, $oauth->parseState($state));
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('Failed to parse login state params as passed from OAuth provider');
|
||||
}
|
||||
} else {
|
||||
$state = $defaultState;
|
||||
}
|
||||
|
||||
if (!$validateURL->isValid($state['success'])) {
|
||||
throw new Exception('Invalid redirect URL for success login', 400);
|
||||
}
|
||||
|
||||
if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) {
|
||||
throw new Exception('Invalid redirect URL for failure login', 400);
|
||||
}
|
||||
|
||||
$accessToken = $oauth->getAccessToken($code);
|
||||
|
||||
if (empty($accessToken)) {
|
||||
|
|
|
|||
BIN
public/images/oauth/amazon.png
Normal file
BIN
public/images/oauth/amazon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
public/images/oauth/vk.png
Normal file
BIN
public/images/oauth/vk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
|
|
@ -78,6 +78,20 @@ abstract class OAuth
|
|||
*/
|
||||
abstract public function getUserName(string $accessToken):string;
|
||||
|
||||
// The parseState function was designed specifically for Amazon OAuth Adapter to override.
|
||||
// The response from Amazon is html encoded and hence it needs to be html_decoded before
|
||||
// json_decoding
|
||||
|
||||
/**
|
||||
* @param $state
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function parseState(string $state)
|
||||
{
|
||||
return json_decode($state, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
|
|
|
|||
138
src/Auth/OAuth/Amazon.php
Normal file
138
src/Auth/OAuth/Amazon.php
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
namespace Auth\OAuth;
|
||||
|
||||
use Auth\OAuth;
|
||||
|
||||
// Reference Material
|
||||
// https://developer.amazon.com/docs/login-with-amazon/authorization-code-grant.html
|
||||
// https://developer.amazon.com/docs/login-with-amazon/register-web.html
|
||||
// https://developer.amazon.com/docs/login-with-amazon/obtain-customer-profile.html
|
||||
class Amazon extends OAuth
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $user = [];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'amazon';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $state
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function parseState(string $state)
|
||||
{
|
||||
return json_decode(html_entity_decode($state), true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
return 'https://www.amazon.com/ap/oa?' .
|
||||
'client_id='.urlencode($this->appID).
|
||||
'&redirect_uri='.urlencode($this->callback).
|
||||
'&response_type=code'.
|
||||
'&state='.urlencode(json_encode($this->state)).
|
||||
'&scope=profile';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessToken(string $code): string
|
||||
{
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8';
|
||||
$accessToken = $this->request(
|
||||
'POST',
|
||||
'https://api.amazon.com/auth/o2/token',
|
||||
$headers,
|
||||
'code=' . urlencode($code) .
|
||||
'&client_id=' . urlencode($this->appID) .
|
||||
'&client_secret=' . urlencode($this->appSecret).
|
||||
'&redirect_uri='.urlencode($this->callback).
|
||||
'&grant_type=authorization_code'
|
||||
);
|
||||
$accessToken = json_decode($accessToken, true);
|
||||
|
||||
if (isset($accessToken['access_token'])) {
|
||||
return $accessToken['access_token'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['user_id'])) {
|
||||
return $user['user_id'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['email'])) {
|
||||
return $user['email'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['name'])) {
|
||||
return $user['name'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$user = $this->request('GET', 'https://api.amazon.com/user/profile?access_token='.urlencode($accessToken));
|
||||
$this->user = json_decode($user, true);
|
||||
}
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ class Apple extends OAuth
|
|||
{
|
||||
if (empty($this->user)) {
|
||||
$headers[] = 'Authorization: Bearer '. urlencode($accessToken);
|
||||
$user = $this->request('POST', 'https://api.dropboxapi.com/2/users/get_current_account', $headers);
|
||||
$user = $this->request('POST', '', $headers);
|
||||
$this->user = json_decode($user, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
150
src/Auth/OAuth/Vk.php
Normal file
150
src/Auth/OAuth/Vk.php
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace Auth\OAuth;
|
||||
|
||||
use Auth\OAuth;
|
||||
|
||||
// Reference Material
|
||||
// https://vk.com/dev/first_guide
|
||||
// https://vk.com/dev/auth_sites
|
||||
// https://vk.com/dev/api_requests
|
||||
// https://plugins.miniorange.com/guide-to-configure-vkontakte-as-oauth-server
|
||||
|
||||
class Vk extends OAuth
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $user = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $version = '5.101';
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'vk';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
return 'https://oauth.vk.com/authorize?' .
|
||||
'client_id='.urlencode($this->appID).
|
||||
'&redirect_uri='.urlencode($this->callback).
|
||||
'&response_type=code'.
|
||||
'&state='.urlencode(json_encode($this->state)).
|
||||
'&v='.urlencode($this->version).
|
||||
'&scope=openid+email';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessToken(string $code): string
|
||||
{
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8';
|
||||
$accessToken = $this->request(
|
||||
'POST',
|
||||
'https://oauth.vk.com/access_token?',
|
||||
$headers,
|
||||
'code=' . urlencode($code) .
|
||||
'&client_id=' . urlencode($this->appID) .
|
||||
'&client_secret=' . urlencode($this->appSecret).
|
||||
'&redirect_uri='.urlencode($this->callback)
|
||||
);
|
||||
$accessToken = json_decode($accessToken, true);
|
||||
|
||||
if (isset($accessToken['email'])) {
|
||||
$this->user['email'] = $accessToken['email'];
|
||||
}
|
||||
|
||||
if (isset($accessToken['user_id'])) {
|
||||
$this->user['user_id'] = $accessToken['user_id'];
|
||||
}
|
||||
|
||||
if (isset($accessToken['access_token'])) {
|
||||
return $accessToken['access_token'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['user_id'])) {
|
||||
return $user['user_id'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['email'])) {
|
||||
return $user['email'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['name'])) {
|
||||
return $user['name'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user['name'])) {
|
||||
$user = $this->request(
|
||||
'GET',
|
||||
'https://api.vk.com/method/users.get?'.
|
||||
'v='.urlencode($this->version).
|
||||
'&fields=id,name,email,first_name,last_name'.
|
||||
'&access_token='.urlencode($accessToken)
|
||||
);
|
||||
|
||||
$user = json_decode($user, true);
|
||||
$this->user['name'] = $user['response'][0]['first_name'] ." ".$user['response'][0]['last_name'];
|
||||
}
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue