mirror of
https://github.com/NamelessMC/Nameless
synced 2026-08-18 06:29:04 -04:00
221 lines
8 KiB
PHP
221 lines
8 KiB
PHP
<?php
|
|
|
|
const PAGE = 'oauth';
|
|
require_once(ROOT_PATH . '/core/templates/frontend_init.php');
|
|
|
|
if (isset($_GET['action']) && $_GET['action'] == 'cancel_registration') {
|
|
Session::delete('oauth_register_data');
|
|
Redirect::to(URL::build('/register'));
|
|
}
|
|
|
|
if (!isset($_GET['provider'])) {
|
|
ErrorHandler::logWarning('No provider set when accessing OAuth');
|
|
Session::flash('home_error', $language->get('general', 'oauth_no_data'));
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
|
|
if (!array_key_exists($_GET['provider'], NamelessOAuth::getInstance()->getProvidersAvailable())) {
|
|
ErrorHandler::logWarning("Invalid provider {$_GET['provider']}");
|
|
Session::flash('home_error', $language->get('general', 'oauth_failed'));
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
|
|
if (!Session::exists('oauth_method')) {
|
|
ErrorHandler::logWarning("No OAuth method set");
|
|
Session::flash('home_error', $language->get('general', 'oauth_failed'));
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
|
|
if (isset($_GET['action']) && $_GET['action'] == 'init') {
|
|
try {
|
|
$provider_data = NamelessOAuth::getInstance()->getProvider($_GET['provider']);
|
|
$provider = NamelessOAuth::getInstance()->getProviderInstance($_GET['provider']);
|
|
|
|
$url = $provider->getAuthorizationUrl([
|
|
'scope' => $provider_data['scopes'] ?? [
|
|
$provider_data['scope_id_name'],
|
|
'email',
|
|
],
|
|
]);
|
|
|
|
Session::put('oauth_state', $provider->getState());
|
|
Redirect::to($url);
|
|
} catch (Exception $e) {
|
|
ErrorHandler::logWarning('An error occurred while handling an OAuth ' . Session::get('oauth_method') . ' request: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
if (!isset($_GET['code'])) {
|
|
ErrorHandler::logWarning('No code set when accessing OAuth');
|
|
Session::flash('home_error', $language->get('general', 'oauth_no_data'));
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
|
|
if (!isset($_GET['state']) || !Session::exists('oauth_state') || $_GET['state'] !== Session::get('oauth_state')) {
|
|
ErrorHandler::logWarning('OAuth state validation failed');
|
|
Session::flash('home_error', $language->get('general', 'oauth_failed'));
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
Session::delete('oauth_state');
|
|
|
|
// If they are filling in 2FA. We've already retrieved their user. We can skip the other steps in this case
|
|
if (isset($_SESSION['user_id']) && isset($_POST['tfa_code'])) {
|
|
$user = new User($_SESSION['user_id']);
|
|
|
|
// Continue the 2FA process
|
|
$tfa = new \RobThree\Auth\TwoFactorAuth(new \RobThree\Auth\Providers\Qr\QRServerProvider(), Output::getClean(SITE_NAME));
|
|
if ($tfa->verifyCode($user->data()->tfa_secret, str_replace(' ', '', $_POST['tfa_code'])) !== true) {
|
|
Session::flash('tfa_signin', $language->get('user', 'invalid_tfa'));
|
|
require(ROOT_PATH . '/core/includes/tfa_signin.php');
|
|
die();
|
|
}
|
|
unset($_SESSION['user_id']);
|
|
|
|
// Log the user in if 2FA passed
|
|
if ($user->login(
|
|
$user->data()->id,
|
|
'', true, 'oauth'
|
|
)) {
|
|
Log::getInstance()->log(Log::Action('user/login'));
|
|
Session::flash('home', $language->get('user', 'oauth_login_success', ['provider' => ucfirst($provider_name)]));
|
|
Session::delete('oauth_method');
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
}
|
|
|
|
$provider_name = $_GET['provider'];
|
|
$provider = NamelessOAuth::getInstance()->getProviderInstance($provider_name);
|
|
try {
|
|
$token = $provider->getAccessToken('authorization_code', [
|
|
'code' => $_GET['code']
|
|
]);
|
|
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
|
|
Session::flash('oauth_error', $language->get('general', 'oauth_failed_setup'));
|
|
ErrorHandler::logWarning('An error occurred while handling an OAuth ' . Session::get('oauth_method') . ' request: ' . $e->getMessage());
|
|
|
|
$method = Session::get('oauth_method');
|
|
switch($method) {
|
|
case 'register':
|
|
Redirect::to(URL::build('/register'));
|
|
|
|
case 'login':
|
|
Redirect::to(URL::build('/login'));
|
|
|
|
case 'link':
|
|
Redirect::to(URL::build('/user/oauth/'));
|
|
|
|
case 'link_integration':
|
|
Redirect::to(URL::build('/user/connections/'));
|
|
}
|
|
}
|
|
|
|
$oauth_user = $provider->getResourceOwner($token)->toArray();
|
|
$provider_id = $oauth_user[NamelessOAuth::getInstance()->getUserIdName($provider_name)];
|
|
|
|
// register
|
|
if (Session::get('oauth_method') === 'register') {
|
|
$integration = Integrations::getInstance()->getIntegration($provider_name);
|
|
if ($integration == null) {
|
|
Session::flash('oauth_error', $language->get('general', 'oauth_failed_setup'));
|
|
Redirect::to(URL::build('/register'));
|
|
}
|
|
|
|
$integrationUser = new IntegrationUser($integration, $provider_id, 'identifier');
|
|
if ($integrationUser->exists()) {
|
|
Session::flash('oauth_error', $language->get('user', 'oauth_already_linked', ['provider' => ucfirst($provider_name)]));
|
|
Redirect::to(URL::build('/register'));
|
|
}
|
|
|
|
Session::put('oauth_register_data', json_encode([
|
|
'provider' => $provider_name,
|
|
'id' => $provider_id,
|
|
'email' => $oauth_user['email'],
|
|
'data' => $oauth_user
|
|
]));
|
|
|
|
Redirect::to(URL::build('/register'));
|
|
}
|
|
|
|
// login
|
|
if (Session::get('oauth_method') === 'login') {
|
|
$integration = Integrations::getInstance()->getIntegration($provider_name);
|
|
if ($integration == null) {
|
|
Session::flash('oauth_error', $language->get('general', 'oauth_failed_setup'));
|
|
Redirect::to(URL::build('/register'));
|
|
}
|
|
|
|
$integrationUser = new IntegrationUser($integration, $provider_id, 'identifier');
|
|
if (!$integrationUser->exists()) {
|
|
Session::flash('oauth_error', $language->get('user', 'no_user_found_with_provider', ['provider' => ucfirst($provider_name)]));
|
|
Redirect::to(URL::build('/login'));
|
|
}
|
|
|
|
$user_id = $integrationUser->data()->user_id;
|
|
$user = new User($user_id);
|
|
|
|
// Make sure user is validated
|
|
if (!$user->isValidated()) {
|
|
Session::flash('oauth_error', $language->get('user', 'inactive_account'));
|
|
Redirect::to(URL::build('/login'));
|
|
}
|
|
|
|
// Make sure user is not banned
|
|
if ($user->data()->isbanned == 1) {
|
|
Session::flash('oauth_error', $language->get('user', 'account_banned'));
|
|
Redirect::to(URL::build('/login'));
|
|
}
|
|
|
|
// If the user has 2FA enabled, ask for those credentials
|
|
if ($user->data()->tfa_enabled == 1 && $user->data()->tfa_complete == 1) {
|
|
$_SESSION['user_id'] = $user_id;
|
|
if (!isset($_POST['tfa_code'])) {
|
|
require(ROOT_PATH . '/core/includes/tfa_signin.php');
|
|
die();
|
|
}
|
|
}
|
|
|
|
// Log the user in
|
|
if ((new User())->login(
|
|
$user_id,
|
|
'', true, 'oauth'
|
|
)) {
|
|
Log::getInstance()->log(Log::Action('user/login'));
|
|
Session::flash('home', $language->get('user', 'oauth_login_success', ['provider' => ucfirst($provider_name)]));
|
|
Session::delete('oauth_method');
|
|
|
|
if (isset($_SESSION['last_page']) && substr($_SESSION['last_page'], -1) != '=') {
|
|
Redirect::back();
|
|
}
|
|
|
|
Redirect::to(URL::build('/'));
|
|
}
|
|
|
|
throw new RuntimeException('Failed to login user with OAuth');
|
|
}
|
|
|
|
// link user integration
|
|
if (Session::get('oauth_method') === 'link_integration') {
|
|
$integration = Integrations::getInstance()->getIntegration($provider_name);
|
|
if ($integration == null) {
|
|
Session::flash('connections_error', $language->get('general', 'oauth_failed_setup'));
|
|
}
|
|
|
|
// Allow the user integration to access the data from the oauth response
|
|
Session::put('oauth_register_data', json_encode([
|
|
'provider' => $provider_name,
|
|
'id' => $provider_id,
|
|
'email' => $oauth_user['email'],
|
|
'data' => $oauth_user
|
|
]));
|
|
|
|
// Link the user integration
|
|
$integration->successfulRegistration($user);
|
|
|
|
if ($integration->getErrors()) {
|
|
Session::flash('connections_error', $integration->getErrors()[0]);
|
|
}
|
|
|
|
Session::delete('oauth_register_data');
|
|
Session::delete('oauth_method');
|
|
Redirect::to(URL::build('/user/connections'));
|
|
}
|