Skip to content

Commit

Permalink
fix: Credential Service Staging - Resolve issue with page not loading…
Browse files Browse the repository at this point in the history
… and broken login [DEV-3162] (#358)

* Remove the custom implementation of JSON.stringify
because this custom method is written incorrectly and doesn't allow to
show swagger.json in SwaggerUI.

* Fix login/logout dynamic custom button panel.

* Revert code.

* Update custom-button.ts.

* Fixed hot replacement + various enhancements on feature toggles

* Fixed inco

* Removed redundant

* Overall format

---------

Co-authored-by: Tasos Derisiotis <50984242+Eengineer1@users.noreply.github.com>
  • Loading branch information
abdulla-ashurov and Eengineer1 committed Aug 29, 2023
1 parent a17f5b2 commit 419d2ec
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 113 deletions.
186 changes: 145 additions & 41 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
"@cosmjs/amino": "^0.31.1",
"@cosmjs/encoding": "^0.31.1",
"@logto/express": "^2.1.0",
"@types/jsonwebtoken": "^9.0.2",
"@veramo/core": "^5.4.1",
"@veramo/credential-ld": "^5.4.1",
"@veramo/credential-w3c": "^5.4.1",
Expand Down Expand Up @@ -100,6 +99,7 @@
"@types/express-session": "^1.17.7",
"@types/helmet": "^4.0.0",
"@types/json-stringify-safe": "^5.0.0",
"@types/jsonwebtoken": "^9.0.2",
"@types/node": "^20.5.6",
"@types/secp256k1": "^4.0.3",
"@types/swagger-jsdoc": "^6.0.1",
Expand Down
11 changes: 11 additions & 0 deletions src/controllers/revocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,17 @@ export class RevocationController {
}`,
} satisfies CheckStatusListUnsuccessfulResponseBody);

// handle incorrect access control conditions
if (errorRef?.errorCode === 'incorrect_access_control_conditions')
return response.status(StatusCodes.BAD_REQUEST).json({
checked: false,
error: `check: error: ${
errorRef?.message
? 'incorrect access control conditions'
: (error as Record<string, unknown>).toString()
}`,
} satisfies CheckStatusListUnsuccessfulResponseBody);

// return catch-all error
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
checked: false,
Expand Down
6 changes: 5 additions & 1 deletion src/monkey-patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export const JSONStringify = (obj: Record<string, any> | null) => {
return tempArr.join('');
};

const escape = (str: string) => {
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
};

if (ignoreDataTypes(obj)) {
return undefined;
}
Expand All @@ -88,7 +92,7 @@ export const JSONStringify = (obj: Record<string, any> | null) => {

if (restOfDataTypes(obj)) {
const passQuotes = isString(obj) ? `"` : '';
return `${passQuotes}${obj}${passQuotes}`;
return `${passQuotes}${isString(obj) ? escape(obj as unknown as string) : obj}${passQuotes}`;
}

if (isArray(obj)) {
Expand Down
4 changes: 2 additions & 2 deletions src/services/connectors/verida.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class VeridaService {
)
}

const messagingClient = await this.context!.getMessaging()
const messagingClient = await this.context?.getMessaging()

