Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion apps/agent-service/src/agent-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
ITenantRecord,
ITenantSchema,
IUserRequestInterface,
IWallet
IWallet,
VerifyAuthorizationResponse
} from './interface/agent-service.interface';

import { AgentServiceService } from './agent-service.service';
Expand Down Expand Up @@ -467,4 +468,20 @@ export class AgentServiceController {
);
return this.agentServiceService.createOid4vpVerificationSession(payload.sessionRequest, payload.url, payload.orgId);
}

@MessagePattern({ cmd: 'agent-verify-oid4vp-session-auth-response' })
async verifyOid4vpSessionAuthResponse(payload: {
verifyAuthorizationResponse: VerifyAuthorizationResponse;
url: string;
orgId: string;
}): Promise<object> {
this.logger.log(
`[verifyOid4vpSessionAuthResponse] Received 'agent-verify-oid4vp-session-auth-response' request for orgId=${payload?.orgId || 'N/A'}`
);
return this.agentServiceService.verifyOid4vpSessionAuthResponse(
payload.verifyAuthorizationResponse,
payload.url,
payload.orgId
);
}
}
25 changes: 24 additions & 1 deletion apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ import {
IBasicMessage,
WalletDetails,
ILedger,
IStoreOrgAgent
IStoreOrgAgent,
VerifyAuthorizationResponse
} from './interface/agent-service.interface';
import { AgentSpinUpStatus, AgentType, DidMethod, Ledgers, OrgAgentType, PromiseResult } from '@credebl/enum/enum';
import { AgentServiceRepository } from './repositories/agent-service.repository';
Expand Down Expand Up @@ -2284,4 +2285,26 @@ export class AgentServiceService {
throw error;
}
}

async verifyOid4vpSessionAuthResponse(
verifyAuthorizationResponse: VerifyAuthorizationResponse,
url: string,
orgId: string
): Promise<object> {
this.logger.log(
`[verifyOid4vpSessionAuthResponse] Verifying OID4VP session auth response for orgId=${orgId || 'N/A'}`
);
try {
const getApiKey = await this.getOrgAgentApiKey(orgId);
const verifySession = await this.commonService
.httpPost(url, verifyAuthorizationResponse, { headers: { authorization: getApiKey } })
.then(async (response) => response);
return verifySession;
} catch (error) {
this.logger.error(
`[verifyOid4vpSessionAuthResponse] Error in verifying oid4vp session auth response in agent service : ${JSON.stringify(error)}`
);
throw error;
}
}
}
6 changes: 6 additions & 0 deletions apps/agent-service/src/interface/agent-service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,3 +660,9 @@ export interface WalletDetails {
tenantId: string;
orgId: string;
}

export interface VerifyAuthorizationResponse {
verificationSessionId: string;
authorizationResponse: Record<string, unknown>;
origin?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsObject, IsOptional, IsString } from 'class-validator';

export class VerifyAuthorizationResponseDto {
@ApiProperty({
description: 'verification session id received in the authorization response',
example: '93e156ca-a6b9-46ea-913d-f499be167d02'
})
@IsString()
@IsNotEmpty()
verificationSessionId!: string;

@ApiProperty({
description:
'authorization response received from the wallet after user approves or denies the verification request',
example: {
// eslint-disable-next-line camelcase
id_token: {
Passport: [
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tL2F1dGgvdjEvcmVhbG0tY3JlZGVibCIsInN1YiI6IjEyMzQ1Njc4OTAiLCJhdWQiOiJhdXRoLWNlbnRlci1pZCIsImV4cCI6MTY5ODAwMDAwMCwiaWF0IjoxNjk3OTk2NDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
]
}
}
Comment on lines +16 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Example JWT in Swagger docs triggers secret-detection (Gitleaks).

The example JWT on line 20 is flagged by Gitleaks as a potential secret. While it's clearly a dummy value for documentation, consider using a visibly fake placeholder (e.g., 'eyJ...example-token...') to suppress the false positive and avoid noise in CI secret scans.

🧰 Tools
🪛 ESLint

[error] 19-19: There should be no linebreak after '['.

(array-bracket-newline)


[error] 21-21: There should be no linebreak before ']'.

(array-bracket-newline)

🪛 Gitleaks (8.30.0)

[high] 20-20: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In
`@apps/api-gateway/src/oid4vc-verification/dtos/verify-authorization-response.dto.ts`
around lines 16 - 23, Replace the real-looking example JWT in the Swagger
example payload with a clearly fake placeholder to avoid secret-detection false
positives: locate the example object in verify-authorization-response.dto.ts
(the example -> id_token -> Passport value) and change the token string to an
obvious placeholder like 'eyJ...example-token...' or 'REDACTED_EXAMPLE_TOKEN' so
the docs remain illustrative but won’t trigger Gitleaks.

})
@IsObject()
@IsNotEmpty()
authorizationResponse!: Record<string, unknown>;

@ApiProperty({
description: 'The origin of the verification session, if Digital Credentials API was used.',
example: 'https://example.com'
})
@IsOptional()
@IsString()
origin?: string;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { PresentationRequestDto, VerificationPresentationQueryDto } from './dtos
import { Oid4vpPresentationWhDto } from '../oid4vc-issuance/dtos/oid4vp-presentation-wh.dto';
import { CreateVerificationTemplateDto, UpdateVerificationTemplateDto } from './dtos/verification-template.dto';
import { CreateIntentBasedVerificationDto } from './dtos/create-intent-based-verification.dto';
import { VerifyAuthorizationResponseDto } from './dtos/verify-authorization-response.dto';

@Controller()
@UseFilters(CustomExceptionFilter)
Expand Down Expand Up @@ -718,4 +719,45 @@ export class Oid4vcVerificationController {
};
return res.status(HttpStatus.OK).json(finalResponse);
}

