From e8c278aa41ce41b5434c8db357b9ef1a53682033 Mon Sep 17 00:00:00 2001 From: Alvar San Martin Date: Tue, 27 Jan 2026 12:12:40 +0100 Subject: [PATCH] Firma de tokens jwt propios para las solicitues --- packages/shared/domain/JWT.ts | 47 ++++++++++++++ packages/sim-consumidor-activaciones/.env | 1 + .../aplication/JWT.service.test.ts | 5 +- .../aplication/JWT.service.ts | 62 +++++++++++++++++-- .../config/env/index.ts | 4 +- .../sim-consumidor-activaciones/mykey.pub | 6 ++ packages/sim-consumidor-activaciones/obj.pub | 9 +++ 7 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 packages/sim-consumidor-activaciones/mykey.pub create mode 100644 packages/sim-consumidor-activaciones/obj.pub diff --git a/packages/shared/domain/JWT.ts b/packages/shared/domain/JWT.ts index 9a45040..0eab8ba 100644 --- a/packages/shared/domain/JWT.ts +++ b/packages/shared/domain/JWT.ts @@ -1,3 +1,5 @@ +import { sign } from "node:crypto" + export type JWTHeader = { alg: string, typ: string, @@ -42,6 +44,20 @@ export type JWT = { signature: JWTSignature } +// todo pasar a la clase JWT +function signJWT(args: { + algorythm: "sha256" | string, + data: string, + privateKey: string +}) { + const signature = sign( + args.algorythm, + Buffer.from(args.data), + args.privateKey + ) + return signature +} + export class JWTToken { public rawToken: string @@ -54,6 +70,37 @@ export class JWTToken { this.decodedPayload = this.decodePayload() } + public static fromParts(args: { + header: JWTHeader, + payload?: JWTPayload, + sigantureData?: { + privateKey: string, + algorythm: string + } + }) { + const strHeader = JSON.stringify(args.header) + const base64Header = Buffer.from(strHeader).toString("base64url") + let msg = base64Header + + if (args.payload != undefined) { + const strPayload = JSON.stringify(args.payload) + const base64payload = Buffer.from(strPayload).toString("base64url") + msg += ("." + base64payload) + } + + if (args.sigantureData != undefined) { + const base64signature = signJWT({ + algorythm: args.sigantureData.algorythm, + privateKey: args.sigantureData.privateKey, + data: msg + }).toString("base64url") + msg += ("." + base64signature) + } + console.log("JWT", msg) + + + } + private decodePayload(): JWTPayload { if (this.rawToken == undefined) throw new Error("La clase no tiene un token definido") const rawTokenPayload = this.rawToken.split(".")[1] diff --git a/packages/sim-consumidor-activaciones/.env b/packages/sim-consumidor-activaciones/.env index 232c329..85d1f4b 100644 --- a/packages/sim-consumidor-activaciones/.env +++ b/packages/sim-consumidor-activaciones/.env @@ -3,3 +3,4 @@ OBJ_PEM_PATH=./obj.pem OBJ_AUTHORIZATION=XOc7FtwXD8hUX2SFVX94XSty8wkOmChkwDNF09O_aIxPubMDdFUdCDCB4zpzSIxi8nOcTg7r_LM_nmd5qm7uLbksf_XArjI8iAyhjKz_2BAXPhmvKs4Fc9f3vv5LDfCVrPB9lP8P7rJ66_qnWs4jvhLQxSfn29m96hgXeCf8oySdIDUjN2q9Js3KAS5LL52Ri6ryvUeO1PvMhaPQMWRqoHIqTV1wPfPtiqQwcjUPmu5GeW164Kq1JLgV3KaGzfCZ9Qv9lbv30EJrukXxWuLCAhBS0kzrBXZoWvf2pb9uh3Am_93_dDxiIGQfIap9ZU_m8ZD1HPgvZOMCY6ZkxQconQ OBJ_CLI_ASSERTION=XOc7FtwXD8hUX2SFVX94XSty8wkOmChkwDNF09O_aIxPubMDdFUdCDCB4zpzSIxi8nOcTg7r_LM_nmd5qm7uLbksf_XArjI8iAyhjKz_2BAXPhmvKs4Fc9f3vv5LDfCVrPB9lP8P7rJ66_qnWs4jvhLQxSfn29m96hgXeCf8oySdIDUjN2q9Js3KAS5LL52Ri6ryvUeO1PvMhaPQMWRqoHIqTV1wPfPtiqQwcjUPmu5GeW164Kq1JLgV3KaGzfCZ9Qv9lbv30EJrukXxWuLCAhBS0kzrBXZoWvf2pb9uh3Am_93_dDxiIGQfIap9ZU_m8ZD1HPgvZOMCY6ZkxQconQ OBJ_CLIENT_ID=savefamily_rest_ws +OBJ_KID=xNfbMiyL1ORXGP8lElhcv8nVaG3EJKye4Lc1YoN3I1E diff --git a/packages/sim-consumidor-activaciones/aplication/JWT.service.test.ts b/packages/sim-consumidor-activaciones/aplication/JWT.service.test.ts index bd6977d..35b3ffb 100644 --- a/packages/sim-consumidor-activaciones/aplication/JWT.service.test.ts +++ b/packages/sim-consumidor-activaciones/aplication/JWT.service.test.ts @@ -1,6 +1,5 @@ import { test, describe } from "vitest" import { JWTService } from "./JWT.service" -import { loadEnvFile } from "node:process" describe("Tokens Objenious", () => { const jwtService = new JWTService() @@ -9,7 +8,7 @@ describe("Tokens Objenious", () => { console.log("test env", process.env.OBJ_CLIENT_ID) test("Solicicitud normal de auth", async () => { - //const token = await jwtService.getAccessToken() - + const token = await jwtService.getAccessToken() + console.log("acceso objenious", token) }) }) diff --git a/packages/sim-consumidor-activaciones/aplication/JWT.service.ts b/packages/sim-consumidor-activaciones/aplication/JWT.service.ts index f485f8b..e0b70b5 100644 --- a/packages/sim-consumidor-activaciones/aplication/JWT.service.ts +++ b/packages/sim-consumidor-activaciones/aplication/JWT.service.ts @@ -1,11 +1,13 @@ // PEM ? import { env } from "#config/env"; +import fs from "fs" import { JWTToken } from "#shared/domain/JWT" -import axios from "axios"; +import axios, { AxiosError } from "axios"; +import { sign } from "node:crypto" type GrantAccessRequestBody = { grant_type: string, @@ -23,9 +25,19 @@ type TokensRequestResponse = { "not-before-policy": number, "session_state": string, "scope": string - } +type AuthHeaders = { + content_type: string, + sub: string, + iss: string, + aud: string, + jti: string, + iat: number, + exp: number, +} + + const GET_TOKEN_URL = "https://idp.docapost.io/auth/realms/GETWAY/protocol/openid-connect/token" const REFRESH_TOKEN_URL = GET_TOKEN_URL @@ -45,6 +57,20 @@ const DEFAULT_HEADERS = { "content-type": "application/x-www-form-urlencoded" } +function addIATHeaders(authHeaders: Object) { + const headers = { + ...authHeaders, + sub: env.OBJ_CLIENT_ID, + iss: env.OBJ_CLIENT_ID, + aud: GET_TOKEN_URL, + jti: Date.now().toString(), + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 5 * 60, + } + return headers +} + + /** * El servicio gestiona un par de tokens auth - refresh para las * operaciones de Objenious. @@ -69,12 +95,40 @@ export class JWTService { console.warn("Se está intentado conseguir un token sin expirar el anterior") } + console.log("headers", addIATHeaders(DEFAULT_HEADERS)) + console.log("body", DEFAULT_BODY) + console.log("keypath", __dirname + "/../obj.pem") + const key = fs.readFileSync(__dirname + "/../obj.pem", "utf8") + const msg = Buffer.from("test") + const signature = sign( + "sha256", + Buffer.from(msg), + key + ) + JWTToken.fromParts({ + header: { alg: "RS256", typ: "JWT", kid: "1234" }, + payload: { + "iss": "savefamily_rest_ws", + "aud": "https://idp.docapost.io/auth/realms/GETWAY", + }, + sigantureData: { + algorythm: "sha256", + privateKey: key + } + }) + console.log("signature", signature.toString("base64url")) + + return; + const req = axios.post(GET_TOKEN_URL, DEFAULT_BODY, { - headers: DEFAULT_HEADERS + headers: addIATHeaders(DEFAULT_HEADERS) } ) + + + let res; try { @@ -84,7 +138,7 @@ export class JWTService { return this.authToken } catch (e) { const errorString = "No se ha podido conseguir el token de acceso de OBJENIOUS" - console.error(errorString, e) + console.error(errorString, (e as AxiosError).response?.data) throw new Error(errorString) } diff --git a/packages/sim-consumidor-activaciones/config/env/index.ts b/packages/sim-consumidor-activaciones/config/env/index.ts index 11f25bd..820595c 100644 --- a/packages/sim-consumidor-activaciones/config/env/index.ts +++ b/packages/sim-consumidor-activaciones/config/env/index.ts @@ -26,8 +26,8 @@ export const env = { OBJ_PEM_PATH: String(process.env.OBJ_PEM_PATH), OBJ_AUTHOIZATION: String(process.env.OBJ_ATHORIZATION), OBJ_CLI_ASSERTION: String(process.env.OBJ_CLI_ASSERTION), - OBJ_CLIENT_ID: String(process.env.OBJ_CLIENT_ID) + OBJ_CLIENT_ID: String(process.env.OBJ_CLIENT_ID), + OBJ_KID: String(process.env.OBJ_KID) }; -console.log("env", env) diff --git a/packages/sim-consumidor-activaciones/mykey.pub b/packages/sim-consumidor-activaciones/mykey.pub new file mode 100644 index 0000000..b8bfd1f --- /dev/null +++ b/packages/sim-consumidor-activaciones/mykey.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIeBiNCOYvDODs8ruiJzTAiBgW +IiYbKdJf5fyX56tUhXhSHqG53nK0U9xgBFZY2y3DBXNnE9Sl9lXYdAo8kULtXTT4 +3Krcwb1mmbg3ofVliyGaLSymtSJGHfTKG2VMUf6EBkjnNKn279h7xnK+xvKb7KrK +vNPaK2KZllMX7ITRnwIDAQAB +-----END PUBLIC KEY----- diff --git a/packages/sim-consumidor-activaciones/obj.pub b/packages/sim-consumidor-activaciones/obj.pub new file mode 100644 index 0000000..99257ed --- /dev/null +++ b/packages/sim-consumidor-activaciones/obj.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4aJ+D7qw+PI0Pa/0BKz4 +1Y6ihP7FLBBag93KPeo1SEjinXyVTfFmxeTxOEhUvsomIA1E5QounKD6i3H83bX/ ++KMm0GgpT+9OjbkEWF8a7+kMGXokilE/9Ah9uwBBzXCzJl4YUyE2VhDQUG6nYCj2 +0XH8bSbtdEb5cUeFA6ZTMm3wYddmfJjKTtZvz4yiyLO8HjW2+1H32rQ0Sr0d7mPD +ch0zm4kBjG4kVXgSUnfk68TgUVNTwikxEQfJ5fb+AME0HOA9mgiGdyKgdNIsd4IP +2zgenWpniAPbGfth6sO78+vrETw/Ul42dgxpxejLfgDhqgrTPbi7zFomh61WFVJO +zQIDAQAB +-----END PUBLIC KEY-----