From d94e83b4686a14052c172fc2379622025b7191d4 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Wed, 18 Mar 2020 11:00:57 +0100 Subject: [PATCH] Making grants and authentication now possible. --- .vscode/launch.json | 2 +- locales/en.json | 4 +- src/api/oauth/auth.ts | 247 +++++++++++++++++++++++------------------- 3 files changed, 141 insertions(+), 112 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index cc4f503..d5c9108 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "type": "node", + "type": "pwa-node", "request": "launch", "name": "Launch Program", "program": "${workspaceFolder}/lib/index.js", diff --git a/locales/en.json b/locales/en.json index 407cc36..71c3f86 100644 --- a/locales/en.json +++ b/locales/en.json @@ -11,5 +11,7 @@ "Special token invalid": "Special token invalid", "You are not logged in or your login is expired(Special token invalid)": "You are not logged in or your login is expired(Special token invalid)", "No login token": "No login token", - "Login token invalid": "Login token invalid" + "Login token invalid": "Login token invalid", + "Authorize %s": "Authorize %s", + "By clicking on ALLOW, you allow this app to access the requested recources.": "By clicking on ALLOW, you allow this app to access the requested recources." } \ No newline at end of file diff --git a/src/api/oauth/auth.ts b/src/api/oauth/auth.ts index e5dce2c..22f86ba 100644 --- a/src/api/oauth/auth.ts +++ b/src/api/oauth/auth.ts @@ -84,128 +84,155 @@ import GetAuthPage from "../../views/authorize"; // } // }) -const GetAuthRoute = (view = false) => Stacker(GetUserMiddleware(false), async (req: Request, res: Response) => { - let { response_type, client_id, redirect_uri, scope, state, nored } = req.query; - const sendError = (type) => { - if (redirect_uri === "$local") - redirect_uri = "/code"; - res.redirect(redirect_uri += `?error=${type}&state=${state}`); - } +const GetAuthRoute = (view = false) => + Stacker(GetUserMiddleware(false), async (req: Request, res: Response) => { + let { + response_type, + client_id, + redirect_uri, + scope, + state, + nored + } = req.query; + const sendError = type => { + if (redirect_uri === "$local") redirect_uri = "/code"; + res.redirect((redirect_uri += `?error=${type}&state=${state}`)); + }; - const scopes = scope.split(";"); + const scopes = scope.split(";"); - Logging.debug("Scopes:", scope); + Logging.debug("Scopes:", scope); - try { - if (response_type !== "code") { - return sendError("unsupported_response_type"); - } else { + try { + if (response_type !== "code") { + return sendError("unsupported_response_type"); + } else { + let client = await Client.findOne({ client_id: client_id }); + if (!client) { + return sendError("unauthorized_client"); + } - let client = await Client.findOne({ client_id: client_id }); - if (!client) { - return sendError("unauthorized_client"); - } - - if (redirect_uri && client.redirect_url !== redirect_uri) { - Logging.log(redirect_uri, client.redirect_url); - return res.send("Invalid redirect_uri. Please check the integrity of the site requesting and contact the administrator of the page, you want to authorize!"); - } - - let permissions: IPermission[] = []; - let proms: PromiseLike[] = []; - if (scopes) { - for (let perm of scopes.filter(e => e !== "read_user")) { - proms.push( - Permission.findById(perm).then(p => { - if (!p) return Promise.reject(new Error()); - permissions.push(p); - }) + if (redirect_uri && client.redirect_url !== redirect_uri) { + Logging.log(redirect_uri, client.redirect_url); + return res.send( + "Invalid redirect_uri. Please check the integrity of the site requesting and contact the administrator of the page, you want to authorize!" ); } - } - let err = undefined; - await Promise.all(proms).catch(e => { - err = e; - }); - - if (err) { - Logging.error(err); - return sendError("invalid_scope"); - } - - let grant: IGrant | undefined = await Grant.findOne({ - client: client._id, - user: req.user._id - }) - - Logging.debug("Grant", grant, permissions); - - let missing_permissions: IPermission[] = []; - - if (grant) { - missing_permissions = grant.permissions.map(perm => permissions.find(p => p._id.equals(perm))).filter(e => !!e); - } else { - missing_permissions = permissions; - } - - let client_granted_perm = missing_permissions.filter(e => e.grant_type == "client") - if (client_granted_perm.length > 0) { - return sendError("no_permission") - } - - if (grant && missing_permissions.length > 0) { - await new Promise((yes, no) => GetUserMiddleware(false, true)(req, res, (err?: Error) => err ? no(err) : yes())); // Maybe unresolved when redirect is happening - - if (view) { - res.send(GetAuthPage(req.__, client.name, permissions.map(perm => { - return { - name: perm.name, - description: perm.description, - logo: client.logo - } - }))); - return; - } else { - if (req.body.allow = "true") { - if (!grant) - grant = Grant.new({ - client: client._id, - user: req.user._id, - permissions: [] - }); - - grant.permissions.push(...missing_permissions.map(e => e._id)); - await Grant.save(grant); - } else { - return sendError("access_denied"); + let permissions: IPermission[] = []; + let proms: PromiseLike[] = []; + if (scopes) { + for (let perm of scopes.filter(e => e !== "read_user")) { + proms.push( + Permission.findById(perm).then(p => { + if (!p) return Promise.reject(new Error()); + permissions.push(p); + }) + ); } } - } - let code = ClientCode.new({ - user: req.user._id, - client: client._id, - permissions: permissions.map(p => p._id), - validTill: moment().add(30, "minutes").toDate(), - code: randomBytes(16).toString("hex") - }); - await ClientCode.save(code); + let err = undefined; + await Promise.all(proms).catch(e => { + err = e; + }); - let redir = client.redirect_url === "$local" ? "/code" : client.redirect_url; - let ruri = redir + `?code=${code.code}&state=${state}`; - if (nored === "true") { - res.json({ - redirect_uri: ruri - }) - } else { - res.redirect(ruri); + if (err) { + Logging.error(err); + return sendError("invalid_scope"); + } + + let grant: IGrant | undefined = await Grant.findOne({ + client: client._id, + user: req.user._id + }); + + Logging.debug("Grant", grant, permissions); + + let missing_permissions: IPermission[] = []; + + if (grant) { + missing_permissions = grant.permissions + .map(perm => permissions.find(p => p._id.equals(perm))) + .filter(e => !!e); + } else { + missing_permissions = permissions; + } + + let client_granted_perm = missing_permissions.filter( + e => e.grant_type == "client" + ); + if (client_granted_perm.length > 0) { + return sendError("no_permission"); + } + + if (!grant && missing_permissions.length > 0) { + await new Promise((yes, no) => + GetUserMiddleware(false, true)(req, res, (err?: Error) => + err ? no(err) : yes() + ) + ); // Maybe unresolved when redirect is happening + + if (view) { + res.send( + GetAuthPage( + req.__, + client.name, + permissions.map(perm => { + return { + name: perm.name, + description: perm.description, + logo: client.logo + }; + }) + ) + ); + return; + } else { + if ((req.body.allow = "true")) { + if (!grant) + grant = Grant.new({ + client: client._id, + user: req.user._id, + permissions: [] + }); + + grant.permissions.push( + ...missing_permissions.map(e => e._id) + ); + await Grant.save(grant); + } else { + return sendError("access_denied"); + } + } + } + + let code = ClientCode.new({ + user: req.user._id, + client: client._id, + permissions: permissions.map(p => p._id), + validTill: moment() + .add(30, "minutes") + .toDate(), + code: randomBytes(16).toString("hex") + }); + await ClientCode.save(code); + + let redir = + client.redirect_url === "$local" ? "/code" : client.redirect_url; + let ruri = redir + `?code=${code.code}&state=${state}`; + if (nored === "true") { + res.json({ + redirect_uri: ruri + }); + } else { + res.redirect(ruri); + } } + } catch (err) { + Logging.error(err); + sendError("server_error"); } - } catch (err) { - Logging.error(err); - sendError("server_error") - } -}); + }); export default GetAuthRoute;