Skip to content

Commit

Permalink
chore: added acquiring authorization challenge authorization code to …
Browse files Browse the repository at this point in the history
…vci client using the rest api
  • Loading branch information
Brummos committed Jan 13, 2025
1 parent 2b4c069 commit acf2cdc
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 12 deletions.
63 changes: 60 additions & 3 deletions packages/client/lib/AuthorizationCodeClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
AuthorizationChallengeCodeResponse,
AuthorizationChallengeErrorResponse, AuthorizationChallengeRequestOpts,
AuthorizationDetails,
AuthorizationRequestOpts,
CodeChallengeMethod,
CodeChallengeMethod, CommonAuthorizationChallengeRequest,
convertJsonToURI,
CreateRequestObjectMode,
CredentialConfigurationSupportedV1_0_13,
Expand All @@ -16,12 +18,13 @@ import {
JsonURIMode,
Jwt,
OpenId4VCIVersion,
OpenIDResponse,
PARMode,
PKCEOpts,
PushedAuthorizationResponse,
RequestObjectOpts,
ResponseType,
} from '@sphereon/oid4vci-common';
ResponseType
} from '@sphereon/oid4vci-common'
import Debug from 'debug';

import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
Expand Down Expand Up @@ -272,3 +275,57 @@ const handleLocations = (endpointMetadata: EndpointMetadataResultV1_0_13, author
}
return authorizationDetails;
};

export const acquireAuthorizationChallengeAuthCode = async (opts: AuthorizationChallengeRequestOpts): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> => {
return await acquireAuthorizationChallengeAuthCodeUsingRequest({

Check warning on line 280 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L280

Added line #L280 was not covered by tests
authorizationChallengeRequest: await createAuthorizationChallengeRequest(opts)
});
}

export const acquireAuthorizationChallengeAuthCodeUsingRequest = async (opts: { authorizationChallengeRequest: CommonAuthorizationChallengeRequest }): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> => {
const { authorizationChallengeRequest } = opts

Check warning on line 286 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L286

Added line #L286 was not covered by tests
// TODO validate request
const authorizationChallengeCodeUrl = '' // TODO
const response = await sendAuthorizationChallengeRequest(

Check warning on line 289 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L288-L289

Added lines #L288 - L289 were not covered by tests
authorizationChallengeCodeUrl,
authorizationChallengeRequest
);

return response

Check warning on line 294 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L294

Added line #L294 was not covered by tests
}

export const createAuthorizationChallengeRequest = async (opts: AuthorizationChallengeRequestOpts): Promise<CommonAuthorizationChallengeRequest> => {
const {
clientId,
issuerState,
authSession,
scope,
definitionId,
codeChallenge,
codeChallengeMethod,
presentationDuringIssuanceSession
} = opts;

Check warning on line 307 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L307

Added line #L307 was not covered by tests

const request: CommonAuthorizationChallengeRequest = {

Check warning on line 309 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L309

Added line #L309 was not covered by tests
client_id: clientId,
issuer_state: issuerState,
auth_session: authSession,
scope,
code_challenge: codeChallenge,
code_challenge_method: codeChallengeMethod,
definition_id: definitionId,
presentation_during_issuance_session: presentationDuringIssuanceSession
}

return request

Check warning on line 320 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L320

Added line #L320 was not covered by tests
}

