From ee46e141032048ce4784899743d8dc2f22061713 Mon Sep 17 00:00:00 2001 From: adityaoberai Date: Fri, 1 Apr 2022 16:04:56 +0530 Subject: [PATCH 1/9] Create Auth0 OAuth Adapter --- app/config/providers.php | 10 + app/views/console/users/oauth/auth0.phtml | 12 ++ public/images/users/auth0.png | Bin 0 -> 2512 bytes public/scripts/views/forms/oauth-custom.js | 4 + src/Appwrite/Auth/OAuth2/Auth0.php | 206 +++++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 app/views/console/users/oauth/auth0.phtml create mode 100644 public/images/users/auth0.png create mode 100644 src/Appwrite/Auth/OAuth2/Auth0.php diff --git a/app/config/providers.php b/app/config/providers.php index 9a6b5fb50f..aa3877005c 100644 --- a/app/config/providers.php +++ b/app/config/providers.php @@ -21,6 +21,16 @@ return [ // Ordered by ABC. 'beta' => true, 'mock' => false, ], + 'auth0' => [ + 'name' => 'Auth0', + 'developers' => 'https://auth0.com/developers', + 'icon' => 'icon-auth0', + 'enabled' => true, + 'sandbox' => false, + 'form' => 'auth0.phtml', + 'beta' => false, + 'mock' => false, + ], 'bitbucket' => [ 'name' => 'BitBucket', 'developers' => 'https://developer.atlassian.com/bitbucket', diff --git a/app/views/console/users/oauth/auth0.phtml b/app/views/console/users/oauth/auth0.phtml new file mode 100644 index 0000000000..504eca6bc1 --- /dev/null +++ b/app/views/console/users/oauth/auth0.phtml @@ -0,0 +1,12 @@ +getParam('provider', ''); +?> + + + + + + + + + \ No newline at end of file diff --git a/public/images/users/auth0.png b/public/images/users/auth0.png new file mode 100644 index 0000000000000000000000000000000000000000..d0800c6294456910029132f3edf02cbbdbefc6fb GIT binary patch literal 2512 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 literal 0 HcmV?d00001 diff --git a/public/scripts/views/forms/oauth-custom.js b/public/scripts/views/forms/oauth-custom.js index 323c874411..22ab85f872 100644 --- a/public/scripts/views/forms/oauth-custom.js +++ b/public/scripts/views/forms/oauth-custom.js @@ -16,6 +16,10 @@ "keyId": "oauth2AppleKeyId", "teamId": "oauth2AppleTeamId", "p8": "oauth2AppleP8" + }, + "Auth0": { + "clientSecret": "oauth2Auth0ClientSecret", + "auth0Domain": "oauth2Auth0Domain" } } let provider = element.getAttribute("data-forms-oauth-custom"); diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php new file mode 100644 index 0000000000..43a4038aa1 --- /dev/null +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -0,0 +1,206 @@ +getAuth0Domain().'/authorize?'.\http_build_query([ + 'client_id' => $this->appID, + 'redirect_uri' => $this->callback, + 'state'=> \json_encode($this->state), + 'scope'=> \implode(' ', $this->getScopes()), + 'response_type' => 'code' + ]); + } + + /** + * @param string $code + * + * @return array + */ + protected function getTokens(string $code): array + { + if(empty($this->tokens)) { + $headers = ['Content-Type: application/x-www-form-urlencoded']; + $this->tokens = \json_decode($this->request( + 'POST', + 'https://'.$this->getAuth0Domain().'/oauth/token', + $headers, + \http_build_query([ + 'code' => $code, + 'client_id' => $this->appID, + 'client_secret' => $this->getClientSecret(), + 'redirect_uri' => $this->callback, + 'scope' => \implode(' ', $this->getScopes()), + 'grant_type' => 'authorization_code' + ]) + ), true); + } + + return $this->tokens; + } + + + /** + * @param string $refreshToken + * + * @return array + */ + public function refreshTokens(string $refreshToken):array + { + $headers = ['Content-Type: application/x-www-form-urlencoded']; + $this->tokens = \json_decode($this->request( + 'POST', + 'https://'.$this->getAuth0Domain().'/oauth/token', + $headers, + \http_build_query([ + 'refresh_token' => $refreshToken, + 'client_id' => $this->appID, + 'client_secret' => $this->getClientSecret(), + 'grant_type' => 'refresh_token' + ]) + ), true); + + if(empty($this->tokens['refresh_token'])) { + $this->tokens['refresh_token'] = $refreshToken; + } + + return $this->tokens; + } + + /** + * @param string $accessToken + * + * @return string + */ + public function getUserID(string $accessToken): string + { + $user = $this->getUser($accessToken); + + if (isset($user['sub'])) { + return $user['sub']; + } + + 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) + { + if (empty($this->user)) { + $headers = ['Authorization: Bearer '. \urlencode($accessToken)]; + $user = $this->request('GET', 'https://'.$this->getAuth0Domain().'/userinfo', $headers); + $this->user = \json_decode($user, true); + } + + return $this->user; + } + + /** + * Extracts the Client Secret from the JSON stored in appSecret + * @return string + */ + protected function getClientSecret(): string + { + $secret = $this->decodeJson(); + + return (isset($secret['clientSecret'])) ? $secret['clientSecret'] : ''; + } + + /** + * Extracts the Auth0 Domain from the JSON stored in appSecret. Defaults to 'common' as a fallback + * @return string + */ + protected function getAuth0Domain(): string + { + $secret = $this->decodeJson(); + return (isset($secret['auth0Domain'])) ? $secret['auth0Domain'] : ''; + } + + /** + * Decode the JSON stored in appSecret + * @return array + */ + protected function decodeJson(): array + { + try { + $secret = \json_decode($this->appSecret, true); + } catch (\Throwable $th) { + throw new Exception('Invalid secret'); + } + return $secret; + } +} \ No newline at end of file From 4400d4b8079454f825639267d0a2f271af113b7a Mon Sep 17 00:00:00 2001 From: adityaoberai Date: Fri, 1 Apr 2022 16:54:58 +0530 Subject: [PATCH 2/9] Add refresh token support --- src/Appwrite/Auth/OAuth2/Auth0.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 43a4038aa1..0709217b5b 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -15,7 +15,8 @@ class Auth0 extends OAuth2 protected $scopes = [ 'openid', 'profile', - 'email' + 'email', + 'offline_access' ]; /** From 0cacfd17cbff94e8b80ab8f825a0822b0f247085 Mon Sep 17 00:00:00 2001 From: adityaoberai Date: Fri, 1 Apr 2022 19:43:29 +0530 Subject: [PATCH 3/9] Update Auth0 domain info tip for better clarity --- app/views/console/users/oauth/auth0.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/console/users/oauth/auth0.phtml b/app/views/console/users/oauth/auth0.phtml index 504eca6bc1..8509a582b5 100644 --- a/app/views/console/users/oauth/auth0.phtml +++ b/app/views/console/users/oauth/auth0.phtml @@ -6,7 +6,7 @@ $provider = $this->getParam('provider', ''); - + \ No newline at end of file From 0784981c4209b4d583fc1384d9fa98d4da19b153 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Sun, 3 Apr 2022 19:17:16 +0530 Subject: [PATCH 4/9] Update src/Appwrite/Auth/OAuth2/Auth0.php Co-authored-by: Christy Jacob --- src/Appwrite/Auth/OAuth2/Auth0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 0709217b5b..9186f7c1cd 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -84,7 +84,7 @@ class Auth0 extends OAuth2 * * @return array */ - public function refreshTokens(string $refreshToken):array + public function refreshTokens(string $refreshToken): array { $headers = ['Content-Type: application/x-www-form-urlencoded']; $this->tokens = \json_decode($this->request( From e7fd6a81ac873283fe99175114d28b6c3da77416 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Sun, 3 Apr 2022 19:17:29 +0530 Subject: [PATCH 5/9] Update src/Appwrite/Auth/OAuth2/Auth0.php Co-authored-by: Christy Jacob --- src/Appwrite/Auth/OAuth2/Auth0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 9186f7c1cd..b7e6071417 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -195,7 +195,7 @@ class Auth0 extends OAuth2 * Decode the JSON stored in appSecret * @return array */ - protected function decodeJson(): array + protected function getAppSecret(): array { try { $secret = \json_decode($this->appSecret, true); From 0c09d73a20d35b841746bf1729df58616bc5afbf Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Sun, 3 Apr 2022 21:57:15 +0530 Subject: [PATCH 6/9] Update src/Appwrite/Auth/OAuth2/Auth0.php Co-authored-by: Christy Jacob --- src/Appwrite/Auth/OAuth2/Auth0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index b7e6071417..7195bce83e 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -200,7 +200,7 @@ class Auth0 extends OAuth2 try { $secret = \json_decode($this->appSecret, true); } catch (\Throwable $th) { - throw new Exception('Invalid secret'); + throw new \Exception('Invalid secret'); } return $secret; } From 3397036224f9e3f3a23fc670baad79349072be44 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Sun, 3 Apr 2022 21:57:28 +0530 Subject: [PATCH 7/9] Update src/Appwrite/Auth/OAuth2/Auth0.php Co-authored-by: Christy Jacob --- src/Appwrite/Auth/OAuth2/Auth0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 7195bce83e..0558bfc24c 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -198,7 +198,7 @@ class Auth0 extends OAuth2 protected function getAppSecret(): array { try { - $secret = \json_decode($this->appSecret, true); + $secret = \json_decode($this->appSecret, true, 512, JSON_THROW_ON_ERROR); } catch (\Throwable $th) { throw new \Exception('Invalid secret'); } From 90e55f4c34a2d43aa111ecf86a2cfcba23695213 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Sun, 3 Apr 2022 21:57:40 +0530 Subject: [PATCH 8/9] Update src/Appwrite/Auth/OAuth2/Auth0.php Co-authored-by: Christy Jacob --- src/Appwrite/Auth/OAuth2/Auth0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 0558bfc24c..75616e41c8 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -159,7 +159,7 @@ class Auth0 extends OAuth2 * * @return array */ - protected function getUser(string $accessToken) + protected function getUser(string $accessToken): array { if (empty($this->user)) { $headers = ['Authorization: Bearer '. \urlencode($accessToken)]; From 528b4eb947260e1c89800249ff8399253b324226 Mon Sep 17 00:00:00 2001 From: adityaoberai Date: Sun, 3 Apr 2022 22:07:49 +0530 Subject: [PATCH 9/9] Add suggested changes --- src/Appwrite/Auth/OAuth2/Auth0.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 75616e41c8..b1c9c8ce1f 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -172,27 +172,30 @@ class Auth0 extends OAuth2 /** * Extracts the Client Secret from the JSON stored in appSecret + * * @return string */ protected function getClientSecret(): string { - $secret = $this->decodeJson(); + $secret = $this->getAppSecret(); return (isset($secret['clientSecret'])) ? $secret['clientSecret'] : ''; } /** - * Extracts the Auth0 Domain from the JSON stored in appSecret. Defaults to 'common' as a fallback + * Extracts the Auth0 Domain from the JSON stored in appSecret + * * @return string */ protected function getAuth0Domain(): string { - $secret = $this->decodeJson(); + $secret = $this->getAppSecret(); return (isset($secret['auth0Domain'])) ? $secret['auth0Domain'] : ''; } /** * Decode the JSON stored in appSecret + * * @return array */ protected function getAppSecret(): array