UNPKG

@opengis/fastify-table

Version:

core-plugins

91 lines (90 loc) 3.67 kB
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); }