export const sendAuthorizationChallengeRequest = async (
authorizationChallengeCodeUrl: string,
authorizationChallengeRequest: CommonAuthorizationChallengeRequest,
opts?: { headers?: Record<string, string> }
): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> => {
return await formPost(authorizationChallengeCodeUrl, convertJsonToURI(authorizationChallengeRequest, { mode: JsonURIMode.X_FORM_WWW_URLENCODED }), { // TODO check encoding

Check warning on line 328 in packages/client/lib/AuthorizationCodeClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/AuthorizationCodeClient.ts#L327-L328

Added lines #L327 - L328 were not covered by tests
customHeaders: opts?.headers ? opts.headers : undefined,
});
}
32 changes: 28 additions & 4 deletions packages/client/lib/OpenID4VCIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {
AccessTokenRequestOpts,
AccessTokenResponse,
Alg,
AuthorizationChallengeCodeResponse,
AuthorizationChallengeErrorResponse,
AuthorizationChallengeRequestOpts,
AuthorizationRequestOpts,
AuthorizationResponse,
AuthorizationServerOpts,
Expand Down Expand Up @@ -31,16 +34,20 @@ import {
NotificationResponseResult,
OID4VCICredentialFormat,
OpenId4VCIVersion,
OpenIDResponse,
PKCEOpts,
ProofOfPossessionCallbacks,
toAuthorizationResponsePayload,
} from '@sphereon/oid4vci-common';
toAuthorizationResponsePayload
} from '@sphereon/oid4vci-common'
import { CredentialFormat } from '@sphereon/ssi-types';
import Debug from 'debug';

import { AccessTokenClient } from './AccessTokenClient';
import { AccessTokenClientV1_0_11 } from './AccessTokenClientV1_0_11';
import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
import {
acquireAuthorizationChallengeAuthCode,
createAuthorizationRequestUrl
} from './AuthorizationCodeClient'
import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
import { CredentialOfferClient } from './CredentialOfferClient';
import { CredentialRequestOpts } from './CredentialRequestClient';
Expand Down Expand Up @@ -270,10 +277,18 @@ export class OpenID4VCIClient {
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
}

public async acquireAuthorizationChallengeCode(opts: AuthorizationChallengeRequestOpts): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> {
const response = await acquireAuthorizationChallengeAuthCode({

Check warning on line 281 in packages/client/lib/OpenID4VCIClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClient.ts#L280-L281

Added lines #L280 - L281 were not covered by tests
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
...opts
})
return response

Check warning on line 285 in packages/client/lib/OpenID4VCIClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClient.ts#L285

Added line #L285 was not covered by tests
}

