Skip to content

Commit

Permalink
fix: improve parseInvitation to handle parsing oob properly either wi…
Browse files Browse the repository at this point in the history
…th URL or with parsed object.

Signed-off-by: Francisco Javier Ribo Labrador <elribonazo@gmail.com>
  • Loading branch information
elribonazo committed Sep 2, 2024
1 parent a6a72ff commit 3a384f8
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 30 deletions.
25 changes: 20 additions & 5 deletions src/edge-agent/Agent.Invitations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ConnectionsManager } from "./connectionsManager/ConnectionsManager";
import { DIDCommConnectionRunner } from "./protocols/connection/DIDCommConnectionRunner";
import { Pluto } from "../domain/buildingBlocks/Pluto";
import { DIDCommInvitationRunner } from "./protocols/invitation/v2/DIDCommInvitationRunner";
import { base64 } from "multiformats/bases/base64";

/**
* An extension for the Edge agent that groups the functionality to parse, manage and
Expand All @@ -46,6 +47,20 @@ export class AgentInvitations implements AgentInvitationsClass {
private connection: ConnectionsManager
) { }

private decodeOOB(str: string) {
const components = new URL(str);
if (!components) {
throw new AgentError.InvalidURLError();
}
const message = components.searchParams.get("_oob")
if (!message) {
throw new AgentError.InvalidURLError();
}
const dataJson = Buffer.from(base64.baseDecode(message)).toString();
const json = JSON.parse(dataJson);
return json
}

/**
* Asyncronously parse an invitation from a valid json string
*
Expand All @@ -54,14 +69,14 @@ export class AgentInvitations implements AgentInvitationsClass {
* @returns {Promise<InvitationType>}
*/
async parseInvitation(str: string): Promise<InvitationType> {
const json = JSON.parse(str);
const typeString = findProtocolTypeByValue(json.type);

const url = this.decodeOOB(str);
const messasgeType = url.piuri || url.type;
const typeString = findProtocolTypeByValue(messasgeType);
switch (typeString) {
case ProtocolType.PrismOnboarding:
return this.parsePrismInvitation(str);
case ProtocolType.Didcomminvitation:
return this.parseOOBInvitation(new URL(str));
return this.parseOOBInvitation(url);
}

throw new AgentError.UnknownInvitationTypeError();
Expand Down Expand Up @@ -189,7 +204,7 @@ export class AgentInvitations implements AgentInvitationsClass {
* @param {URL} str
* @returns {Promise<OutOfBandInvitation>}
*/
async parseOOBInvitation(str: URL): Promise<OutOfBandInvitation> {
async parseOOBInvitation(str: URL | object): Promise<OutOfBandInvitation> {
return new DIDCommInvitationRunner(str).run();
}
}
7 changes: 3 additions & 4 deletions src/edge-agent/protocols/ProtocolTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ export enum ProtocolType {

export function findProtocolTypeByValue(string: string): ProtocolType {
const values = Object.values(ProtocolType) as string[];
for (const value of values) {
if (value === string) {
return ProtocolType[value as keyof typeof ProtocolType];
}
const validType = values.includes(string)
if (validType) {
return string as ProtocolType
}
throw new Error("Unknown invitation type error.");
}
42 changes: 26 additions & 16 deletions src/edge-agent/protocols/invitation/v2/DIDCommInvitationRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { OutOfBandInvitation } from "./OutOfBandInvitation";
import { AttachmentDescriptor } from "../../../../domain";

export class DIDCommInvitationRunner {
constructor(private url: URL) { }
constructor(private url: URL | object) { }

private isDIDCommInvitation(
type: ProtocolType,
Expand All @@ -17,11 +17,11 @@ export class DIDCommInvitationRunner {
return type === ProtocolType.Didcomminvitation;
}

private safeParseBody(body: string, type: ProtocolType): OutOfBandInvitation {
private safeParseBody(body: string | object, type: ProtocolType): OutOfBandInvitation {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let parsed: any;
try {
parsed = JSON.parse(body);
parsed = typeof body === "string" ? JSON.parse(body) : body
} catch (err) {
throw new AgentError.UnknownInvitationTypeError();
}
Expand Down Expand Up @@ -75,19 +75,29 @@ export class DIDCommInvitationRunner {
}

run(): OutOfBandInvitation {
const components = new URLSearchParams(this.url.search);
if (!components) {
throw new AgentError.InvalidURLError();
}
const message = components.get("_oob");
if (!message) {
throw new AgentError.InvalidURLError();
}
const dataJson = Buffer.from(base64.baseDecode(message)).toString();
const invitation = this.safeParseBody(dataJson, ProtocolType.Didcomminvitation);
if (invitation.isExpired) {
throw new AgentError.InvitationIsInvalidError('expired')
if (this.url instanceof URL) {
const components = new URLSearchParams(this.url.search);
if (!components) {
throw new AgentError.InvalidURLError();
}
const message = components.get("_oob");
if (!message) {
throw new AgentError.InvalidURLError();
}
const dataJson = Buffer.from(base64.baseDecode(message)).toString();
const invitation = this.safeParseBody(dataJson, ProtocolType.Didcomminvitation);
if (invitation.isExpired) {
throw new AgentError.InvitationIsInvalidError('expired')
}
return invitation;

} else {
const invitation = this.safeParseBody(this.url, ProtocolType.Didcomminvitation);
if (invitation.isExpired) {
throw new AgentError.InvitationIsInvalidError('expired')
}
return invitation;
}
return invitation

}
}
2 changes: 1 addition & 1 deletion src/edge-agent/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export interface AgentInvitations {

parsePrismInvitation(str: string): Promise<PrismOnboardingInvitation>;

parseOOBInvitation(str: URL): Promise<OutOfBandInvitation>;
parseOOBInvitation(str: URL | object): Promise<OutOfBandInvitation>;
}

type MessageEventArg = Message[];
Expand Down
36 changes: 36 additions & 0 deletions tests/agent/Agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,42 @@ describe("Agent Tests", () => {
).to.eventually.be.rejectedWith(AgentError.InvitationIsInvalidError);
});


it("As a developer with a valid invitationMessage I will be sending a presentation with the correct information, but will fail as it is expired.", async () => {
const agentInvitations = (agent as any).agentInvitations;
const agentInvitationsConnection = agentInvitations.connection;
const didHigherFunctions = (agent as any).agentDIDHigherFunctions;

const did = DID.fromString(
"did:peer:2.Ez6LSms555YhFthn1WV8ciDBpZm86hK9tp83WojJUmxPGk1hZ.Vz6MkmdBjMyB4TS5UbbQw54szm8yvMMf1ftGV2sQVYAxaeWhE.SeyJpZCI6Im5ldy1pZCIsInQiOiJkbSIsInMiOnsidXJpIjoiaHR0cHM6Ly9tZWRpYXRvci5yb290c2lkLmNsb3VkIiwiYSI6WyJkaWRjb21tL3YyIl19fQ"
);
const validOOB =
"https://my.domain.com/path?_oob=eyJpZCI6IjViMjUwMjIzLWExNDItNDRmYi1hOWJkLWU1MjBlNGI0ZjQzMiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzIuMC9pbnZpdGF0aW9uIiwiZnJvbSI6ImRpZDpwZWVyOjIuRXo2TFNkV0hWQ1BFOHc0NWZETjM4aUh0ZFJ6WGkyTFNqQmRSUjRGTmNOUm12VkNKcy5WejZNa2Z2aUI5S1F1OGlnNVZpeG1HZHM3dmdMNmoyUXNOUGFybkZaanBNQ0E5aHpQLlNleUowSWpvaVpHMGlMQ0p6SWpwN0luVnlhU0k2SW1oMGRIQTZMeTh4T1RJdU1UWTRMakV1TXpjNk9EQTNNQzlrYVdSamIyMXRJaXdpY2lJNlcxMHNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAiLCJib2R5Ijp7ImdvYWxfY29kZSI6InByZXNlbnQtdnAiLCJnb2FsIjoiUmVxdWVzdCBwcm9vZiBvZiB2YWNjaW5hdGlvbiBpbmZvcm1hdGlvbiIsImFjY2VwdCI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiIyYTZmOGM4NS05ZGE3LTRkMjQtOGRhNS0wYzliZDY5ZTBiMDEiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJpZCI6IjI1NTI5MTBiLWI0NmMtNDM3Yy1hNDdhLTlmODQ5OWI5ZTg0ZiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0uYXRhbGFwcmlzbS5pby9wcmVzZW50LXByb29mLzMuMC9yZXF1ZXN0LXByZXNlbnRhdGlvbiIsImJvZHkiOnsiZ29hbF9jb2RlIjoiUmVxdWVzdCBQcm9vZiBQcmVzZW50YXRpb24iLCJ3aWxsX2NvbmZpcm0iOmZhbHNlLCJwcm9vZl90eXBlcyI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiJiYWJiNTJmMS05NDUyLTQzOGYtYjk3MC0yZDJjOTFmZTAyNGYiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJvcHRpb25zIjp7ImNoYWxsZW5nZSI6IjExYzkxNDkzLTAxYjMtNGM0ZC1hYzM2LWIzMzZiYWI1YmRkZiIsImRvbWFpbiI6Imh0dHBzOi8vcHJpc20tdmVyaWZpZXIuY29tIn0sInByZXNlbnRhdGlvbl9kZWZpbml0aW9uIjp7ImlkIjoiMGNmMzQ2ZDItYWY1Ny00Y2E1LTg2Y2EtYTA1NTE1NjZlYzZmIiwiaW5wdXRfZGVzY3JpcHRvcnMiOltdfX19LCJmb3JtYXQiOiJwcmlzbS9qd3QifV0sInRoaWQiOiI1YjI1MDIyMy1hMTQyLTQ0ZmItYTliZC1lNTIwZTRiNGY0MzIiLCJmcm9tIjoiZGlkOnBlZXI6Mi5FejZMU2RXSFZDUEU4dzQ1ZkROMzhpSHRkUnpYaTJMU2pCZFJSNEZOY05SbXZWQ0pzLlZ6Nk1rZnZpQjlLUXU4aWc1Vml4bUdkczd2Z0w2ajJRc05QYXJuRlpqcE1DQTloelAuU2V5SjBJam9pWkcwaUxDSnpJanA3SW5WeWFTSTZJbWgwZEhBNkx5OHhPVEl1TVRZNExqRXVNemM2T0RBM01DOWthV1JqYjIxdElpd2ljaUk2VzEwc0ltRWlPbHNpWkdsa1kyOXRiUzkyTWlKZGZYMCJ9fX1dLCJjcmVhdGVkX3RpbWUiOjE3MjQzMzkxNDQsImV4cGlyZXNfdGltZSI6MTcyNDMzOTQ0NH0";

const createPeerDID = sandbox.stub(
didHigherFunctions,
"createNewPeerDID"
);
const sendMessage = sandbox.stub(
agentInvitationsConnection,
"sendMessage"
);
const addConnection = sandbox.stub(
agentInvitationsConnection,
"addConnection"
);

sandbox.stub(UUIDLib, "uuid").returns("123456-123456-12356-123456");

createPeerDID.resolves(did);
sendMessage.resolves();
addConnection.resolves();

expect(
agent.parseInvitation(validOOB)
).to.eventually.be.rejectedWith(AgentError.InvitationIsInvalidError);
});

});


Expand Down
4 changes: 0 additions & 4 deletions tests/pollux/Bitstring.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ describe('Bitstring', () => {
for (let i = 0; i < 16; i++) {
const bitstringIndex = bitstring.get(i);
if (validIndexes.includes(i)) {
console.log("Index should be true ", i)
expect(bitstringIndex).to.be.true;
} else {
console.log("Index should be false ", i)
expect(bitstringIndex).to.be.false;
}
}
Expand All @@ -34,10 +32,8 @@ describe('Bitstring', () => {
for (let i = 0; i < 16; i++) {
const bitstringIndex = bitstring.get(i);
if (validIndexes.includes(i)) {
console.log("Index should be true ", i)
expect(bitstringIndex).to.be.true;
} else {
console.log("Index should be false ", i)
expect(bitstringIndex).to.be.false;
}
}
Expand Down

0 comments on commit 3a384f8

Please sign in to comment.