Skip to content

Commit

Permalink
feat(qol): add redirect post login if invalid sess
Browse files Browse the repository at this point in the history
  • Loading branch information
tabarra committed Jan 23, 2023
1 parent 1e91468 commit 852f1a9
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 71 deletions.
8 changes: 6 additions & 2 deletions core/components/WebServer/requestAuthenticator.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const requestAuth = (epType) => {
if (epType === 'api') {
const sessToken = ctx.session?.auth?.csrfToken;
const headerToken = ctx.headers['x-txadmin-csrftoken'];
if(sessToken && (sessToken !== headerToken)){
if (sessToken && (sessToken !== headerToken)) {
//DEBUG
// ogConsole.dir({
// route: `${ctx.method} ${ctx.path}`,
Expand All @@ -51,7 +51,11 @@ export const requestAuth = (epType) => {
if (verbose) logWarn(`Invalid session auth: ${ctx.path}`, epType);
ctx.session.auth = {};
if (epType === 'web') {
return ctx.response.redirect('/auth?logout');
if (ctx.method === 'GET' && ctx.path !== '/') {
return ctx.response.redirect(`/auth?logout&r=${encodeURIComponent(ctx.path)}`);
} else {
return ctx.response.redirect(`/auth?logout`);
}
} else if (epType === 'api') {
return ctx.send({ logout: true });
} else if (epType === 'nuiStart') {
Expand Down
8 changes: 8 additions & 0 deletions core/extras/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,11 @@ export type PlayerIdsObjectType = {
steam: string | null;
xbl: string | null;
};


/**
* Validates if a redirect path is valid or not.
* To prevent open redirect, we need to make sure the first char is / and the second is not,
* otherwise //example.com would be a valid redirect to <proto>://example.com
*/
export const isValidRedirectPath = (redirPath: unknown) => typeof redirPath === 'string' && /^\/\w/.test(redirPath);
4 changes: 3 additions & 1 deletion core/webroutes/authentication/providerCallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const modulename = 'WebServer:ProviderCallback';
import crypto from 'node:crypto';
import logger, { ogConsole } from '@core/extras/console.js';
import { verbose } from '@core/globalData';
import { isValidRedirectPath } from '@core/extras/helpers';
const { dir, log, logOk, logWarn, logError } = logger(modulename);

//Helper functions
Expand Down Expand Up @@ -122,7 +123,8 @@ export default async function ProviderCallback(ctx) {
ctx.utils.logAction(`logged in from ${ctx.ip} via citizenfx`);
globals.databus.txStatsData.login.origins[ctx.txVars.hostType]++;
globals.databus.txStatsData.login.methods.citizenfx++;
return ctx.response.redirect('/');
const redirectPath = (isValidRedirectPath(ctx.session?.socialLoginRedirect)) ? ctx.session.socialLoginRedirect : '/';
return ctx.response.redirect(redirectPath);
} catch (error) {
ctx.session.auth = {};
if (verbose) logError(`Failed to login: ${error.message}`);
Expand Down
15 changes: 10 additions & 5 deletions core/webroutes/authentication/providerRedirect.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
const modulename = 'WebServer:ProviderRedirect';
import logger from '@core/extras/console.js';
import { isValidRedirectPath } from '@core/extras/helpers';
import { verbose } from '@core/globalData';
const { dir, log, logOk, logWarn, logError } = logger(modulename);

//Helper functions
const isUndefined = (x) => { return (typeof x === 'undefined'); };
const genCallbackURL = (ctx, provider) => {
return ctx.protocol + '://' + ctx.get('host') + `/auth/${provider}/callback`;
};
const returnJustMessage = (ctx, errorTitle, errorMessage) => {
return ctx.utils.render('login', { template: 'justMessage', errorTitle, errorMessage });
};
Expand All @@ -30,10 +28,17 @@ export default async function ProviderRedirect(ctx) {
//Make sure the session is initialized
ctx.session.startedSocialLogin = Date.now();

//Generatte CitizenFX provider Auth URL
//Save redirection path in session, if any
//NOTE: technically we don't need to regex validate here, as that will be done on providerCallback
if(isValidRedirectPath(ctx.query?.r)){
ctx.session.socialLoginRedirect = ctx.query.r;
}

//Generate CitizenFX provider Auth URL
const callbackUrl = ctx.protocol + '://' + ctx.get('host') + `/auth/citizenfx/callback`;
try {
const urlCitizenFX = await globals.adminVault.providers.citizenfx.getAuthURL(
genCallbackURL(ctx, 'citizenfx'),
callbackUrl,
ctx.session._sessCtx.externalKey,
);
return ctx.response.redirect(urlCitizenFX);
Expand Down
4 changes: 3 additions & 1 deletion core/webroutes/authentication/verifyPassword.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const modulename = 'WebServer:AuthVerify';
import logger from '@core/extras/console.js';
import { isValidRedirectPath } from '@core/extras/helpers';
import { verbose } from '@core/globalData';
const { dir, log, logOk, logWarn, logError } = logger(modulename);

Expand Down Expand Up @@ -54,5 +55,6 @@ export default async function AuthVerify(ctx) {
return ctx.utils.render('login', renderData);
}

return ctx.response.redirect('/');
const redirectPath = (isValidRedirectPath(ctx.query?.r)) ? ctx.query.r : '/';
return ctx.response.redirect(redirectPath);
};
95 changes: 36 additions & 59 deletions docs/dev_notes.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,42 @@
# TODO:
- [x] rename txAdmin Logs to System Logs (check chungus commands as well)
- [x] Finish diagnostics report function
- [x] Make cyclical exec in cfg file block the server start
- [x] change nui player card default tab back to actions
- [x] upgrade packages
- [x] bot: upgrade discord.js
- [x] bot: convert into slash commands
- [x] bot: add NEW tag to settings menu and discord tab
- [x] bot: add dynamic activity ("watching xx/yy players")
- [x] bot: add persistent /status message
- [x] bot: embed/config editor on settings page
- [x] bot: embed/config docs file
- [x] bot: fix resolveMember()
- [x] bot: add /whitelist command
- [x] bot: add /info command
- [x] add new whitelist modes
- [x] admin-only (#516)
- [x] guild membership (#450)
- [x] guild roles
- [x] bot: update AGAIN to djs v14
- [x] fix `Restarting the fxserver with delay override 0.`
- [x] add cap to `stats_heatmapData_v1.json` (StatsCollector.hardConfigs.performance.lengthCap)
- [x] chore(core): move admin action log() to logger
- [x] Improve the message `[txAdmin] You do not have at least 1 valid identifier [...]`
- [x] CFG Editor: add hotkeys for search, comment, and restart sv
- [x] add a `Wait(0)` on `sv_main.lua` kick/ban handlers? (Issue #639)
- [x] merge translations
- [x] remove `discord.*` from locale files
- [x] adjust the message that shows when deployer step 3 has no server.cfg to read
- [x] set nui/vite.config.ts > target > chrome103
- [x] checkJoin: add messages to locale files
- [x] checkJoin: customMessage `\n` to `<br>`
- [x] fix(core): cfx.re login match by admin id instead of name
- [x] finish txdiagnostics backend, test e2e one last time
- [x] bot: change settings page description





# Next up:
- [x] QoL: add redirect post login if invalid sess
- [ ] Improve discord embed UX:
- [x] embed placeholder
- [x] check for the emoji
- [x] check for the url fields
- [ ] discord auth not admin response
- [ ] bot save: intent message
- [ ] bot save: could not resolve guild id = was the bot invited?
- [ ] embed jsons reset buttons
- [ ] status embed every 30 seconds or reactive to status changes
- [ ] add superjump
- [ ] the PR about hiding notifications
- [ ] wav for announcements
- [ ] create events for dynamic scheduled restarts
- [ ] create new whitelist events
- [ ] whitelistPlayer:
- license: xxxxx
- author: admin name
- status: true/false
- [ ] whitelistPreApproval:
- action: added/removed
- identifier: `discord:xxxxxx` / `license:xxxxx`
- author: admin name
- [ ] whitelistRequest:
- action: requested/approved/denied
- author: either player name, or admin name
- requestId: Rxxxx
- license: xxxxxx
- [ ] At the schedule restart input prompt, add a note saying what is the current server time


## Optional
- [ ] bot: fix http agent options for localAddress
- [ ] bot: add rate limit events to diagnostics page
- [ ] change dashboard median player message
- top 1000: "your server seems to be in top 1000, join and type /server to track your progress"
- top 500: "you might be in top 500, join discord and see if you are eligible for the role"
- [ ] update readme with new features
- [ ] update readme with new features and contributing warning
- [ ] stats:
- [ ] ????
- [ ] jwe
Expand All @@ -65,12 +53,17 @@ CreateThread(function()
end)
```


# Next up:
- [ ] xxxxxx

===================
### MUI update
5.10.17 ok
5.11.0 broken
To test it, remove the `^`
rm -rf node_modules/; npm i; npm list @mui/material; npm run dev:menu:game
https://github.com/mui/material-ui/blob/master/CHANGELOG.md
===================


Expand All @@ -97,23 +90,7 @@ teste:

- [ ] no duplicated id type in bans? preparing for the new db migration
- [ ] reorder `sv_main.lua` and add `local` prefix to most if not all functions
- [ ] create events for dynamic scheduled restarts
- [ ] create new whitelist events
- [ ] whitelistPlayer:
- license: xxxxx
- author: admin name
- status: true/false
- [ ] whitelistPreApproval:
- action: added/removed
- identifier: `discord:xxxxxx` / `license:xxxxx`
- author: admin name
- [ ] whitelistRequest:
- action: requested/approved/denied
- author: either player name, or admin name
- requestId: Rxxxx
- license: xxxxxx
- [ ] mock out insights page (assets + http reqs)
- [ ] At the schedule restart input prompt, add a note saying what is the current server time
- [ ] `cfg cyclical 'exec' command detected to file` should be blocking instead of warning. Behare that this is not trivial without also turning missing exec target read error also being error
- [ ] maybe some sort of lockfile to admins.json file which would disable admin manager?

Expand Down Expand Up @@ -513,7 +490,7 @@ To check of admin perm, just do `IsPlayerAceAllowed(src, 'txadmin.xxxxxx')`


### txPointing (old txBanana)
- code prototype with ItsANoBrainer#1337
- code prototype with ItsANoBrainer#1337 (https://github.com/tabarra/txBanana)
- keybind to toggle gun (grab or put away)
- when you point at player, show above head some info
- when you "shoot" it will open the player menu and hopefully fire a laser or something
Expand Down
2 changes: 1 addition & 1 deletion web/public/js/txadmin/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ for (let pfp of pfpList) {
//================================================================
const checkApiLogoutRefresh = (data) => {
if (data.logout === true) {
window.location = '/auth?logout';
window.location = `/auth?logout&r=${encodeURIComponent(window.location.pathname)}`;
return true;
} else if (data.refresh === true) {
window.location.reload(true);
Expand Down
16 changes: 14 additions & 2 deletions web/standalone/login.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@
<h1 class="mb-3">Login</h1>
<% if (isWebInterface) { %>
<a class="btn cfxrebtn<%= citizenfxDisabled ? ' disabled' : '' %>"
role="button" href="auth/citizenfx/redirect">
role="button" href="auth/citizenfx/redirect" id="btn-cfxredirect">
<i class="cfxrelogo"><svg><use href="#cfxre-icon"></use></svg></i>
</a>
<% } else { %>
Expand All @@ -293,7 +293,7 @@
<div class="hrsep">OR</div>
<form action="auth/password" method="post">
<form action="auth/password" id="form-password" method="post">
<div class="input-group mb-2 mx-auto" style="max-width: 280px;">
<div class="input-group-prepend">
<span class="input-group-text">
Expand Down Expand Up @@ -387,6 +387,18 @@
<script src="<%= resourcePath %>js/coreui.bundle.min.js"></script>
<script src="<%= resourcePath %>js/txadmin/base.js"></script>
<script>
const searchParams = new URLSearchParams(window.location.search);
const encodedRedirectTarget = encodeURIComponent(searchParams.get('r'));
if(encodedRedirectTarget){
const passwordForm = document.getElementById('form-password');
if(passwordForm){
passwordForm.action = `${passwordForm.action}?r=${encodedRedirectTarget}`;
}
const cfxRedirectButton = document.getElementById('btn-cfxredirect');
if(cfxRedirectButton){
cfxRedirectButton.href = `${cfxRedirectButton.href}?r=${encodedRedirectTarget}`;
}
}
window.history.pushState(null, 'txAdmin', '/auth');
</script>
</body>
Expand Down

0 comments on commit 852f1a9

Please sign in to comment.