const messageType = 'inbox/type/dataSend' // There are different types of message, here we are sending some data.
const messageData = {
Expand All @@ -93,7 +93,7 @@ export class VeridaService {
did: recipientDid,
}

await messagingClient.send(
await messagingClient?.send(
recipientDid,
messageType,
messageData,
Expand Down
5 changes: 4 additions & 1 deletion src/services/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { CredentialPayload, VerifiableCredential } from '@veramo/core';
import { VC_CONTEXT, VC_TYPE } from '../types/constants.js';
import type { CredentialRequest } from '../types/shared.js';
import { IdentityServiceStrategySetup } from './identity/index.js';
import { VeridaService } from '../services/connectors/verida.js';
import { v4 } from 'uuid';
import * as dotenv from 'dotenv';
dotenv.config();
Expand Down Expand Up @@ -41,6 +40,10 @@ export class Credentials {

if (ENABLE_VERIDA_CONNECTOR === 'true' && request.subjectDid.startsWith('did:vda')) {
if (!request.credentialSchema) throw new Error('Credential schema is required');

// dynamic import to avoid circular dependency
const { VeridaService } = await import('./connectors/verida.js');

await VeridaService.instance.sendCredential(
request.subjectDid,
'New Verifiable Credential',
Expand Down
28 changes: 20 additions & 8 deletions src/services/identity/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { KeyManager } from '@veramo/key-manager';
import { DIDStore, KeyStore } from '@veramo/data-store';
import { DIDManager } from '@veramo/did-manager';
import { DIDResolverPlugin, getUniversalResolver as UniversalResolver } from '@veramo/did-resolver';
import { getResolver as VeridaResolver } from '@verida/vda-did-resolver';
import { CredentialPlugin } from '@veramo/credential-w3c';
import { CredentialIssuerLD, LdDefaultContexts, VeramoEd25519Signature2018 } from '@veramo/credential-ld';
import {
Expand Down Expand Up @@ -51,7 +50,6 @@ import {
import type { CheqdNetwork } from '@cheqd/sdk';
import { getDidKeyResolver as KeyDidResolver } from '@veramo/did-provider-key';
import { Resolver, ResolverRegistry } from 'did-resolver';

import {
BroadcastStatusListOptions,
CheckStatusListOptions,
Expand All @@ -74,6 +72,10 @@ import {
import { MINIMAL_DENOM, VC_PROOF_FORMAT, VC_REMOVE_ORIGINAL_FIELDS } from '../../types/constants.js';
import { toCoin, toDefaultDkg, toMinimalDenom } from '../../helpers/helpers.js';

// dynamic import to avoid circular dependency
const VeridaResolver =
process.env.ENABLE_VERIDA_CONNECTOR === 'true' ? (await import('@verida/vda-did-resolver')).getResolver : undefined;

export class Veramo {
static instance = new Veramo();

Expand Down Expand Up @@ -115,14 +117,24 @@ export class Veramo {
}

if (enableResolver) {
// construct resolver map
const resolvers = {
...(CheqdDidResolver({ url: process.env.RESOLVER_URL }) as ResolverRegistry),
...KeyDidResolver(),
...UniversalResolver(),
};

// handle optional dependencies
if (VeridaResolver) {
const veridaResolver = VeridaResolver();

// add verida resolver to resolver map
Object.assign(resolvers, veridaResolver);
}

plugins.push(
new DIDResolverPlugin({
resolver: new Resolver({
...(CheqdDidResolver({ url: process.env.RESOLVER_URL }) as ResolverRegistry),
...KeyDidResolver(),
...VeridaResolver(),
...UniversalResolver(),
}),
resolver: new Resolver(resolvers),
})
);
}
Expand Down
111 changes: 56 additions & 55 deletions src/services/identity/postgres.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
import type { AbstractPrivateKeyStore } from '@veramo/key-manager';
import { KeyManagementSystem, SecretBox } from '@veramo/kms-local';
import { PrivateKeyStore } from '@veramo/data-store';
import { CheqdNetwork } from '@cheqd/sdk'
import { CheqdNetwork } from '@cheqd/sdk';
import {
Cheqd,
CheqdDIDProvider,
Expand Down Expand Up @@ -127,7 +127,7 @@ export class PostgresIdentityService extends DefaultIdentityService {
async getKey(kid: string, agentId: string) {
const isOwner = await CustomerService.instance.find(agentId, { kid });
if (!isOwner) {
throw new Error(`${kid} not found in wallet`)
throw new Error(`${kid} not found in wallet`);
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return await Veramo.instance.getKey(this.agent!, kid);
Expand Down Expand Up @@ -169,11 +169,11 @@ export class PostgresIdentityService extends DefaultIdentityService {
throw new Error('Customer not found');
}
try {
const agent = await this.createAgent(agentId)
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
const agent = await this.createAgent(agentId);
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.deactivateDid(agent, did)
return await Veramo.instance.deactivateDid(agent, did);
} catch (error) {
throw new Error(`${error}`);
}
Expand Down Expand Up @@ -205,12 +205,12 @@ export class PostgresIdentityService extends DefaultIdentityService {

async createResource(network: string, payload: ResourcePayload, agentId: string) {
try {
const agent = await this.createAgent(agentId)
const did = `did:cheqd:${network}:${payload.collectionId}`
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
const agent = await this.createAgent(agentId);
const did = `did:cheqd:${network}:${payload.collectionId}`;
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.createResource(agent, network, payload)
return await Veramo.instance.createResource(agent, network, payload);
} catch (error) {
throw new Error(`${error}`);
}
Expand Down Expand Up @@ -259,9 +259,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<CreateStatusList2021Result> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.createUnencryptedStatusList2021(agent, did, resourceOptions, statusOptions);
}

Expand All @@ -272,9 +272,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<CreateStatusList2021Result> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.createEncryptedStatusList2021(agent, did, resourceOptions, statusOptions);
}

Expand All @@ -284,9 +284,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<BulkRevocationResult | BulkSuspensionResult | BulkUnsuspensionResult> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.updateUnencryptedStatusList2021(agent, did, statusOptions);
}

Expand All @@ -296,9 +296,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<BulkRevocationResult | BulkSuspensionResult | BulkUnsuspensionResult> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.updateUnencryptedStatusList2021(agent, did, statusOptions);
}

Expand All @@ -308,9 +308,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<StatusCheckResult> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.checkStatusList2021(agent, did, statusOptions);
}

Expand All @@ -321,9 +321,9 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
): Promise<boolean> {
const agent = await this.createAgent(agentId);
if (!await CustomerService.instance.find(agentId, { did })) {
throw new Error(`${did} not found in wallet`)
}
if (!(await CustomerService.instance.find(agentId, { did }))) {
throw new Error(`${did} not found in wallet`);
}
return await Veramo.instance.broadcastStatusList2021(agent, did, resourceOptions, statusOptions);
}

Expand All @@ -338,7 +338,7 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
) {
const agent = await this.createAgent(agentId);
await this.validateCredentialAccess(credentials, agentId)
await this.validateCredentialAccess(credentials, agentId);
return await Veramo.instance.revokeCredentials(agent, credentials, publish);
}

Expand All @@ -348,7 +348,7 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
) {
const agent = await this.createAgent(agentId);
await this.validateCredentialAccess(credentials, agentId)
await this.validateCredentialAccess(credentials, agentId);
return await Veramo.instance.suspendCredentials(agent, credentials, publish);
}

Expand All @@ -358,31 +358,32 @@ export class PostgresIdentityService extends DefaultIdentityService {
agentId: string
) {
const agent = await this.createAgent(agentId);
await this.validateCredentialAccess(credentials, agentId)
await this.validateCredentialAccess(credentials, agentId);
return await Veramo.instance.unsuspendCredentials(agent, credentials, publish);
}

private async validateCredentialAccess(credentials: VerifiableCredential | VerifiableCredential[], agentId: string) {
credentials = Array.isArray(credentials) ? credentials : [credentials]
const customer = await CustomerService.instance.get(agentId) as CustomerEntity | null
if(!customer) {
throw new Error('Customer not found')
}

for(const credential of credentials) {
const decodedCredential = typeof credential === 'string'
? await Cheqd.decodeCredentialJWT(credential)
: credential

const issuerId = typeof decodedCredential.issuer === 'string'
? decodedCredential.issuer
: decodedCredential.issuer.id

const existsInWallet = customer.dids.find((did) => did === issuerId)

if (!existsInWallet) {
throw new Error(`${issuerId} not found in wallet`)
}
}
}
private async validateCredentialAccess(
credentials: VerifiableCredential | VerifiableCredential[],
agentId: string
) {
credentials = Array.isArray(credentials) ? credentials : [credentials];
const customer = (await CustomerService.instance.get(agentId)) as CustomerEntity | null;
if (!customer) {
throw new Error('Customer not found');
}

for (const credential of credentials) {
const decodedCredential =
typeof credential === 'string' ? await Cheqd.decodeCredentialJWT(credential) : credential;

const issuerId =
typeof decodedCredential.issuer === 'string' ? decodedCredential.issuer : decodedCredential.issuer.id;

const existsInWallet = customer.dids.find((did) => did === issuerId);

if (!existsInWallet) {
throw new Error(`${issuerId} not found in wallet`);
}
}
}
}
8 changes: 5 additions & 3 deletions src/static/custom-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ window.addEventListener('load', function () {
window.location.href = base_url + '/logto/sign-out';
};
const auth_pan = document.createElement('div');
auth_pan.classList.add('auth-wrapper');
auth_pan.classList.add('auth-wrapper', 'wrapper');
auth_pan.appendChild(login_button);

const scheme_pan = document.getElementsByClassName('scheme-container')[0];
scheme_pan.children[0].appendChild(auth_pan);
const info_div = document.getElementsByClassName('information-container')[0];
if (info_div) {
info_div.insertAdjacentElement('afterend', auth_pan);
}

isAuthenticated().then(function (value) {
if (value) {
Expand Down
2 changes: 1 addition & 1 deletion src/types/swagger-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@
* type: string
* example: cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg
* feePaymentAmount:
* description: Amount in CHEQ tokens to unlocked the encrypted StatusList2021 DID-Linked Resource.
* description: Amount in CHEQ tokens to unlock the encrypted StatusList2021 DID-Linked Resource.
* type: number
* minimum: 0
* exclusiveMinimum: true
Expand Down

0 comments on commit 419d2ec

Please sign in to comment.