UNPKG

@opengis/fastify-table

Version:

core-plugins

94 lines (93 loc) 3.9 kB
import pgClients from "../../../../plugins/pg/pgClients.js"; import dataInsert from "../../../../plugins/crud/funcs/dataInsert.js"; import { sign, scryptHash } from "../../../../plugins/auth/funcs/jwt.js"; import authorizeUser from "../../../../plugins/auth/funcs/authorizeUser.js"; const getIp = (req) => (req.headers?.["x-real-ip"] || req.headers?.["x-forwarded-for"] || req.ip || req.connection?.remoteAddress || "") .split(":") .pop(); const expireMsec = 1000 * 60 * 60; // ? Request example: http://localhost:3000/oauth/authorize?response_type=code&client_id=2835134164020233999&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth%2Ftoken%3Fclient_id%3D2835134164020233999%26noredirect%3D1%26grant_type%3Dauthorization_code // ? add &noredirect=1 to retrieve code via GET request or simply send POST requests export default async function authorize(req, reply) { const { pg = pgClients.client, query, body } = req; const payload = req.method === "POST" ? body : query; const { response_type, client_id, redirect_uri, scope } = payload; if (response_type !== "code") { return reply .code(400) .send({ error: "unsupported response_type", code: 400 }); } if (!client_id) { return reply .code(400) .send({ error: "not enough query params: client_id", 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 and ${scope ? "$1=any(scopes)" : "1=1"}`; 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] || {}) : {}; 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 href1 = await authorizeUser(user, req, "jwt", expireMsec); // Generate authorization code const code = sign(userId, secret, expireMsec); const tokenHash = await scryptHash(code); const ip = getIp(req); // disable access via old tokens if (pg.pk?.["oauth.tokens"]) { await pg.query("update oauth.tokens set revoked_at = now(), revocation_reason='refresh' where client_id=$1", [client_id]); } await dataInsert({ pg, table: "oauth.tokens", data: { token_type: "access", token_hash: tokenHash, token_hint: code.slice(-6), // jti: undefined, client_id, user_id: userId, // issuer: undefined, scopes: [scope].filter(Boolean), // claims: undefined, issued_at: new Date(), expires_at: new Date(Date.now() + expireMsec), // revoked_at: undefined, // revocation_reason: undefined, ip, }, uid: userId, }); 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(code); } return reply.redirect(href); }