@Post('/orgs/:orgId/oid4vp/verify-authorization-response')
@ApiOperation({
summary: 'Verify authorization response',
description: 'Verifies an authorization response for the specified organization.'
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Authorization response verified successfully.',
type: ApiResponseDto
})
@ApiBearerAuth()
@Roles(OrgRoles.OWNER)
@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
async verifyAuthorizationResponse(
@Param(
'orgId',
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId);
}
})
)
orgId: string,
@Body() verifyAuthorizationResponseDto: VerifyAuthorizationResponseDto,
@Res() res: Response
): Promise<Response> {
this.logger.debug(`[verifyAuthorizationResponse] Called with orgId=${orgId}`);

const result = await this.oid4vcVerificationService.verifyAuthorizationResponse(
verifyAuthorizationResponseDto,
orgId
);
this.logger.debug(`[verifyAuthorizationResponse] Authorization response verified successfully for orgId=${orgId}`);
const finalResponse: IResponse = {
statusCode: HttpStatus.CREATED,
message: 'Authorization response verified successfully',
data: result
};
return res.status(HttpStatus.CREATED).json(finalResponse);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IPresentationRequest } from '@credebl/common/interfaces/oid4vp-verifica
import { Oid4vpPresentationWhDto } from '../oid4vc-issuance/dtos/oid4vp-presentation-wh.dto';
import { CreateVerificationTemplateDto, UpdateVerificationTemplateDto } from './dtos/verification-template.dto';
import { CreateIntentBasedVerificationDto } from './dtos/create-intent-based-verification.dto';
import { VerifyAuthorizationResponseDto } from './dtos/verify-authorization-response.dto';

