Switched to public API for authentication and a horrible device auth implementation for unsecured connections.

This commit is contained in:
flash 2024-11-20 02:43:47 +00:00
parent 951ec95ca2
commit d0cab7054f
16 changed files with 169 additions and 115 deletions

View file

@ -50,6 +50,10 @@ $config['flashiiUrl']['feedback'] = 'https://flashii.net/forum';
$config['flashiiUrl']['changelog'] = 'https://flashii.net/changelog';
$config['flashiiUrl']['rules'] = 'https://flashii.net/info/rules';
$config['flashiiUrl']['contact'] = 'https://flashii.net/info/contact';
$config['flashiiId']['api'] = '';
$config['flashiiId']['id'] = '';
$config['flashiiId']['clientId'] = '';
$config['flashiiId']['clientSecret'] = '';
if(is_file(AJAX_CHAT_PATH . '/config/config-db.php'))
include_once AJAX_CHAT_PATH . '/config/config-db.php';

View file

@ -119,3 +119,5 @@ $lang['logsTime'] = 'Time';
$lang['logsSearch'] = 'Search';
$lang['logsPrivateChannels'] = 'Private Channels';
$lang['logsPrivateMessages'] = 'Private Messages';
$lang['fidAuthzRequestFailed'] = 'Could not request authorization code.';
$lang['fidAuthzTokenFailed'] = 'Could not complete authorization request, please try again.';

View file

@ -17,6 +17,8 @@
color:#f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #222, #000);
background-image: -moz-linear-gradient(to bottom, #222, #000);
background-image: -webkit-linear-gradient(top, #222, #000);
}
#content select, #loginForm select, #loginForm input, #content textarea {
background-color:#000;
@ -95,4 +97,4 @@
background-color:#212121;
color:#FFF;
}
}
}

View file

@ -20,6 +20,7 @@
color:#f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #002545, #000);
background-image: -moz-linear-gradient(to bottom, #002545, #000);
background-image: -webkit-linear-gradient(top, #002545, #000);
}
#content select, #loginForm select, #loginForm input, #content textarea {
@ -103,4 +104,4 @@
background-color:#0D355D;
color:#FFF;
}
}
}

View file

