Implementing basic auth_grant
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import { Request, Response, Router } from "express"
|
||||
import Stacker from "../middlewares/stacker";
|
||||
import { GetClientAuthMiddleware } from "../middlewares/client";
|
||||
import { GetClientAuthMiddleware, GetClientApiAuthMiddleware } from "../middlewares/client";
|
||||
import { GetUserMiddleware } from "../middlewares/user";
|
||||
import { createJWT } from "../../keys";
|
||||
import Client from "../../models/client";
|
||||
@ -44,4 +44,13 @@ ClientRouter.get("/user", Stacker(GetClientAuthMiddleware(false), GetUserMiddlew
|
||||
res.redirect(redirect_uri + "?jwt=" + jwt + (state ? `&state=${state}` : ""));
|
||||
}));
|
||||
|
||||
export default ClientRouter;
|
||||
ClientRouter.get("/account", Stacker(GetClientApiAuthMiddleware(), async (req: Request, res) => {
|
||||
res.json({
|
||||
user: {
|
||||
username: req.user.username,
|
||||
name: req.user.name,
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
export default ClientRouter;
|
||||
|
@ -7,38 +7,103 @@ import Permission, { IPermission } from "../../models/permissions";
|
||||
import ClientCode from "../../models/client_code";
|
||||
import moment = require("moment");
|
||||
import { randomBytes } from "crypto";
|
||||
import { ObjectID } from "bson";
|
||||
// import { ObjectID } from "bson";
|
||||
import Grant, { IGrant } from "../../models/grants";
|
||||
import GetAuthPage from "../../views/authorize";
|
||||
|
||||
const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => {
|
||||
// const AuthRoute = Stacker(GetUserMiddleware(true), 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}`);
|
||||
// }
|
||||
// /**
|
||||
// * error
|
||||
// REQUIRED. A single ASCII [USASCII] error code from the
|
||||
// following:
|
||||
// invalid_request
|
||||
// The request is missing a required parameter, includes an
|
||||
// invalid parameter value, includes a parameter more than
|
||||
// once, or is otherwise malformed.
|
||||
// unauthorized_client
|
||||
// The client is not authorized to request an authorization
|
||||
// code using this method.
|
||||
// access_denied
|
||||
// The resource owner or authorization server denied the
|
||||
// request.
|
||||
// */
|
||||
// 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")
|
||||
// }
|
||||
|
||||
// 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[] = [];
|
||||
// if (scope) {
|
||||
// let perms = (<string>scope).split(";").filter(e => e !== "read_user").map(p => new ObjectID(p));
|
||||
// permissions = await Permission.find({ _id: { $in: perms } })
|
||||
|
||||
// if (permissions.length != perms.length) {
|
||||
// return sendError("invalid_scope");
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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")
|
||||
// }
|
||||
// })
|
||||
|
||||
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}`);
|
||||
}
|
||||
/**
|
||||
* error
|
||||
REQUIRED. A single ASCII [USASCII] error code from the
|
||||
following:
|
||||
invalid_request
|
||||
The request is missing a required parameter, includes an
|
||||
invalid parameter value, includes a parameter more than
|
||||
once, or is otherwise malformed.
|
||||
unauthorized_client
|
||||
The client is not authorized to request an authorization
|
||||
code using this method.
|
||||
access_denied
|
||||
The resource owner or authorization server denied the
|
||||
request.
|
||||
*/
|
||||
try {
|
||||
|
||||
const scopes = scope.split(";");
|
||||
|
||||
Logging.debug("Scopes:", scope);
|
||||
|
||||
try {
|
||||
if (response_type !== "code") {
|
||||
return sendError("unsupported_response_type");
|
||||
} else {
|
||||
let client = await Client.findOne({ client_id: client_id })
|
||||
|
||||
let client = await Client.findOne({ client_id: client_id });
|
||||
if (!client) {
|
||||
return sendError("unauthorized_client")
|
||||
return sendError("unauthorized_client");
|
||||
}
|
||||
|
||||
if (redirect_uri && client.redirect_url !== redirect_uri) {
|
||||
@ -47,12 +112,74 @@ const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Res
|
||||
}
|
||||
|
||||
let permissions: IPermission[] = [];
|
||||
if (scope) {
|
||||
let perms = (<string>scope).split(";").filter(e => e !== "read_user").map(p => new ObjectID(p));
|
||||
permissions = await Permission.find({ _id: { $in: perms } })
|
||||
let proms: PromiseLike<void>[] = [];
|
||||
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 (permissions.length != perms.length) {
|
||||
return sendError("invalid_scope");
|
||||
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<void>((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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +193,6 @@ const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Res
|
||||
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({
|
||||
@ -80,5 +206,6 @@ const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Res
|
||||
Logging.error(err);
|
||||
sendError("server_error")
|
||||
}
|
||||
})
|
||||
export default AuthRoute;
|
||||
});
|
||||
|
||||
export default GetAuthRoute;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import AuthRoute from "./auth";
|
||||
import GetAuthRoute from "./auth";
|
||||
import JWTRoute from "./jwt";
|
||||
import Public from "./public";
|
||||
import RefreshTokenRoute from "./refresh";
|
||||
@ -19,7 +19,7 @@ const OAuthRoue: Router = Router();
|
||||
* @apiParam {String} state State, that will be passed to redirect_uri for client
|
||||
* @apiParam {String} nored Deactivates the Redirect response from server and instead returns the redirect URI in JSON response
|
||||
*/
|
||||
OAuthRoue.post("/auth", AuthRoute);
|
||||
OAuthRoue.post("/auth", GetAuthRoute(false));
|
||||
|
||||
/**
|
||||
* @api {get} /oauth/jwt
|
||||
@ -60,4 +60,4 @@ OAuthRoue.get("/refresh", RefreshTokenRoute);
|
||||
* @apiGroup oauth
|
||||
*/
|
||||
OAuthRoue.post("/refresh", RefreshTokenRoute);
|
||||
export default OAuthRoue;
|
||||
export default OAuthRoue;
|
||||
|
Reference in New Issue
Block a user