From 4d9bab9edd64ee8a0659d309fb6dac20c9c9373c Mon Sep 17 00:00:00 2001 From: kkmanos Date: Tue, 16 Apr 2024 12:45:53 +0300 Subject: [PATCH] this fix handles error in case user session is not existent --- .../grant_types/AuthorizationCodeGrant.ts | 54 ------------------- .../grant_types/PreAuthorizedCodeGrant.ts | 9 ---- src/openid4vci/utils/generateAccessToken.ts | 7 ++- ...entialIssuingAuthorizationServerService.ts | 16 ++++-- 4 files changed, 19 insertions(+), 67 deletions(-) delete mode 100644 src/openid4vci/grant_types/AuthorizationCodeGrant.ts delete mode 100644 src/openid4vci/grant_types/PreAuthorizedCodeGrant.ts diff --git a/src/openid4vci/grant_types/AuthorizationCodeGrant.ts b/src/openid4vci/grant_types/AuthorizationCodeGrant.ts deleted file mode 100644 index de470ab..0000000 --- a/src/openid4vci/grant_types/AuthorizationCodeGrant.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { AuthorizationServerState } from "../../entities/AuthorizationServerState.entity"; -import { generateAccessToken } from "../utils/generateAccessToken"; - -export async function authorizationCodeGrantTokenEndpoint(state: AuthorizationServerState, _authorizationHeader?: string) { - // TODO: validate the code verifier... - - // let client: ClientEntity; - // if (authorizationHeader) { - // // TODO: Verify client_id and client_secret (only registered clients are accepted) - // const clientAuthenticationType = authorizationHeader.split(' ')[0]; - // if (clientAuthenticationType != "Basic") { - // throw "Client authentication type is not supported" - // } - // const [_, b64Credential] = authorizationHeader.split(' '); - // if (!b64Credential) { - // throw "Basic credentials not found"; - // } - // const decodedCredential = Buffer.from(b64Credential, 'base64').toString('utf-8'); - // const [client_id, client_secret] = decodedCredential.split(':'); - // if (!client_id || !client_secret) { - // throw "Client id or client secret is not defined in Basic credentials"; - // } - // const clientFetchRes = await getOpenid4vciClientByClientIdAndSecret(client_id, client_secret); - // if (clientFetchRes.err) - // throw "Client not found by client_id and client_secret"; - // client = clientFetchRes.unwrap(); - // // TODO: verify redirect_uri based on client id - // if (client.redirect_uri !== body.redirect_uri) - // throw "Redirect uri is not the same with the registered client"; - // } - // else if (body.client_assertion && body.client_assertion_method) { - // // set the client entity - // const [_header, _payload, _] = body.client_assertion.split('.') - // .map((part, index) => index != 2 ? JSON.parse(base64url.decode(part)) : part); - - - - // // const { kid } = header as { kid?: string }; - // // const { iss, aud } = payload as { iss?: string, aud?: string }; - // // use kid to find the user in the Client DB in the jwks - // // verify that aud matches the our issuer. - // } - // else { - // throw "There is no way to authenticate the client" - // } - - - - - - - - return generateAccessToken(state); -} \ No newline at end of file diff --git a/src/openid4vci/grant_types/PreAuthorizedCodeGrant.ts b/src/openid4vci/grant_types/PreAuthorizedCodeGrant.ts deleted file mode 100644 index f0f2cc8..0000000 --- a/src/openid4vci/grant_types/PreAuthorizedCodeGrant.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { AuthorizationServerState } from "../../entities/AuthorizationServerState.entity"; -import { TokenResponseSchemaType } from "../../types/oid4vci"; -import { generateAccessToken } from "../utils/generateAccessToken"; - - -export async function preAuthorizedCodeGrantTokenEndpoint(state: AuthorizationServerState): Promise { - - return generateAccessToken(state); -} diff --git a/src/openid4vci/utils/generateAccessToken.ts b/src/openid4vci/utils/generateAccessToken.ts index c9b487e..0d11626 100644 --- a/src/openid4vci/utils/generateAccessToken.ts +++ b/src/openid4vci/utils/generateAccessToken.ts @@ -2,13 +2,18 @@ import { TokenResponseSchemaType } from '../../types/oid4vci'; import * as crypto from 'node:crypto'; import { AuthorizationServerState } from "../../entities/AuthorizationServerState.entity"; import * as jose from 'jose'; +import { Request, Response } from 'express'; const accessTokenExpirationInSeconds = 8000; export const keyPairPromise = jose.generateKeyPair('RSA-OAEP-256'); -export async function generateAccessToken(userSession: AuthorizationServerState): Promise { +export async function generateAccessToken(ctx: { req: Request, res: Response }): Promise { + if (ctx.res.headersSent) { + return null; + } + const userSession = ctx.req.authorizationServerState; const credentialIssuersIdentifiers: string[] = []; if (userSession.authorization_details) { diff --git a/src/services/OpenidForCredentialIssuingAuthorizationServerService.ts b/src/services/OpenidForCredentialIssuingAuthorizationServerService.ts index 47d43d6..6b59289 100644 --- a/src/services/OpenidForCredentialIssuingAuthorizationServerService.ts +++ b/src/services/OpenidForCredentialIssuingAuthorizationServerService.ts @@ -355,14 +355,24 @@ export class OpenidForCredentialIssuingAuthorizationServerService implements Ope } async tokenRequestHandler(ctx: { req: Request, res: Response }): Promise { - ctx.res.setHeader("Cache-Control", "no-store"); await this.tokenRequestGrantTypeHandler(ctx); await this.tokenRequestAuthorizationCodeHandler(ctx); await this.tokenRequestPreAuthorizedCodeHandler(ctx); // await this.tokenRequestUserPinHandler(ctx); keep this commented to not require userpin - const response = await generateAccessToken(ctx.req.authorizationServerState); - ctx.res.send(response); + try { + const response = await generateAccessToken(ctx); + if (response) { + ctx.res.setHeader("Cache-Control", "no-store"); + ctx.res.send(response); + } + } + catch(err) { + console.error("Couldn't generate access token. Detailed error:"); + console.error(err); + ctx.res.status(400).send({ error: "Couldn't generate access token" }); + return; + } } } \ No newline at end of file