Skip to content

Commit

Permalink
update to credo 0.5
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra committed Mar 17, 2024
1 parent d630a07 commit 30d7cca
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 255 deletions.
16 changes: 8 additions & 8 deletions agent/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "agent",
"dependencies": {
"@credo-ts/askar": "0.5.0-alpha.124",
"@credo-ts/cheqd": "0.5.0-alpha.124",
"@credo-ts/core": "0.5.0-alpha.124",
"@credo-ts/indy-vdr": "0.5.0-alpha.124",
"@credo-ts/node": "0.5.0-alpha.124",
"@credo-ts/openid4vc": "0.5.0-alpha.124",
"@hyperledger/aries-askar-nodejs": "0.2.0-dev.6",
"@hyperledger/indy-vdr-nodejs": "0.2.0-dev.6",
"@credo-ts/askar": "^0.5.0",
"@credo-ts/cheqd": "^0.5.0",
"@credo-ts/core": "^0.5.0",
"@credo-ts/indy-vdr": "^0.5.0",
"@credo-ts/node": "^0.5.0",
"@credo-ts/openid4vc": "^0.5.0",
"@hyperledger/aries-askar-nodejs": "^0.2.0",
"@hyperledger/indy-vdr-nodejs": "^0.2.0",
"cors": "^2.8.5",
"express": "^4.18.2",
"zod": "^3.22.4"
Expand Down
159 changes: 76 additions & 83 deletions agent/src/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { credentialSupportedIds } from "./issuerMetadata";
import { getIssuer } from "./issuer";
import {
DifPresentationExchangeService,
JsonEncoder,
JsonTransformer,
KeyDidCreateOptions,
KeyType,
RecordNotFoundError,
W3cJsonLdVerifiableCredential,
W3cJsonLdVerifiablePresentation,
W3cJwtVerifiableCredential,
Expand All @@ -18,9 +18,10 @@ import {
parseDid,
} from "@credo-ts/core";
import { getAvailableDids, getWebDidDocument } from "./did";
import { setOfferSessionMetadata } from "./session";
import { getVerifier } from "./verifier";
import { getVerifiablePresentationFromEncoded } from "@credo-ts/core/build/modules/dif-presentation-exchange/utils/transform";
import { OpenId4VcIssuanceSessionRepository } from "@credo-ts/openid4vc/build/openid4vc-issuer/repository";
import { OfferSessionMetadata } from "./session";
import { OpenId4VcVerificationSessionState } from "@credo-ts/openid4vc";

const zCreateOfferRequest = z.object({
// FIXME: rename offeredCredentials to credentialSupportedIds in AFJ
Expand Down Expand Up @@ -48,9 +49,18 @@ apiRouter.post(
},
});

await setOfferSessionMetadata(offer.credentialOfferPayload, {
// FIXME: in 0.5.1 we can pass the issuanceMetadata to the createCredentialOffer method
// directly
const issuanceSessionRepository = agent.dependencyManager.resolve(
OpenId4VcIssuanceSessionRepository
);
offer.issuanceSession.issuanceMetadata = {
issuerDidMethod: createOfferRequest.issuerDidMethod,
});
} satisfies OfferSessionMetadata;
await issuanceSessionRepository.update(
agent.context,
offer.issuanceSession
);

return response.json(offer);
}
Expand Down Expand Up @@ -195,7 +205,7 @@ apiRouter.post(
});
}

const { authorizationRequestUri, authorizationRequestPayload } =
const { authorizationRequest, verificationSession } =
await agent.modules.openId4VcVerifier.createAuthorizationRequest({
verifierId: verifier.verifierId,
requestSigner: {
Expand All @@ -208,23 +218,9 @@ apiRouter.post(
},
});

// FIXME: return correlationId in AFJ
const nonce = JsonEncoder.fromBase64(
authorizationRequestPayload.request?.split(".")[1] as string
).nonce;
const requestState = await agent.modules.openId4VcVerifier.config
.getSessionManager(agent.context)
.getRequestStateByNonce(nonce);

if (!requestState) {
return response.status(500).json({
error: "Request state not found",
});
}

return response.json({
authorizationRequestUri,
requestId: requestState.correlationId,
authorizationRequestUri: authorizationRequest,
verificationSessionId: verificationSession.id,
});
}
);
Expand All @@ -233,72 +229,69 @@ const zReceivePresentationRequestBody = z.object({
authorizationRequestUri: z.string().url(),
});