@ -18,7 +18,9 @@
#loginContent {
background-color: #000000;
background-image: -linear-gradient(to bottom, #4c3b52, #000000);
background-image: linear-gradient(to bottom, #4c3b52, #000000);
background-image: -moz-linear-gradient(to bottom, #4c3b52, #000000);
background-image: -webkit-linear-gradient(top, #4c3b52, #000000);
color: #999999;
}
#loginContent h1 {
@ -42,6 +44,8 @@
#content {
background-color: #000000;
background-image: linear-gradient(to bottom, #4c3b52, #000000);
background-image: -moz-linear-gradient(to bottom, #4c3b52, #000000);
background-image: -webkit-linear-gradient(top, #4c3b52, #000000);
color: #999999;
}
#content h1 {
@ -105,4 +109,4 @@
#content #settingsContainer #settingsList input.playback {
background: url('../images/playback.png') no-repeat;
}
}
}

View file

@ -17,6 +17,7 @@
color:#f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #110033, #000000);
background-image: -moz-linear-gradient(to bottom, #110033, #000000);
background-image: -webkit-linear-gradient(top, #110033, #000000);
}
#loginContent #loginButton {
@ -24,6 +25,7 @@
color:#f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #110033, #000000);
background-image: -moz-linear-gradient(to bottom, #110033, #000000);
background-image: -webkit-linear-gradient(top, #110033, #000000);
}
#loginContent input {
@ -133,4 +135,4 @@
#content .cmod {
color: #0033FF;
}*/
}
}

View file

@ -15,7 +15,10 @@ h3 {
font-size: 15px;
padding: 2px;
margin: 10px;
background: linear-gradient(180deg, #900, #600) #700;
background-color: #700;
background-image: linear-gradient(to bottom, #900, #600);
background-image: -moz-linear-gradient(to bottom, #900, #600);
background-image: -webkit-linear-gradient(top, #900, #600);
}
div.copyright {
@ -66,4 +69,4 @@ a {
a:hover {
text-shadow: 0px 0px 1em #F1F1F1;
}
}

View file

@ -14,7 +14,11 @@ body {
margin: 0px;
padding: 0px;
font-family: Verdana, Arial, Helvetica, sans-serif;
background: linear-gradient(180deg, #C2AFFE, #FBEEFF) repeat-x scroll center top #FBEEFF;
background-color: #fbeeff;
background-image: linear-gradient(to bottom, #c2affe, #fbeeff);
background-image: -moz-linear-gradient(to bottom, #c2affe, #fbeeff);
background-image: -webkit-linear-gradient(top, #c2affe, #fbeeff);
background-repeat: repeat-x;
background-size: auto 200px;
text-align: center;
}
@ -23,7 +27,7 @@ img.logo {
height: 150px;
width: 450px;
border: 0px;
background: url('https://static.flash.moe/logos/logo.png') no-repeat scroll left top transparent;
background: url('//static.flash.moe/logos/logo.png') no-repeat scroll left top transparent;
background-size: cover;
}
@ -424,7 +428,7 @@ div.ucp_avatar_cont {
height: 23px;
width: 23px;
border: 0px;
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px 0px transparent;
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px 0px transparent;
}
.maxbutton {
@ -432,7 +436,7 @@ div.ucp_avatar_cont {
height: 23px;
width: 23px;
border: 0px;
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -23px transparent;
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -23px transparent;
}
.minbutton {
@ -440,7 +444,7 @@ div.ucp_avatar_cont {
height: 23px;
width: 23px;
border: 0px;
background: url('https://static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -46px transparent;
background: url('//static.flash.moe/images/window-sprite.png') no-repeat scroll 0px -46px transparent;
}
.donate-btn {
@ -448,7 +452,7 @@ div.ucp_avatar_cont {
height: 26px;
width: 90px;
border: 0px;
background: url('https://static.flash.moe/images/donate-btn.png') no-repeat scroll 0px 0px transparent;
background: url('//static.flash.moe/images/donate-btn.png') no-repeat scroll 0px 0px transparent;
}
div.topLeftBar {
@ -848,4 +852,4 @@ div#recaptcha_image {
}
.news-comments-container {
margin: 5px auto 0px;
}
}

View file

@ -357,6 +357,7 @@
color:#f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #222, #000);
background-image: -moz-linear-gradient(to bottom, #222, #000);
background-image: -webkit-linear-gradient(top, #222, #000);
}
#content select, #loginForm select, #loginForm input, #content textarea {
@ -436,4 +437,4 @@
background-color:#212121;
color:#FFF;
}
}
}

View file

@ -331,6 +331,8 @@
color: #f0f0f0;
border: 1px solid #808080;
background-image: linear-gradient(to bottom, #222, #000);
background-image: -moz-linear-gradient(to bottom, #222, #000);
background-image: -webkit-linear-gradient(top, #222, #000);
}
#content select, #loginForm select, #loginForm input, #content textarea {
background-color: #000;
@ -407,4 +409,4 @@
#content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
background-color: #212121;
color: #FFF;
}
}

View file

@ -15,7 +15,11 @@ html {
}
body {
font: 12px/20px Verdana, sans-serif;
background: linear-gradient(180deg, #C2AFFE, #FBEEFF) no-repeat scroll left top #FBEEFF;
background-color: #fbeeff;
background-repeat: no-repeat;
background-image: linear-gradient(to bottom, #c2affe, #fbeeff);
background-image: -moz-linear-gradient(to bottom, #c2affe, #fbeeff);
background-image: -webkit-linear-gradient(top, #c2affe, #fbeeff);
background-size: cover;
color: #000;
height: 100%;
@ -118,7 +122,7 @@ a.default:active {
}
a.gotop {
display: inline-block;
background: url('https://static.flash.moe/images/arrow.png') #111;
background: url('//static.flash.moe/images/arrow.png') #111;
color: #FFF;
width: 60px;
height: 60px;
@ -192,7 +196,9 @@ a.gotop:active {
/* Site Header Styling */
.header {
text-align: center;
background: linear-gradient(180deg, #C2AFFE, #CCBAFE);
background-image: linear-gradient(to bottom, #c2affe, #ccbafe);
background-image: -moz-linear-gradient(to bottom, #c2affe, #ccbafe);
background-image: -webkit-linear-gradient(top, #c2affe, #ccbafe);
box-shadow: 0 0 5px #8364A1;
}
/*.header .logo {
@ -349,7 +355,10 @@ a.gotop:active {
width: 100%;
padding-top: 10px;
padding-bottom: 30px;
background: linear-gradient(180deg, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%) #C2AFFE;
background-color: #c2affe;
background-image: linear-gradient(to bottom, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
background-image: -moz-linear-gradient(to bottom, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
background-image: -webkit-linear-gradient(top, #9475B2 0%, #FBEEFF 20%, #C2AFFE 100%);
position: absolute;
bottom: 0;
}
@ -537,7 +546,7 @@ a.gotop:active {
font-weight: 700;
font-size: 20px;
color: #306;
background: linear-gradient(90deg, rgba(148,117,178,.7), rgba(148,117,178,0)) #C2AFFE;
background: linear-gradient(90deg, rgba(148,117,178,.7), rgba(148,117,178,0));
border-radius: 2px;
}
.content-right .head,
@ -558,7 +567,10 @@ a.gotop:active {
text-align: center;
border-radius: 5px;
font-weight: 100;
background: linear-gradient(180deg, #874399, #35245E) #874399;
background-color: #874399;
background-image: linear-gradient(to bottom, #874399, #35245E);
background-image: -moz-linear-gradient(to bottom, #874399, #35245E);
background-image: -webkit-linear-gradient(top, #874399, #35245E);
transition: text-shadow .25s;
color: #FFF;
font-size: 16px;
@ -570,7 +582,10 @@ a.gotop:active {
cursor: pointer;
}
.content-right .registerbutton {
background: linear-gradient(180deg, #874399, #35245E) #874399;
background-color: #874399;
background-image: linear-gradient(to bottom, #874399, #35245E);
background-image: -moz-linear-gradient(to bottom, #874399, #35245E);
background-image: -webkit-linear-gradient(top, #874399, #35245E);
}
.button.profileOption {
width: auto !important;

View file

@ -2410,7 +2410,7 @@ var ajaxChat = {
replaceCommandWhois: function(textParts) {
return '<span class="chatBotMessage">'
+ this.lang['whois'].replace(/%s/, textParts[1]) + ' <a target="_blank" href="https://flash.moe/whois/'
+ this.lang['whois'].replace(/%s/, textParts[1]) + ' <a target="_blank" href="//flash.moe/whois/'
+ textParts[2]
+ '">'
+ textParts[2]
@ -3002,4 +3002,4 @@ var ajaxChat = {
return true;
}
}
}

View file

@ -303,7 +303,11 @@ HTML;
function getErrorMessageTags() {
$errorMessages = '';
foreach($this->ajaxChat->getInfoMessages('error') as $error) {
$errorMessages .= '<h3 class="miotitle">'.$this->ajaxChat->htmlEncode($this->ajaxChat->getLang($error)).'</h3>';
$html = $this->ajaxChat->getLang($error);
if($error !== 'errorInvalidUser')
$html = $this->ajaxChat->htmlEncode($html);
$errorMessages .= '<h3 class="miotitle">'.$html.'</h3>';
}
return $errorMessages;
}

View file

@ -9,52 +9,108 @@
namespace AJAXChat;
use Flashii\{FlashiiClient,FlashiiUrls};
use Flashii\Credentials\{BasicCredentials,BearerCredentials,MisuzuCredentials};
class CustomAJAXChat extends AJAXChat {
// Returns an associative array containing userName, userID and userRole
// Returns null if login is invalid
function getValidLoginUserData() {
if(empty($_COOKIE['msz_auth'])) {
header('Location: ' . $this->getConfig('flashiiAuth', 'login'));
exit;
}
$userInfo = SockChatAuth::attempt(
$this->getConfig('flashiiAuth', 'verify'),
$this->getConfig('flashiiSecret'),
(string)filter_input(INPUT_COOKIE, 'msz_auth')
// TODO: this sucks
$urls = new FlashiiUrls(
(fn() => (($url = $this->getConfig('flashiiId', 'api')) === '' ? FlashiiUrls::PROD_API_URL : $url))(),
(fn() => (($url = $this->getConfig('flashiiId', 'id')) === '' ? FlashiiUrls::PROD_ID_URL : $url))()
);
if($userInfo->success) {
// Check if we have a valid registered user:
if(filter_has_var(INPUT_SERVER, 'HTTPS')) {
$authToken = trim((string)filter_input(INPUT_COOKIE, 'msz_auth'));
if($authToken === '') {
header('Location: ' . $this->getConfig('flashiiAuth', 'login'));
exit;
}
$chatUser = [
'userID' => $userInfo->user_id,
'userName' => $userInfo->username,
'userRole' => AJAX_CHAT_GUEST,
];
// sock chat auth doesn't actually return role ids lol
if($userInfo->colour_raw === 0xEE9400)
$chatUser['userRole'] = DONATOR;
elseif($userInfo->colour_raw === 0x0099FF)
$chatUser['userRole'] = CMOD;
elseif($userInfo->colour_raw === 0x7353C4)
$chatUser['userRole'] = PURPLE;
elseif($userInfo->colour_raw === 0x9E8DA7)
$chatUser['userRole'] = BOTS;
elseif($userInfo->rank >= 10)
$chatUser['userRole'] = AJAX_CHAT_ADMIN;
elseif($userInfo->rank >= 5)
$chatUser['userRole'] = AJAX_CHAT_MODERATOR;
elseif($userInfo->rank >= 1)
$chatUser['userRole'] = AJAX_CHAT_USER;
return $chatUser;
$flashii = new FlashiiClient('AJAX Chat', new MisuzuCredentials($authToken), $urls);
} else {
// Guest users:
return $this->getGuestUser();
$flashii = new FlashiiClient('AJAX Chat', new BasicCredentials(
$this->getConfig('flashiiId', 'clientId'),
$this->getConfig('flashiiId', 'clientSecret')
), $urls);
$doPoll = true;
$expiresIn = (int)$this->getSessionVar('fidDeviceExpiresIn');
if($expiresIn < time()) {
$this->regenerateSessionID();
$doPoll = false;
$request = $flashii->oauth2()->requestAuthorize('identify');
if($request instanceof \Flashii\OAuth2\OAuth2AuthorizationRequest) {
$this->setSessionVar('fidDeviceCode', $request->getDeviceCode());
$this->setSessionVar('fidDeviceUserCode', $request->getUserCode());
$this->setSessionVar('fidDeviceExpiresIn', time() + $request->getExpiresIn());
$this->setSessionVar('fidDevicePollInterval', $request->getInterval());
$this->setSessionVar('fidDeviceUri', $request->getVerificationUri());
$this->setSessionVar('fidDeviceUriFull', $request->getVerificationUriComplete());
} else
$this->addInfoMessage('fidAuthzRequestFailed');
}
$deviceCode = $this->getSessionVar('fidDeviceCode');
if(!empty($deviceCode)) {
if($doPoll) {
$token = $flashii->oauth2()->tokenWithDeviceCode($deviceCode);
if($token instanceof \Flashii\OAuth2\OAuth2Token)
$flashii = $flashii->forkWithAccessToken($token->getAccessToken());
else {
if($token->getCode() !== 'slow_down') {
$this->setSessionVar('fidDeviceExpiresIn', 0);
$this->regenerateSessionID();
}
$this->addInfoMessage('fidAuthzTokenFailed');
}
}
$this->getLang(); // load language
$this->_lang['errorInvalidUser'] = sprintf(
$this->_lang['fidPoll'] ?? 'You need to approve the login attempt! If your browser supports HTTPS <a href="%s" target="_blank" rel="noopener">click here</a>, or go to %s on a device that does and enter <code>%s</code> and press the Login button again.',
$this->getSessionVar('fidDeviceUriFull'),
$this->getSessionVar('fidDeviceUri'),
$this->getSessionVar('fidDeviceUserCode')
);
}
}
// Check if we have a valid registered user:
$userInfo = $flashii->v1()->me();
// Guest users:
if($userInfo === null)
return $this->getGuestUser();
$chatUser = [
'userID' => $userInfo->getId(),
'userName' => $userInfo->getName(),
];
if($userInfo->hasRole('admin'))
$chatUser['userRole'] = AJAX_CHAT_ADMIN;
elseif($userInfo->hasRole('gmod'))
$chatUser['userRole'] = AJAX_CHAT_MODERATOR;
elseif($userInfo->hasRole('dev'))
$chatUser['userRole'] = PURPLE;
elseif($userInfo->hasRole('bot'))
$chatUser['userRole'] = BOTS;
elseif($userInfo->hasRole('tenshi'))
$chatUser['userRole'] = DONATOR;
elseif($userInfo->hasRole('og') || $userInfo->getId() === '72')
$chatUser['userRole'] = CMOD; // OGs are blue here i guess lol
elseif($userInfo->getRank() > 0)
$chatUser['userRole'] = AJAX_CHAT_USER;
else
$chatUser['userRole'] = AJAX_CHAT_GUEST;
return $chatUser;
}
// Store the channels the current user has access to

View file

@ -1,52 +0,0 @@
<?php
namespace AJAXChat;
final class SockChatAuth {
public static function attempt(string $endPoint, string $secret, string $cookie): object {
if(!empty($cookie)) {
$method = 'Misuzu';
$signature = sprintf('verify#%s#%s#%s', $method, $cookie, $_SERVER['REMOTE_ADDR']);
$signature = hash_hmac('sha256', $signature, $secret);
$login = curl_init($endPoint);
curl_setopt_array($login, [
CURLOPT_AUTOREFERER => false,
CURLOPT_FAILONERROR => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HEADER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'method' => $method,
'token' => $cookie,
'ipaddr' => $_SERVER['REMOTE_ADDR'],
], '', '&', PHP_QUERY_RFC3986),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TCP_FASTOPEN => true,
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_MAXREDIRS => 2,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_TIMEOUT => 5,
CURLOPT_USERAGENT => 'AJAX Chat',
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'X-SharpChat-Signature: ' . $signature,
],
]);
$userInfo = json_decode(curl_exec($login));
curl_close($login);
}
if(empty($userInfo->success)) {
$userInfo = new stdClass;
$userInfo->success = false;
$userInfo->user_id = 0;
$userInfo->username = 'Anonymous';
$userInfo->colour_raw = 0x40000000;
$userInfo->rank = 0;
$userInfo->hierarchy = 0;
$userInfo->perms = 0;
}
return $userInfo;
}
}

View file

@ -23,7 +23,9 @@
div.toplogo {
font-size: 30px;
background-image: linear-gradient(180deg, #190015/*#2F426C#FF2400*/, transparent);
background-image: linear-gradient(to bottom, #190015/*#2F426C#FF2400*/, transparent);
background-image: -moz-linear-gradient(to bottom, #190015/*#2F426C#FF2400*/, transparent);
background-image: -webkit-linear-gradient(top, #190015/*#2F426C#FF2400*/, transparent);
padding-left: 10px;
padding-right: 10px;
font-family: "Century Gothic", Gothic, sans-serif;
@ -72,11 +74,15 @@
div.topmenu a:hover {
text-shadow: 0px 0px 8px #F1F1F1;
background-image: linear-gradient(to bottom, #8800BB, transparent);
background-image: -moz-linear-gradient(to bottom, #8800BB, transparent);
background-image: -webkit-linear-gradient(top, #8800BB, transparent);
}
div.topmenu a:active {
text-shadow: 0px 0px 8px #0042FF;
background-image: linear-gradient(to bottom, #440077, transparent);
background-image: -moz-linear-gradient(to bottom, #440077, transparent);
background-image: -webkit-linear-gradient(top, #440077, transparent);
}
</style>
[STYLE_SHEETS/]