@opengis/fastify-table
Version:
core-plugins
91 lines (90 loc) • 3.67 kB
JavaScript
import { verify, scryptVerify } from "../../../../plugins/auth/funcs/jwt.js";
import pgClients from "../../../../plugins/pg/pgClients.js";
import authorizeUser from "../../../../plugins/auth/funcs/authorizeUser.js";
const expireMsec = 1000 * 60 * 60;
const getIp = (req) => (req.headers?.["x-real-ip"] ||
req.headers?.["x-forwarded-for"] ||
req.ip ||
req.connection?.remoteAddress ||
"")
.split(":")
.pop();
export default async function oauthToken(req, reply) {
const { pg = pgClients.client, query, body } = req;
const payload = req.method === "POST" ? body : query;
const { grant_type, client_id, code, redirect_uri, code_verifier } = payload;
if (grant_type !== "authorization_code") {
return reply.code(400).send({ error: "unsupported grant_type", code: 400 });
}
if (!client_id) {
return reply
.code(400)
.send({ error: "not enough params: client_id", code: 400 });
}
if (!code) {
return reply
.code(400)
.send({ error: "not enough params: code", code: 400 });
}
const q = `select owner_user_id, client_secret_hash, redirect_uris from oauth.clients where client_id=$1 and token_endpoint_auth_method=$2`;
const { owner_user_id: userId, client_secret_hash: secret, redirect_uris = [], } = pg.pk?.["oauth.clients"]
? await pg
.query(q, [client_id, "private_key_jwt"])
.then((el) => el.rows?.[0] || {})
: {};
const isCodeValid = verify(code, secret);
const q1 = "select token_hash, expires_at, ip from oauth.tokens where client_id=$1 and revoked_at is null and expires_at > now()";
const { token_hash: stored, expires_at, ip: storedIp, } = await pg.query(q1, [client_id]).then((el) => el.rows?.[0] || {});
const ip = getIp(req);
if (storedIp !== ip) {
return reply
.code(403)
.send({ error: "access restricted: wrong IP address", code: 403 });
}
if (!stored) {
return reply
.code(403)
.send({ error: "access restricted: code expired", code: 403 });
}
const isValid = await scryptVerify(stored, code);
if (!isValid) {
return reply
.code(403)
.send({ error: "access restricted: stored code mismatch", code: 403 });
}
if (!isCodeValid) {
return reply
.code(403)
.send({ error: "access restricted: invalid code", code: 403 });
}
if (!userId) {
return reply.code(400).send({ error: "invalid client id", code: 400 });
}
if (redirect_uri &&
Array.isArray(redirect_uris) &&
!redirect_uris.includes(redirect_uri)) {
return reply.code(400).send({ error: "invalid redirect_uri", code: 400 });
}
const user = pg.pk?.["admin.users"]
? await pg
.query("select * from admin.users where uid=$1 and enabled limit 1", [
userId,
])
.then((el) => el.rows[0])
: null;
if (!user) {
return reply.code(404).send({ error: "user not found", code: 404 });
}
const expire = expires_at ? expires_at - Date.now() : expireMsec;
const href1 = await authorizeUser(user, req, "jwt", expire);
const backUrl = redirect_uri ? `${redirect_uri}?code=${code}` : "";
const href = redirect_uri && !redirect_uri.includes("?")
? backUrl
: backUrl?.replace?.(/\?code=/, "&code=") || href1;
if (req.method === "POST" ||
payload.noredirect ||
process.env.NODE_ENV === "test") {
return reply.code(200).send("auth success");
}
return reply.redirect(href);
}