mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge pull request #362 from appwrite/apple-oauth
Apple OAuth Adapter ⭐️
This commit is contained in:
@@ -104,6 +104,7 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
|
||||
|
||||
if(!$originValidator->isValid($origin)
|
||||
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
|
||||
&& $route->getLabel('origin', false) !== '*'
|
||||
&& empty($request->getHeader('X-Appwrite-Key', ''))) {
|
||||
throw new Exception($originValidator->getDescription(), 403);
|
||||
}
|
||||
|
||||
@@ -5,138 +5,182 @@ return [
|
||||
'developers' => 'https://developer.atlassian.com/bitbucket',
|
||||
'icon' => 'icon-bitbucket',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'facebook' => [
|
||||
'developers' => 'https://developers.facebook.com/',
|
||||
'icon' => 'icon-facebook',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'github' => [
|
||||
'developers' => 'https://developer.github.com/',
|
||||
'icon' => 'icon-github-circled',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'gitlab' => [
|
||||
'developers' => 'https://docs.gitlab.com/ee/api/',
|
||||
'icon' => 'icon-gitlab',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'google' => [
|
||||
'developers' => 'https://developers.google.com/',
|
||||
'icon' => 'icon-google',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
// 'instagram' => [
|
||||
// 'developers' => 'https://www.instagram.com/developer/',
|
||||
// 'icon' => 'icon-instagram',
|
||||
// 'enabled' => false,
|
||||
// 'beta' => false,
|
||||
// 'mock' => false,
|
||||
// ],
|
||||
'microsoft' => [
|
||||
'developers' => 'https://developer.microsoft.com/en-us/',
|
||||
'icon' => 'icon-windows',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
// 'twitter' => [
|
||||
// 'developers' => 'https://developer.twitter.com/',
|
||||
// 'icon' => 'icon-twitter',
|
||||
// 'enabled' => false,
|
||||
// 'beta' => false,
|
||||
// 'mock' => false,
|
||||
// ],
|
||||
'linkedin' => [
|
||||
'developers' => 'https://developer.linkedin.com/',
|
||||
'icon' => 'icon-linkedin',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'slack' => [
|
||||
'developers' => 'https://api.slack.com/',
|
||||
'icon' => 'icon-slack',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'dropbox' => [
|
||||
'developers' => 'https://www.dropbox.com/developers/documentation',
|
||||
'icon' => 'icon-dropbox',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'salesforce' => [
|
||||
'developers' => 'https://developer.salesforce.com/docs/',
|
||||
'icon' => 'icon-salesforce',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'apple' => [
|
||||
'developers' => 'https://developer.apple.com/',
|
||||
'icon' => 'icon-apple',
|
||||
'enabled' => true,
|
||||
'form' => 'apple.phtml', // Perperation for adding ability to customized OAuth UI forms, currently handled hardcoded.
|
||||
'beta' => true,
|
||||
'mock' => false,
|
||||
],
|
||||
// 'apple' => [
|
||||
// 'developers' => 'https://developer.apple.com/',
|
||||
// 'icon' => 'icon-apple',
|
||||
// 'enabled' => false,
|
||||
// 'mock' => false,
|
||||
// ],
|
||||
'amazon' => [
|
||||
'developers' => 'https://developer.amazon.com/apps-and-games/services-and-apis',
|
||||
'icon' => 'icon-amazon',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'vk' => [
|
||||
'developers' => 'https://vk.com/dev',
|
||||
'icon' => 'icon-vk',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'discord' => [
|
||||
'developers' => 'https://discordapp.com/developers/docs/topics/oauth2',
|
||||
'icon' => 'icon-discord',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'twitch' => [
|
||||
'developers' => 'https://dev.twitch.tv/docs/authentication',
|
||||
'icon' => 'icon-twitch',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'spotify' => [
|
||||
'developers' => 'https://developer.spotify.com/documentation/general/guides/authorization-guide/',
|
||||
'icon' => 'icon-spotify',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'yahoo' => [
|
||||
'developers' => 'https://developer.yahoo.com/oauth2/guide/flows_authcode/',
|
||||
'icon' => 'icon-yahoo',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'yandex' => [
|
||||
'developers' => 'https://tech.yandex.com/oauth/',
|
||||
'icon' => 'icon-yandex',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'twitter' => [
|
||||
'developers' => 'https://developer.twitter.com/',
|
||||
'icon' => 'icon-twitter',
|
||||
'enabled' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'paypal' => [
|
||||
'developers' => 'https://developer.paypal.com/docs/api/overview/',
|
||||
'icon' => 'icon-paypal',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'bitly' => [
|
||||
'developers' => 'https://dev.bitly.com/v4_documentation.html',
|
||||
'icon' => 'icon-bitly',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
// Keep Last
|
||||
@@ -144,6 +188,8 @@ return [
|
||||
'developers' => 'https://appwrite.io',
|
||||
'icon' => 'icon-appwrite',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => true,
|
||||
]
|
||||
];
|
||||
|
||||
@@ -308,6 +308,29 @@ $utopia->get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
|
||||
}
|
||||
);
|
||||
|
||||
$utopia->post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
|
||||
->desc('OAuth2 Callback')
|
||||
->label('error', __DIR__.'/../../views/general/error.phtml')
|
||||
->label('scope', 'public')
|
||||
->label('origin', '*')
|
||||
->label('docs', false)
|
||||
->param('projectId', '', function () { return new Text(1024); }, 'Project unique ID.')
|
||||
->param('provider', '', function () { return new WhiteList(array_keys(Config::getParam('providers'))); }, 'OAuth2 provider.')
|
||||
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
|
||||
->param('state', '', function () { return new Text(2048); }, 'Login state params.', true)
|
||||
->action(
|
||||
function ($projectId, $provider, $code, $state) use ($response) {
|
||||
$domain = Config::getParam('domain');
|
||||
$protocol = Config::getParam('protocol');
|
||||
|
||||
$response
|
||||
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||
->addHeader('Pragma', 'no-cache')
|
||||
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
|
||||
.http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
|
||||
}
|
||||
);
|
||||
|
||||
$utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
->desc('OAuth2 Redirect')
|
||||
->label('error', __DIR__.'/../../views/general/error.phtml')
|
||||
@@ -361,6 +384,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) {
|
||||
throw new Exception('Invalid redirect URL for failure login', 400);
|
||||
}
|
||||
|
||||
$state['failure'] = null;
|
||||
$accessToken = $oauth2->getAccessToken($code);
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ $utopia->patch('/v1/projects/:projectId/oauth2')
|
||||
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
|
||||
->param('provider', '', function () { return new WhiteList(array_keys(Config::getParam('providers'))); }, 'Provider Name', false)
|
||||
->param('appId', '', function () { return new Text(256); }, 'Provider app ID.', true)
|
||||
->param('secret', '', function () { return new text(256); }, 'Provider secret key.', true)
|
||||
->param('secret', '', function () { return new text(512); }, 'Provider secret key.', true)
|
||||
->action(
|
||||
function ($projectId, $provider, $appId, $secret) use ($request, $response, $consoleDB) {
|
||||
$project = $consoleDB->getDocument($projectId);
|
||||
|
||||
@@ -337,12 +337,14 @@ $providers = $this->getParam('providers', []);
|
||||
<?php foreach ($providers as $provider => $data):
|
||||
if (isset($data['enabled']) && !$data['enabled']) { continue; }
|
||||
if (isset($data['mock']) && $data['mock']) { continue; }
|
||||
$form = (isset($data['form'])) ? $data['form'] : false;
|
||||
$beta = (isset($data['beta'])) ? $data['beta'] : false;
|
||||
?>
|
||||
<li class="clear <?php echo (isset($data['enabled']) && !$data['enabled']) ? 'dev-feature' : ''; ?>">
|
||||
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="provider-update-<?php echo $provider; ?>">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1><?php echo ucfirst($provider); ?> OAuth2 Settings</h1>
|
||||
<h1><?php echo $this->escape(ucfirst($provider)); ?> OAuth2 Settings</h1>
|
||||
|
||||
<form
|
||||
data-analytics-event="submit"
|
||||
@@ -358,23 +360,30 @@ $providers = $this->getParam('providers', []);
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update project OAuth2 settings"
|
||||
data-failure-param-alert-classname="error">
|
||||
<input name="provider" id="provider<?php echo ucfirst($provider); ?>" type="hidden" autocomplete="off" value="<?php echo $provider; ?>">
|
||||
<input name="provider" id="provider<?php echo $this->escape(ucfirst($provider)); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($provider); ?>">
|
||||
|
||||
<label for="oauth2<?php echo ucfirst($provider); ?>Appid">App ID</label>
|
||||
<input name="appId" id="oauth2<?php echo ucfirst($provider); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}}">
|
||||
<?php if(!$form): ?>
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">App ID</label>
|
||||
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}}">
|
||||
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret">App Secret</label>
|
||||
<input name="secret" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
|
||||
<?php else: ?>
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">Bundle ID <span class="tooltip" data-tooltip="Attribute internal display name"><i class="icon-info-circled"></i></span></label>
|
||||
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}}" placeholder="com.company.appname" />
|
||||
|
||||
<label for="oauth2<?php echo ucfirst($provider); ?>Secret">App Secret</label>
|
||||
<input name="secret" id="oauth2<?php echo ucfirst($provider); ?>Secret" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
|
||||
<input name="secret" data-forms-oauth-apple id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="hidden" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="info row thin margin-bottom margin-top">
|
||||
<div class="col span-1">
|
||||
<i class="icon-info-circled text-sign"></i>
|
||||
</div>
|
||||
<div class="col span-11">
|
||||
<p>To complete set up, add this OAuth2 redirect URI to your <?php echo ucfirst($provider); ?> app configuration.</p>
|
||||
<p>To complete set up, add this OAuth2 redirect URI to your <?php echo $this->escape(ucfirst($provider)); ?> app configuration.</p>
|
||||
|
||||
<div class="input-copy">
|
||||
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1/account/sessions/oauth2/callback/<?php echo $provider; ?>/{{router.params.project}}" class="margin-bottom-no" />
|
||||
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1/account/sessions/oauth2/callback/<?php echo $this->escape($provider); ?>/{{router.params.project}}" class="margin-bottom-no" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -384,19 +393,19 @@ $providers = $this->getParam('providers', []);
|
||||
</div>
|
||||
|
||||
<span data-ls-if="
|
||||
{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}} &&
|
||||
{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
|
||||
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} &&
|
||||
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
|
||||
<button class="switch on pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $provider; ?>"></button>
|
||||
</span>
|
||||
<span data-ls-if="
|
||||
!{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}} ||
|
||||
!{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
|
||||
<button class="switch pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $provider; ?>"></button>
|
||||
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} ||
|
||||
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
|
||||
<button class="switch pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $this->escape($provider); ?>"></button>
|
||||
</span>
|
||||
|
||||
<img src="/images/oauth2/<?php echo strtolower($provider); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo ucfirst($provider); ?> Logo" class="pull-start provider margin-end" />
|
||||
<img src="/images/oauth2/<?php echo $this->escape(strtolower($provider)); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo $this->escape(ucfirst($provider)); ?> Logo" class="pull-start provider margin-end" />
|
||||
<span>
|
||||
<?php echo ucfirst($provider); ?>
|
||||
<?php echo ucfirst($provider); ?> <?php if($beta): ?>(beta)<?php endif; ?>
|
||||
</span>
|
||||
<p class="margin-bottom-no margin-top-small text-one-liner">
|
||||
<a href="<?php echo $data['developers']; ?>" target="_blank" rel="noopener">OAuth2 Developer Docs<i class="icon-link-ext"></i></a>
|
||||
|
||||
Reference in New Issue
Block a user