apiRouter.get("/requests/:requestId", async (request, response) => {
const requestId = request.params.requestId;
const responseState = await agent.modules.openId4VcVerifier.config
.getSessionManager(agent.context)
.getResponseStateByCorrelationId(requestId);
const requestState = await agent.modules.openId4VcVerifier.config
.getSessionManager(agent.context)
.getRequestStateByCorrelationId(requestId);

if (!requestState) {
return response
.status(404)
.json({ error: `Request with id ${requestId} not found` });
}
apiRouter.get("/requests/:verificationSessionId", async (request, response) => {
const verificationSessionId = request.params.verificationSessionId;

// FIXME: if we use request_uri we can know when it's scanned and then update the state to
// 'fetched' or something so we can show a loading indicator
if (!responseState) {
return response.json({
requestId,
responseStatus: "pending",
});
}
try {
const verificationSession =
await agent.modules.openId4VcVerifier.getVerificationSessionById(
verificationSessionId
);

// FIXME: when we get the state in AFJ we should be able to get the presentations and submission back
const presentations: any[] = Array.isArray(
responseState.response.payload.vp_token
)
? responseState.response.payload.vp_token
: [responseState.response.payload.vp_token];
if (
verificationSession.state ===
OpenId4VcVerificationSessionState.ResponseVerified
) {
const verified =
await agent.modules.openId4VcVerifier.getVerifiedAuthorizationResponse(
verificationSessionId
);

return response.json({
verificationSessionId: verificationSession.id,
responseStatus: verificationSession.state,
error: verificationSession.errorMessage,

presentations: verified.presentationExchange?.presentations.map(
(presentation) => {
if (presentation instanceof W3cJsonLdVerifiablePresentation) {
return {
pretty: presentation.toJson(),
encoded: presentation.toJson(),
};
}

return response.json({
requestId,
responseStatus: responseState.status,
error: responseState.error?.message,
presentations: presentations.map((presentation) => {
const presentationInstance = getVerifiablePresentationFromEncoded(
agent.context,
presentation
);
if (presentationInstance instanceof W3cJsonLdVerifiablePresentation) {
return {
pretty: presentationInstance.toJson(),
encoded: presentationInstance.toJson(),
};
}
if (presentation instanceof W3cJwtVerifiablePresentation) {
return {
pretty: JsonTransformer.toJSON(presentation.presentation),
encoded: presentation.serializedJwt,
};
}

if (presentationInstance instanceof W3cJwtVerifiablePresentation) {
return {
pretty: JsonTransformer.toJSON(presentationInstance.presentation),
encoded: presentationInstance.serializedJwt,
};
}
return {
pretty: {
...presentation,
compact: undefined,
},
encoded: presentation.compact,
};
}
),
submission: verified.presentationExchange?.submission,
definition: verified.presentationExchange?.definition,
});
}

return {
pretty: {
...presentationInstance,
compact: undefined,
},
encoded: presentationInstance.compact,
};
}),
submission: responseState.response.payload.presentation_submission,
definition: (await requestState.request.getPresentationDefinitions())?.[0]
.definition,
});
return response.json({
verificationSessionId: verificationSession.id,
responseStatus: verificationSession.state,
error: verificationSession.errorMessage,
});
} catch (error) {
if (error instanceof RecordNotFoundError) {
return response.status(404).send("Verification session not found");
}
}
});

apiRouter.post(
Expand Down
20 changes: 15 additions & 5 deletions agent/src/issuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
credentialsSupported,
issuerDisplay,
} from "./issuerMetadata";
import { getOfferSessionMetadata } from "./session";
import { OfferSessionMetadata } from "./session";
import { getAvailableDids } from "./did";

const issuerId = "e451c49f-1186-4fe4-816d-a942151dfd59";
Expand Down Expand Up @@ -51,16 +51,26 @@ export async function updateIssuer() {
export const credentialRequestToCredentialMapper: OpenId4VciCredentialRequestToCredentialMapper =
async ({
credentialsSupported,
credentialOffer,
credentialRequest,
// FIXME: it would be useful if holderBinding would include some metadata on the key type / alg used
// for the key binding
holderBinding,
}) => {
const credentialSupported = credentialsSupported[0];

const { issuerDidMethod } = await getOfferSessionMetadata(
credentialOffer.credential_offer
);
// FIXME: issuanceSession will be passed to this method from 0.5.1 onward
// https://github.com/openwallet-foundation/credo-ts/pull/1795
const issuanceSession =
await agent.modules.openId4VcIssuer.findIssuanceSessionForCredentialRequest(
{ credentialRequest }
);
if (!issuanceSession) throw new Error("Issuance session not found");
if (!issuanceSession.issuanceMetadata)
throw new Error("No issuance metadata");

const { issuerDidMethod } =
issuanceSession.issuanceMetadata as unknown as OfferSessionMetadata;

const possibleDids = getAvailableDids().filter((d) =>
d.startsWith(issuerDidMethod)
);
Expand Down
35 changes: 1 addition & 34 deletions agent/src/session.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
import { OpenId4VciCredentialOfferPayload } from "@credo-ts/openid4vc";
import { agent } from "./agent";

interface OfferSessionMetadata {
export interface OfferSessionMetadata {
issuerDidMethod: string;
}

export async function setOfferSessionMetadata(
offer: OpenId4VciCredentialOfferPayload,
metadata: OfferSessionMetadata
) {
const preAuthorizedCode = offer.grants?.[
"urn:ietf:params:oauth:grant-type:pre-authorized_code"
]?.["pre-authorized_code"] as string;

const offerSession = await agent.modules.openId4VcIssuer.config
.getCredentialOfferSessionStateManager(agent.context)
.get(preAuthorizedCode);

// FIXME: there needs to be a better way to set the issuerDid
offerSession!.credentialDataSupplierInput = metadata;
}

export async function getOfferSessionMetadata(
offer: OpenId4VciCredentialOfferPayload
) {
const preAuthorizedCode = offer.grants?.[
"urn:ietf:params:oauth:grant-type:pre-authorized_code"
]?.["pre-authorized_code"] as string;

const offerSession = await agent.modules.openId4VcIssuer.config
.getCredentialOfferSessionStateManager(agent.context)
.get(preAuthorizedCode);

return offerSession?.credentialDataSupplierInput as OfferSessionMetadata;
}
4 changes: 2 additions & 2 deletions agent/src/verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export async function createVerifier() {

export async function doesVerifierExist() {
try {
await agent.modules.openId4VcVerifier.getByVerifierId(verifierId);
await agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId);
return true;
} catch (error) {
return false;
}
}

export async function getVerifier() {
return agent.modules.openId4VcVerifier.getByVerifierId(verifierId);
return agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId);
}
Loading

0 comments on commit 30d7cca

Please sign in to comment.