public async acquireAccessToken(
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
clientId?: string;
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object // TODO we need to add support for the authorization code from the auth challenge
additionalRequestParams?: Record<string, any>;
},
): Promise<AccessTokenResponse & { params?: DPoPResponseParams }> {
Expand Down Expand Up @@ -654,6 +669,15 @@ export class OpenID4VCIClient {
return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`;
}

public getAuthorizationChallengeEndpoint(): string | undefined {
this.assertIssuerData();

Check warning on line 673 in packages/client/lib/OpenID4VCIClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClient.ts#L672-L673

Added lines #L672 - L673 were not covered by tests
return this.endpointMetadata?.authorization_challenge_endpoint;
}

public hasAuthorizationChallengeEndpoint(): boolean {
return !!this.getAuthorizationChallengeEndpoint();

Check warning on line 678 in packages/client/lib/OpenID4VCIClient.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClient.ts#L677-L678

Added lines #L677 - L678 were not covered by tests
}

public hasDeferredCredentialEndpoint(): boolean {
return !!this.getAccessTokenEndpoint();
}
Expand Down
17 changes: 15 additions & 2 deletions packages/client/lib/OpenID4VCIClientV1_0_11.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {
AccessTokenRequestOpts,
AccessTokenResponse,
Alg,
AuthorizationChallengeCodeResponse,
AuthorizationChallengeErrorResponse,
AuthorizationChallengeRequestOpts,
AuthorizationRequestOpts,
AuthorizationResponse,
AuthorizationServerOpts,
Expand All @@ -25,10 +28,11 @@ import {
KID_JWK_X5C_ERROR,
OID4VCICredentialFormat,
OpenId4VCIVersion,
OpenIDResponse,
PKCEOpts,
ProofOfPossessionCallbacks,
toAuthorizationResponsePayload,
} from '@sphereon/oid4vci-common';
toAuthorizationResponsePayload
} from '@sphereon/oid4vci-common'
import { CredentialFormat } from '@sphereon/ssi-types';
import Debug from 'debug';

Expand All @@ -39,6 +43,7 @@ import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClient
import { MetadataClientV1_0_11 } from './MetadataClientV1_0_11';
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
import { generateMissingPKCEOpts } from './functions';
import { acquireAuthorizationChallengeAuthCode } from './AuthorizationCodeClient'

const debug = Debug('sphereon:oid4vci');

Expand Down Expand Up @@ -256,6 +261,14 @@ export class OpenID4VCIClientV1_0_11 {
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
}

public async acquireAuthorizationChallengeCode(opts: AuthorizationChallengeRequestOpts): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> {
const response = await acquireAuthorizationChallengeAuthCode({

Check warning on line 265 in packages/client/lib/OpenID4VCIClientV1_0_11.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClientV1_0_11.ts#L264-L265

Added lines #L264 - L265 were not covered by tests
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
...opts
})
return response

Check warning on line 269 in packages/client/lib/OpenID4VCIClientV1_0_11.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClientV1_0_11.ts#L269

Added line #L269 was not covered by tests
}

public async acquireAccessToken(
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
clientId?: string;
Expand Down
21 changes: 18 additions & 3 deletions packages/client/lib/OpenID4VCIClientV1_0_13.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {
AccessTokenRequestOpts,
AccessTokenResponse,
Alg,
AuthorizationChallengeCodeResponse,
AuthorizationChallengeErrorResponse,
AuthorizationChallengeRequestOpts,
AuthorizationRequestOpts,
AuthorizationResponse,
AuthorizationServerOpts,
Expand All @@ -25,15 +28,19 @@ import {
NotificationResponseResult,
OID4VCICredentialFormat,
OpenId4VCIVersion,
OpenIDResponse,
PKCEOpts,
ProofOfPossessionCallbacks,
toAuthorizationResponsePayload,
} from '@sphereon/oid4vci-common';
toAuthorizationResponsePayload
} from '@sphereon/oid4vci-common'
import { CredentialFormat, DIDDocument } from '@sphereon/ssi-types';
import Debug from 'debug';

import { AccessTokenClient } from './AccessTokenClient';
import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
import {
acquireAuthorizationChallengeAuthCode,
createAuthorizationRequestUrl
} from './AuthorizationCodeClient'
import { CredentialOfferClient } from './CredentialOfferClient';
import { CredentialRequestOpts } from './CredentialRequestClient';
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
Expand Down Expand Up @@ -261,6 +268,14 @@ export class OpenID4VCIClientV1_0_13 {
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
}

public async acquireAuthorizationChallengeCode(opts: AuthorizationChallengeRequestOpts): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse | AuthorizationChallengeErrorResponse>> {
const response = await acquireAuthorizationChallengeAuthCode({

Check warning on line 272 in packages/client/lib/OpenID4VCIClientV1_0_13.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClientV1_0_13.ts#L271-L272

Added lines #L271 - L272 were not covered by tests
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
...opts
})
return response

Check warning on line 276 in packages/client/lib/OpenID4VCIClientV1_0_13.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/lib/OpenID4VCIClientV1_0_13.ts#L276

Added line #L276 was not covered by tests
}

public async acquireAccessToken(
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
clientId?: string;
Expand Down
11 changes: 11 additions & 0 deletions packages/oid4vci-common/lib/types/Authorization.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ export interface CommonAuthorizationChallengeRequest {
presentation_during_issuance_session?: string;
}

export interface AuthorizationChallengeRequestOpts {
clientId?: string;
issuerState?: string
authSession?: string
scope?: string
codeChallenge?: string
codeChallengeMethod?: CodeChallengeMethod
definitionId?: string
presentationDuringIssuanceSession?: string;
}

// https://www.ietf.org/archive/id/draft-parecki-oauth-first-party-apps-02.html#name-error-response
export interface AuthorizationChallengeErrorResponse {
/**
Expand Down

0 comments on commit acf2cdc

Please sign in to comment.