101 lines
4.2 KiB
Plaintext
101 lines
4.2 KiB
Plaintext
#load "../../lib/app.uce"
|
|
|
|
COMPONENT(Request& context)
|
|
{
|
|
String title = first(context.props["title"].to_string(), "Sign in with OAuth");
|
|
String subtitle = first(context.props["subtitle"].to_string(), "Choose your preferred authentication method");
|
|
String callback_url = first(context.props["callback_url"].to_string(), app_link("auth/callback", context));
|
|
|
|
DValue services = context.props["services"];
|
|
if(services.get_type_name() != "array" || services["google"]["name"].to_string() == "")
|
|
{
|
|
services["google"]["name"] = "Google";
|
|
services["google"]["color"] = "#4285f4";
|
|
services["google"]["icon"] = "fab fa-google";
|
|
services["google"]["scope"] = "openid email profile";
|
|
services["google"]["auth_url"] = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
|
|
services["github"]["name"] = "GitHub";
|
|
services["github"]["color"] = "#333333";
|
|
services["github"]["icon"] = "fab fa-github";
|
|
services["github"]["scope"] = "user:email";
|
|
services["github"]["auth_url"] = "https://github.com/login/oauth/authorize";
|
|
|
|
services["discord"]["name"] = "Discord";
|
|
services["discord"]["color"] = "#5865f2";
|
|
services["discord"]["icon"] = "fab fa-discord";
|
|
services["discord"]["scope"] = "identify email";
|
|
services["discord"]["auth_url"] = "https://discord.com/api/oauth2/authorize";
|
|
|
|
services["twitch"]["name"] = "Twitch";
|
|
services["twitch"]["color"] = "#9146ff";
|
|
services["twitch"]["icon"] = "fab fa-twitch";
|
|
services["twitch"]["scope"] = "user:read:email";
|
|
services["twitch"]["auth_url"] = "https://id.twitch.tv/oauth2/authorize";
|
|
}
|
|
|
|
<>
|
|
<form class="card">
|
|
<div>
|
|
<h2><?= title ?></h2>
|
|
<label><?= subtitle ?></label>
|
|
</div>
|
|
<? services.each([&](DValue service, String service_key) {
|
|
String client_id = context.props[service_key + "_client_id"].to_string();
|
|
String handler_name = ascii_safe_name(service_key);
|
|
String service_name = service["name"].to_string();
|
|
String scope = service["scope"].to_string();
|
|
String auth_url = service["auth_url"].to_string();
|
|
String store_url = app_link("auth/store-oauth-session", context);
|
|
?><div data-service="<?= service_key ?>">
|
|
<button type="button" class="btn" onclick='initiateOAuth_<?= handler_name ?>()'>
|
|
<i class="<?= service["icon"].to_string() ?>" style="color: <?= service["color"].to_string() ?>"></i>
|
|
Continue with <?= service_name ?>
|
|
</button>
|
|
<div class="loading" style="display: none;"><span>Connecting...</span></div>
|
|
<label>Secure authentication via <?= service_name ?></label>
|
|
<script>
|
|
window.initiateOAuth_<?= handler_name ?> = function () {
|
|
const wrapper = document.querySelector('[data-service="<?= service_key ?>"]');
|
|
if (!wrapper) return;
|
|
const button = wrapper.querySelector('.btn');
|
|
const loading = wrapper.querySelector('.loading');
|
|
if (button) button.style.display = 'none';
|
|
if (loading) loading.style.display = 'block';
|
|
|
|
const clientId = <?: json_encode(client_id) ?>;
|
|
if (!clientId || clientId.indexOf('YOUR_') === 0) {
|
|
alert('<?= service_name ?> OAuth is not configured yet.');
|
|
if (button) button.style.display = '';
|
|
if (loading) loading.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
const state = btoa(Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2)).replace(/[^a-zA-Z0-9]/g, '');
|
|
const params = new URLSearchParams({
|
|
client_id: clientId,
|
|
redirect_uri: <?: json_encode(callback_url) ?>,
|
|
scope: <?: json_encode(scope) ?>,
|
|
response_type: 'code',
|
|
state: state
|
|
});
|
|
|
|
sessionStorage.setItem('oauth_state', state);
|
|
sessionStorage.setItem('oauth_service', <?: json_encode(service_key) ?>);
|
|
|
|
fetch(<?: json_encode(store_url) ?>, {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({oauth_service: <?: json_encode(service_key) ?>, oauth_state: state})
|
|
}).catch(console.error).finally(() => {
|
|
window.location.href = <?: json_encode(auth_url) ?> + '?' + params.toString();
|
|
});
|
|
};
|
|
</script>
|
|
</div><?
|
|
}); ?>
|
|
<div class="banner" id="oauth-status" style="display: none;"></div>
|
|
</form>
|
|
</>
|
|
}
|