Skip to content

Commit

Permalink
Merge branch 'main' into flothjl/action-rule-validation
Browse files Browse the repository at this point in the history
* main:
  #439 - Return `authorization` in queries and reads (#523)
  #439 - Turned `authorization` property from a JWS into a container object (#518)
  npm audit fix get-func-name (#521)
  • Loading branch information
Diane Huxley committed Sep 29, 2023
2 parents 3ffb728 + d5d418b commit 123ec7d
Show file tree
Hide file tree
Showing 47 changed files with 191 additions and 335 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Here's to a thrilling Hacktoberfest voyage with us! 🎉
# Decentralized Web Node (DWN) SDK <!-- omit in toc -->

Code Coverage
![Statements](https://img.shields.io/badge/statements-97.78%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-95.06%25-brightgreen.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-94.28%25-brightgreen.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-97.78%25-brightgreen.svg?style=flat)
![Statements](https://img.shields.io/badge/statements-97.78%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-95.05%25-brightgreen.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-94.26%25-brightgreen.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-97.78%25-brightgreen.svg?style=flat)

- [Introduction](#introduction)
- [Installation](#installation)
Expand Down
6 changes: 4 additions & 2 deletions build/compile-validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Ajv from 'ajv';
import mkdirp from 'mkdirp';
import standaloneCode from 'ajv/dist/standalone/index.js';

import Authorization from '../json-schemas/authorization.json' assert { type: 'json' };
import BaseAuthorizationPayload from '../json-schemas/authorization-payloads/base-authorization-payload.json' assert { type: 'json' };
import Definitions from '../json-schemas/definitions.json' assert { type: 'json' };
import EventsGet from '../json-schemas/events/events-get.json' assert { type: 'json' };
Expand All @@ -40,11 +41,12 @@ import RecordsFilter from '../json-schemas/interface-methods/records-filter.json
import RecordsQuery from '../json-schemas/interface-methods/records-query.json' assert { type: 'json' };
import RecordsRead from '../json-schemas/interface-methods/records-read.json' assert { type: 'json' };
import RecordsWrite from '../json-schemas/interface-methods/records-write.json' assert { type: 'json' };
import RecordsWriteAuthorizationPayload from '../json-schemas/authorization-payloads/records-write-authorization-payload.json' assert { type: 'json' };
import RecordsWriteAuthorSignaturePayload from '../json-schemas/authorization-payloads/records-write-authorization-payload.json' assert { type: 'json' };
import RecordsWriteUnidentified from '../json-schemas/interface-methods/records-write-unidentified.json' assert { type: 'json' };
import SnapshotsCreate from '../json-schemas/interface-methods/snapshots-create.json' assert { type: 'json' };

const schemas = {
Authorization,
RecordsDelete,
RecordsQuery,
RecordsWrite,
Expand All @@ -70,7 +72,7 @@ const schemas = {
PublicJwk,
SnapshotsCreate,
BaseAuthorizationPayload,
RecordsWriteAuthorizationPayload
RecordsWriteAuthorSignaturePayload
};

const ajv = new Ajv({ code: { source: true, esm: true } });
Expand Down
11 changes: 11 additions & 0 deletions json-schemas/authorization.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$id": "https://identity.foundation/dwn/json-schemas/authorization.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"author": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
}
}
}
2 changes: 1 addition & 1 deletion json-schemas/events/events-get.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/hooks/hooks-write.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/messages-get.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
4 changes: 2 additions & 2 deletions json-schemas/interface-methods/permissions-grant.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"additionalProperties": false,
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"delegationChain": {
"description": "the parent grant",
Expand Down Expand Up @@ -71,4 +71,4 @@
}
}
}
}
}
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/permissions-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/permissions-revoke.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"additionalProperties": false,
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/protocols-configure.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/protocols-query.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/records-delete.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
6 changes: 3 additions & 3 deletions json-schemas/interface-methods/records-query.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down Expand Up @@ -44,7 +44,7 @@
"properties": {
"limit": {
"type": "number",
"minimum": 1
"minimum": 1
},
"messageCid": {
"type": "string"
Expand All @@ -63,4 +63,4 @@
}
}
}
}
}
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/records-read.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
},
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"encryption": {
"type": "object",
Expand Down Expand Up @@ -268,4 +268,4 @@
]
}
]
}
}
2 changes: 1 addition & 1 deletion json-schemas/interface-methods/snapshots-create.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"properties": {
"authorization": {
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
"$ref": "https://identity.foundation/dwn/json-schemas/authorization.json"
},
"descriptor": {
"type": "object",
Expand Down
13 changes: 6 additions & 7 deletions src/core/auth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { CID } from 'multiformats';
import type { DidResolver } from '../did/did-resolver.js';
import type { GeneralJws } from '../types/jws-types.js';
import type { GenericMessage } from '../types/message-types.js';
import type { Message } from './message.js';
import type { AuthorizationModel, GenericMessage } from '../types/message-types.js';

import { Cid } from '../utils/cid.js';
import { GeneralJwsVerifier } from '../jose/jws/general/verifier.js';
Expand Down Expand Up @@ -38,12 +37,12 @@ export async function validateAuthorizationIntegrity(
throw new DwnError(DwnErrorCode.AuthorizationMissing, 'Property `authorization` is missing.');
}

if (message.authorization.signatures.length !== 1) {
if (message.authorization.author.signatures.length !== 1) {
throw new Error('expected no more than 1 signature for authorization');
}

// validate payload integrity
const payloadJson = Jws.decodePlainObjectPayload(message.authorization);
const payloadJson = Jws.decodePlainObjectPayload(message.authorization.author);

validateJsonSchema(jsonSchemaKey, payloadJson);

Expand All @@ -62,12 +61,12 @@ export async function validateAuthorizationIntegrity(
* Validates the signature(s) of the given JWS.
* @throws {Error} if fails authentication
*/
export async function authenticate(jws: GeneralJws | undefined, didResolver: DidResolver): Promise<void> {
if (jws === undefined) {
export async function authenticate(authorizationModel: AuthorizationModel | undefined, didResolver: DidResolver): Promise<void> {
if (authorizationModel === undefined) {
throw new DwnError(DwnErrorCode.AuthenticateJwsMissing, 'Missing JWS.');
}

const verifier = new GeneralJwsVerifier(jws);
const verifier = new GeneralJwsVerifier(authorizationModel.author);
await verifier.verify(didResolver);
}

Expand Down
23 changes: 12 additions & 11 deletions src/core/message.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { GeneralJws } from '../types/jws-types.js';
import type { Signer } from '../types/signer.js';
import type { BaseAuthorizationPayload, Descriptor, GenericMessage } from '../types/message-types.js';
import type { AuthorizationModel, BaseAuthorizationPayload, Descriptor, GenericMessage } from '../types/message-types.js';

import { Cid } from '../utils/cid.js';
import { GeneralJwsBuilder } from '../jose/jws/general/builder.js';
Expand Down Expand Up @@ -41,7 +40,7 @@ export abstract class Message<M extends GenericMessage> {
this.message = message;

if (message.authorization !== undefined) {
this.authorizationPayload = Jws.decodePlainObjectPayload(message.authorization);
this.authorizationPayload = Jws.decodePlainObjectPayload(message.authorization.author);
this.author = Message.getAuthor(message as GenericMessage);
}
}
Expand Down Expand Up @@ -74,7 +73,7 @@ export abstract class Message<M extends GenericMessage> {
return undefined;
}

const author = Jws.getSignerDid(message.authorization.signatures[0]);
const author = Jws.getSignerDid(message.authorization.author.signatures[0]);
return author;
}

Expand Down Expand Up @@ -132,25 +131,27 @@ export abstract class Message<M extends GenericMessage> {
}

/**
* Signs over the CID of provided `descriptor`. The output is used as an `authorization` property.
* @param signatureInput - the signature material to use (e.g. key and header data)
* Creates the `authorization` as the author to be used in a DWN message.
* @param signer Signer as the author
* @returns General JWS signature used as an `authorization` property.
*/
public static async signAsAuthorization(
public static async signAuthorizationAsAuthor(
descriptor: Descriptor,
signatureInput: Signer,
signer: Signer,
additionalPayloadProperties?: { permissionsGrantId?: string, protocolRole?: string }
): Promise<GeneralJws> {
): Promise<AuthorizationModel> {
const descriptorCid = await Cid.computeCid(descriptor);

const authPayload: BaseAuthorizationPayload = { descriptorCid, ...additionalPayloadProperties };
removeUndefinedProperties(authPayload);
const authPayloadStr = JSON.stringify(authPayload);
const authPayloadBytes = new TextEncoder().encode(authPayloadStr);

const builder = await GeneralJwsBuilder.create(authPayloadBytes, [signatureInput]);
const builder = await GeneralJwsBuilder.create(authPayloadBytes, [signer]);
const authorJws = builder.getJws();

return builder.getJws();
const authorization = { author: authorJws };
return authorization;
}

/**
Expand Down
21 changes: 3 additions & 18 deletions src/handlers/records-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { MethodHandler } from '../types/method-handler.js';
import type { RecordsWriteMessageWithOptionalEncodedData } from '../store/storage-controller.js';
import type { DataStore, DidResolver, MessageStore } from '../index.js';
import type { Filter, GenericMessage, MessageSort } from '../types/message-types.js';
import type { RecordsQueryMessage, RecordsQueryReply, RecordsQueryReplyEntry } from '../types/records-types.js';
import type { RecordsQueryMessage, RecordsQueryReply } from '../types/records-types.js';

import { authenticate } from '../core/auth.js';
import { messageReplyFromError } from '../core/message-reply.js';
Expand Down Expand Up @@ -53,28 +53,13 @@ export class RecordsQueryHandler implements MethodHandler {
}
}

const entries = RecordsQueryHandler.removeAuthorization(recordsWrites);

return {
status: { code: 200, detail: 'OK' },
entries,
status : { code: 200, detail: 'OK' },
entries : recordsWrites,
paginationMessageCid
};
}

/**
* Removes `authorization` property from each and every `RecordsWrite` message given and returns the result as a different array.
*/
private static removeAuthorization(recordsWriteMessages: RecordsWriteMessageWithOptionalEncodedData[]): RecordsQueryReplyEntry[] {
const recordsQueryReplyEntries: RecordsQueryReplyEntry[] = [];
for (const record of recordsWriteMessages) {
const { authorization: _, ...objectWithRemainingProperties } = record; // a trick to stripping away `authorization`
recordsQueryReplyEntries.push(objectWithRemainingProperties);
}

return recordsQueryReplyEntries;
}

/**
* Convert an incoming DateSort to a sort type accepted by MessageStore
* Defaults to 'dateCreated' in Descending order if no sort is supplied.
Expand Down
5 changes: 2 additions & 3 deletions src/handlers/records-read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ export class RecordsReadHandler implements MethodHandler {
data = result.dataStream;
}

const { authorization: _, ...recordsWriteWithoutAuthorization } = newestRecordsWrite; // a trick to stripping away `authorization`
const messageReply: RecordsReadReply ={
const messageReply: RecordsReadReply = {
status : { code: 200, detail: 'OK' },
record : {
...recordsWriteWithoutAuthorization,
...newestRecordsWrite,
data,
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/events-get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class EventsGet extends Message<EventsGetMessage> {
descriptor.watermark = options.watermark;
}

const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSigner);
const authorization = await Message.signAuthorizationAsAuthor(descriptor, options.authorizationSigner);
const message = { descriptor, authorization };

Message.validateJsonSchema(message);
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/hooks-write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class HooksWrite extends Message<HooksWriteMessage> {
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
removeUndefinedProperties(descriptor);

const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSigner);
const authorization = await Message.signAuthorizationAsAuthor(descriptor, options.authorizationSigner);
const message = { descriptor, authorization };

Message.validateJsonSchema(message);
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/messages-get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class MessagesGet extends Message<MessagesGetMessage> {
messageTimestamp : options?.messageTimestamp ?? getCurrentTimeInHighPrecision(),
};

const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSigner);
const authorization = await Message.signAuthorizationAsAuthor(descriptor, options.authorizationSigner);
const message = { descriptor, authorization };

Message.validateJsonSchema(message);
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/permissions-grant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class PermissionsGrant extends Message<PermissionsGrantMessage> {
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
removeUndefinedProperties(descriptor);

const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSigner);
const authorization = await Message.signAuthorizationAsAuthor(descriptor, options.authorizationSigner);
const message: PermissionsGrantMessage = { descriptor, authorization };

Message.validateJsonSchema(message);
Expand Down
Loading

0 comments on commit 123ec7d

Please sign in to comment.