brainz-social-old/routes/oauth/authorize.js

83 lines
5 KiB
JavaScript

const crypto = require("crypto");
const qs = require("qs");
const databaseHandler = require("../../lib/database-handler");
const input_validate = require("../../lib/input_validate");
module.exports = {
route: (routeObj) => {
routeObj.get((req, res) => {
const validation_result = input_validate.validate_exists(req.query, ["response_type", "client_id", "redirect_uri"]);
if (validation_result !== true) {
res.status(422);
res.send(`<html><body>Someone done goof'ed with your oauth request.<br />${validation_result.error}</body></html>`);
res.end();
return;
}
if (!req.cookies || !req.cookies.auth) {
const new_redirect_url = new URL("https://example.com");
new_redirect_url.host = req.headers.host;
new_redirect_url.pathname = req.path;
new_redirect_url.search = qs.stringify(req.query);
const redirecting_to = new URL("https://example.com");
redirecting_to.host = req.headers.host;
redirecting_to.pathname = "/login";
redirecting_to.searchParams.set("redirect_to", new_redirect_url.toString());
res.status(302);
res.redirect(redirecting_to.toString());
res.end();
} else {
const cookie_db = databaseHandler.checkAuthCookie(req.cookies.auth);
if (cookie_db != null && !cookie_db.revoked && (cookie_db.created_at + 86400) > Math.floor(Date.now() / 1000)) {
const new_cookie_value = crypto.randomBytes(32).toString("base64");
databaseHandler.revokeAuthCookie(req.cookies.auth);
databaseHandler.createAuthCookie(new_cookie_value, Math.floor(Date.now() / 1000), cookie_db.user_id);
const application_obj = databaseHandler.application[req.query.client_id];
let scope = "read";
if (req.query.scope) {
scope = req.query.scope;
}
if (!input_validate.validate_appropriate_scopes(application_obj.scopes, scope)) {
res.status(422);
res.cookie("auth", new_cookie_value);
// TODO: XSS
res.send(`<html><body>Error: invalid scopes requested. Contact the author of ${application_obj.client_name} to correct their scope request.</body></html>`);
res.end();
return;
}
res.status(200);
res.cookie("auth", new_cookie_value);
const approve_url = new URL("https://example.com");
approve_url.host = req.headers.host;
approve_url.pathname = "/oauth/authorize/yes";
approve_url.searchParams.set("response_type", req.query.response_type);
approve_url.searchParams.set("client_id", req.query.client_id);
approve_url.searchParams.set("redirect_uri", req.query.redirect_uri);
approve_url.searchParams.set("scope", scope);
const approve_csrf = crypto.randomBytes(32).toString("base64");
approve_url.searchParams.set("csrf_token", approve_csrf);
const deny_url = new URL(approve_url);
deny_url.pathname = "/oauth/authorize/no";
const deny_csrf = crypto.randomBytes(32).toString("base64");
deny_url.searchParams.set("csrf_token", deny_csrf);
const approve_csrf_id = databaseHandler.createCsrfToken(approve_url.toString(), Math.floor(Date.now() / 1000), new_cookie_value);
const deny_csrf_id = databaseHandler.createCsrfToken(deny_url.toString(), Math.floor(Date.now() / 1000), new_cookie_value);
databaseHandler.createCsrfTokenAssociation(approve_csrf_id, deny_csrf_id);
res.send(`<html><body>The ${application_obj.client_name} application has requested the following scopes:<br /><ul><li>${scope.split(/(\s|\+)+/).join("</li><li>")}</li></ul><br /><a href="${approve_url.toString()}" >Approve</a><br /><a href="${deny_url.toString()}" >Deny</a></body></html>`);
res.end();
return;
}
const new_redirect_url = new URL("https://example.com");
new_redirect_url.host = req.headers.host;
new_redirect_url.pathname = req.path;
new_redirect_url.search = qs.stringify(req.query);
const redirecting_to = new URL("https://example.com");
redirecting_to.host = req.headers.host;
redirecting_to.pathname = "/login";
redirecting_to.searchParams.set("redirect_to", new_redirect_url.toString());
res.status(302);
res.redirect(redirecting_to.toString());
res.end();
}
});
},
};