@Injectable()
export class Oid4vcVerificationService {
Expand Down Expand Up @@ -173,4 +174,12 @@ export class Oid4vcVerificationService {
this.logger.debug(`[deleteVerificationTemplate] Called with orgId=${orgId}, templateId=${templateId}`);
return this.natsClient.sendNatsMessage(this.oid4vpProxy, 'verification-template-delete', payload);
}
async verifyAuthorizationResponse(
verifyAuthorizationResponse: VerifyAuthorizationResponseDto,
orgId: string
): Promise<object> {
const payload = { verifyAuthorizationResponse, orgId };
this.logger.debug(`[verifyAuthorizationResponse] Called with orgId=${orgId}`);
return this.natsClient.sendNatsMessage(this.oid4vpProxy, 'verify-authorization-response', payload);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ export interface X5cSigner {
}

export type RequestSigner = DidSigner | X5cSigner;

export interface VerifyAuthorizationResponse {
verificationSessionId: string;
authorizationResponse: Record<string, unknown>;
origin?: string;
}
17 changes: 16 additions & 1 deletion apps/oid4vc-verification/src/oid4vc-verification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import {
} from '@credebl/common/interfaces/oid4vp-verification';
import { MessagePattern } from '@nestjs/microservices';
import { VerificationSessionQuery } from '../interfaces/oid4vp-verifier.interfaces';
import { Oid4vpPresentationWh } from '../interfaces/oid4vp-verification-sessions.interfaces';
import {
Oid4vpPresentationWh,
VerifyAuthorizationResponse
} from '../interfaces/oid4vp-verification-sessions.interfaces';
import { CreateVerificationTemplate, UpdateVerificationTemplate } from '../interfaces/verification-template.interfaces';

@Controller()
Expand Down Expand Up @@ -181,4 +184,16 @@ export class Oid4vpVerificationController {
);
return this.oid4vpVerificationService.deleteVerificationTemplate(orgId, templateId);
}

@MessagePattern({ cmd: 'verify-authorization-response' })
async verifyAuthorizationResponse(payload: {
verifyAuthorizationResponse: VerifyAuthorizationResponse;
orgId: string;
}): Promise<object> {
const { verifyAuthorizationResponse, orgId } = payload;
this.logger.debug(
`[verifyAuthorizationResponse] Received 'verify-authorization-response' request for orgId=${orgId}`
);
return this.oid4vpVerificationService.verifyAuthorizationResponse(verifyAuthorizationResponse, orgId);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
33 changes: 32 additions & 1 deletion apps/oid4vc-verification/src/oid4vc-verification.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ import { VerificationSessionQuery } from '../interfaces/oid4vp-verifier.interfac
import { BaseService } from 'libs/service/base.service';
import { NATSClient } from '@credebl/common/NATSClient';

import { Oid4vpPresentationWh, RequestSigner } from '../interfaces/oid4vp-verification-sessions.interfaces';
import {
Oid4vpPresentationWh,
RequestSigner,
VerifyAuthorizationResponse
} from '../interfaces/oid4vp-verification-sessions.interfaces';
import { X509CertificateRecord } from '@credebl/common/interfaces/x509.interface';
import { SignerMethodOption, x5cKeyType } from '@credebl/enum/enum';
import { CreateVerificationTemplate, UpdateVerificationTemplate } from '../interfaces/verification-template.interfaces';
Expand Down Expand Up @@ -694,4 +698,31 @@ export class Oid4vpVerificationService extends BaseService {
throw new RpcException(error?.response ?? error.error ?? error);
}
}

async verifyAuthorizationResponse(
verifyAuthorizationResponse: VerifyAuthorizationResponse,
orgId: string
): Promise<object> {
this.logger.debug(
`[verifyAuthorizationResponse] called for orgId=${orgId}, verificationSessionId=${JSON.stringify(verifyAuthorizationResponse.verificationSessionId)}`
);
try {
const agentDetails = await this.oid4vpRepository.getAgentEndPoint(orgId);
if (!agentDetails) {
throw new NotFoundException(ResponseMessages.issuance.error.agentEndPointNotFound);
}
const { agentEndPoint, id } = agentDetails;
const url = getAgentUrl(agentEndPoint, CommonConstants.OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY);
const verificationResult = await this.natsClient.sendNatsMessage(
this.oid4vpVerificationServiceProxy,
'agent-verify-oid4vp-session-auth-response',
{ url, orgId, verifyAuthorizationResponse }
);
this.logger.debug(`[verifyAuthorizationResponse] verification result received successfully for orgId=${orgId}`);
return verificationResult;
} catch (error) {
this.logger.error(`[verifyAuthorizationResponse] - error: ${JSON.stringify(error)}`);
throw new RpcException(error?.response ?? error);
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
2 changes: 2 additions & 0 deletions libs/common/src/common.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export enum CommonConstants {
URL_OIDC_VERIFIER_SESSION_GET_BY_QUERY = '/openid4vc/verification-sessions',
URL_OIDC_VERIFIER_SESSION_RESPONSE_GET_BY_ID = '/openid4vc/verification-sessions/response/#',
URL_OID4VP_VERIFICATION_SESSION = '/openid4vc/verification-sessions/create-presentation-request',
URL_OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY = '/openid4vc/verification-sessions/verify-authorization-response',

//X509 agent API URLs
URL_CREATE_X509_CERTIFICATE = '/x509',
Expand Down Expand Up @@ -439,6 +440,7 @@ export enum CommonConstants {
OIDC_VERIFIER_SESSION_GET_BY_ID = 'get-oid4vp-verifier-session-id',
OIDC_VERIFIER_SESSION_GET_BY_QUERY = 'get-oid4vp-verifier-session-query',
OIDC_VERIFIER_SESSION_RESPONSE_GET_BY_ID = 'get-oid4vp-verifier-session-response-id',
OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY = 'verify-oid4vp-verifier-session-auth-response',

//X509
X509_CREATE_CERTIFICATE = 'create-x509-certificate',
Expand Down
6 changes: 5 additions & 1 deletion libs/common/src/common.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,11 @@ export const getAgentUrl = (agentEndPoint: string, urlFlag: string, paramId?: st
String(CommonConstants.OIDC_VERIFIER_SESSION_RESPONSE_GET_BY_ID),
String(CommonConstants.URL_OIDC_VERIFIER_SESSION_RESPONSE_GET_BY_ID)
],
[String(CommonConstants.OID4VP_VERIFICATION_SESSION), String(CommonConstants.URL_OID4VP_VERIFICATION_SESSION)]
[String(CommonConstants.OID4VP_VERIFICATION_SESSION), String(CommonConstants.URL_OID4VP_VERIFICATION_SESSION)],
[
String(CommonConstants.OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY),
String(CommonConstants.URL_OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY)
]
]);

const urlSuffix = agentUrlMap.get(urlFlag);
Expand Down