diff --git a/apps/shared/src/events/__tests__/connectionEvents.spec.ts b/apps/shared/src/events/__tests__/connectionEvents.spec.ts
index 42ea6e6b7b46ed3c38bc46c279d5841ff444d2f2..70f97f016b6db6c607667ac17ff57f860702386c 100644
--- a/apps/shared/src/events/__tests__/connectionEvents.spec.ts
+++ b/apps/shared/src/events/__tests__/connectionEvents.spec.ts
@@ -5,6 +5,7 @@ import {
 } from '@aries-framework/core';
 
 import {
+  EventDidcommConnectionsBlock,
   EventDidcommConnectionsCreateWithSelf,
   EventDidcommConnectionsGetAll,
   EventDidcommConnectionsGetById,
@@ -49,4 +50,21 @@ describe('Connection Events', () => {
       state: DidExchangeState.Completed,
     });
   });
+
+  it('should create a new connections block event', () => {
+    const event = new EventDidcommConnectionsBlock(
+      new ConnectionRecord({
+        role: DidExchangeRole.Requester,
+        state: DidExchangeState.Completed,
+      }),
+    );
+
+    expect(typeof event.id).toStrictEqual('string');
+    expect(event.type).toStrictEqual('EventDidcommConnectionsBlock');
+    expect(event.timestamp).toBeInstanceOf(Date);
+    expect(event.instance).toMatchObject({
+      role: DidExchangeRole.Requester,
+      state: DidExchangeState.Completed,
+    });
+  });
 });
diff --git a/apps/shared/src/events/connectionEvents.ts b/apps/shared/src/events/connectionEvents.ts
index 1831f5cd2249438ed2498eabfaa8e19e7a9b349b..1ec09a51c4624dca7b56ce0866b7716e0ad1de4c 100644
--- a/apps/shared/src/events/connectionEvents.ts
+++ b/apps/shared/src/events/connectionEvents.ts
@@ -1,23 +1,7 @@
-import {
-  ConnectionRecord,
-  DidDocument,
-  JsonTransformer,
-} from '@aries-framework/core';
+import { ConnectionRecord, JsonTransformer } from '@aries-framework/core';
 
 import { BaseEvent } from './baseEvents.js';
 
-export class EventInfoPublicDid extends BaseEvent<DidDocument> {
-  public static token = 'didcomm.info.publicDid';
-
-  public get instance() {
-    return JsonTransformer.fromJSON(this.data, DidDocument);
-  }
-
-  public static fromEvent(e: EventInfoPublicDid) {
-    return new EventInfoPublicDid(e.data, e.id, e.type, e.timestamp);
-  }
-}
-
 export class EventDidcommConnectionsGetAll extends BaseEvent<
   Array<ConnectionRecord>
 > {
@@ -55,9 +39,7 @@ export class EventDidcommConnectionsCreateWithSelf extends BaseEvent<ConnectionR
   public static token = 'didcomm.connections.createWithSelf';
 
   public get instance() {
-    return JsonTransformer.fromJSON(this.data, ConnectionRecord, {
-      validate: true,
-    });
+    return JsonTransformer.fromJSON(this.data, ConnectionRecord);
   }
 
   public static fromEvent(e: EventDidcommConnectionsCreateWithSelf) {
@@ -69,3 +51,17 @@ export class EventDidcommConnectionsCreateWithSelf extends BaseEvent<ConnectionR
     );
   }
 }
+
+export class EventDidcommConnectionsBlock extends BaseEvent<ConnectionRecord | null> {
+  public static token = 'didcomm.connections.block';
+
+  public get instance() {
+    return this.data
+      ? JsonTransformer.fromJSON(this.data, ConnectionRecord)
+      : null;
+  }
+
+  public static fromEvent(e: EventDidcommConnectionsBlock) {
+    return new EventDidcommConnectionsBlock(e.data, e.id, e.type, e.timestamp);
+  }
+}
diff --git a/apps/shared/src/events/didEvents.ts b/apps/shared/src/events/didEvents.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6a2d68003d3e031dd5a58390e815df73754c6de
--- /dev/null
+++ b/apps/shared/src/events/didEvents.ts
@@ -0,0 +1,32 @@
+import { DidDocument, JsonTransformer } from '@aries-framework/core';
+
+import { BaseEvent } from './baseEvents.js';
+
+/**
+ *
+ * @todo: this should be removed as it is a weird event that should not be needed
+ *
+ */
+export class EventInfoPublicDid extends BaseEvent<DidDocument> {
+  public static token = 'dids.publicDid';
+
+  public get instance() {
+    return JsonTransformer.fromJSON(this.data, DidDocument);
+  }
+
+  public static fromEvent(e: EventInfoPublicDid) {
+    return new EventInfoPublicDid(e.data, e.id, e.type, e.timestamp);
+  }
+}
+
+export class EventDidsResolve extends BaseEvent<DidDocument> {
+  public static token = 'dids.resolve';
+
+  public get instance() {
+    return JsonTransformer.fromJSON(this.data, DidDocument);
+  }
+
+  public static fromEvent(e: EventDidsResolve) {
+    return new EventDidsResolve(e.data, e.id, e.type, e.timestamp);
+  }
+}
diff --git a/apps/shared/src/index.ts b/apps/shared/src/index.ts
index bde9dc3bf812398014890ba91428b1a4a9219a0d..8a7c5425cf8c0c571deb988dc73b0c80275dedda 100644
--- a/apps/shared/src/index.ts
+++ b/apps/shared/src/index.ts
@@ -5,3 +5,4 @@ export * from './logging/logger.js';
 export * from './logging/logAxiosError.js';
 
 export * from './events/connectionEvents.js';
+export * from './events/didEvents.js';
diff --git a/apps/ssi-abstraction/src/agent/agent.service.ts b/apps/ssi-abstraction/src/agent/agent.service.ts
index 0d68b5e3c1ea246439dcf3977901188f465cd45a..ef1ee73eff8a4a2e5e39de3aeec876dd891dbfe1 100644
--- a/apps/ssi-abstraction/src/agent/agent.service.ts
+++ b/apps/ssi-abstraction/src/agent/agent.service.ts
@@ -12,6 +12,8 @@ import {
   CredentialsModule,
   DidsModule,
   HttpOutboundTransport,
+  JwkDidRegistrar,
+  JwkDidResolver,
   KeyDidRegistrar,
   KeyDidResolver,
   KeyType,
@@ -19,6 +21,7 @@ import {
   PeerDidRegistrar,
   PeerDidResolver,
   TypedArrayEncoder,
+  WebDidResolver,
 } from '@aries-framework/core';
 import {
   IndyVdrAnonCredsRegistry,
@@ -107,8 +110,10 @@ export class AgentService implements OnApplicationShutdown {
           new IndyVdrSovDidResolver(),
           new PeerDidResolver(),
           new KeyDidResolver(),
+          new JwkDidResolver(),
+          new WebDidResolver(),
         ],
-        registrars: [new PeerDidRegistrar(), new KeyDidRegistrar()],
+        registrars: [new PeerDidRegistrar(), new KeyDidRegistrar(), new JwkDidRegistrar()],
       }),
 
       askar: new AskarModule({ ariesAskar }),
@@ -203,6 +208,11 @@ export class AgentService implements OnApplicationShutdown {
   public async onApplicationShutdown() {
     if (!this.agent.isInitialized) return;
 
-    await this.agent.shutdown();
+    // If we cannot shutdown the wallet on application shutdown, no error will occur
+    // This is done because the Askar shutdown procedure is a bit buggy
+    try {
+      await this.agent.shutdown();
+      // eslint-disable-next-line no-empty
+    } catch {}
   }
 }
diff --git a/apps/ssi-abstraction/src/agent/connections/connections.controller.ts b/apps/ssi-abstraction/src/agent/connections/connections.controller.ts
index 322f3376da65439c0ee86d74047c76f28db96ac8..0eb6bc7c9c5bccf4763067b8c66e76ffc66283c5 100644
--- a/apps/ssi-abstraction/src/agent/connections/connections.controller.ts
+++ b/apps/ssi-abstraction/src/agent/connections/connections.controller.ts
@@ -4,6 +4,7 @@ import {
   EventDidcommConnectionsGetById,
   EventDidcommConnectionsGetAll,
   EventDidcommConnectionsCreateWithSelf,
+  EventDidcommConnectionsBlock,
 } from '@ocm/shared';
 
 import { ConnectionsService } from './connections.service.js';
@@ -36,4 +37,15 @@ export class ConnectionsController {
       await this.connectionsService.createConnectionWithSelf(),
     );
   }
+
+  @MessagePattern(EventDidcommConnectionsBlock.token)
+  public async blockConnection({
+    idOrDid,
+  }: {
+    idOrDid: string;
+  }): Promise<EventDidcommConnectionsBlock> {
+    return new EventDidcommConnectionsBlock(
+      await this.connectionsService.blockByIdOrDid(idOrDid),
+    );
+  }
 }
diff --git a/apps/ssi-abstraction/src/agent/connections/connections.service.ts b/apps/ssi-abstraction/src/agent/connections/connections.service.ts
index 4c6901cd52a6efb5d07993104564adfc4e6657ac..ba72b2c157f28af5007e74e92860c96c1188a157 100644
--- a/apps/ssi-abstraction/src/agent/connections/connections.service.ts
+++ b/apps/ssi-abstraction/src/agent/connections/connections.service.ts
@@ -9,6 +9,7 @@ import {
   ConnectionRepository,
   DidExchangeState,
 } from '@aries-framework/core';
+import { isDid } from '@aries-framework/core/build/utils/did.js';
 import { Injectable } from '@nestjs/common';
 
 import { MetadataTokens } from '../../common/constants.js';
@@ -30,6 +31,37 @@ export class ConnectionsService {
     return await this.agent.connections.findById(id);
   }
 
+  public async blockByIdOrDid(
+    idOrDid: string,
+  ): Promise<ConnectionRecord | null> {
+    if (isDid(idOrDid)) {
+      const records = await this.agent.connections.findAllByQuery({
+        theirDid: idOrDid,
+      });
+
+      if (records.length === 0) {
+        return null;
+      }
+
+      if (records.length > 1) {
+        throw new Error(
+          'Found multiple records with the same DID. This should not be possible',
+        );
+      }
+
+      await this.agent.connections.deleteById(records[0].id);
+
+      return records[0];
+    }
+
+    const record = await this.agent.connections.findById(idOrDid);
+    if (!record) return null;
+
+    await this.agent.connections.deleteById(record.id);
+
+    return record;
+  }
+
   public async createConnectionWithSelf(): Promise<ConnectionRecord> {
     const outOfBandRecord = await this.agent.oob.createInvitation();
     const invitation = outOfBandRecord.outOfBandInvitation;
diff --git a/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts b/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6507d0f4c8bbbfa9b65c30fd222a8b341757905
--- /dev/null
+++ b/apps/ssi-abstraction/src/agent/dids/__tests__/dids.controller.spec.ts
@@ -0,0 +1,36 @@
+import { DidDocument } from '@aries-framework/core';
+import { Test } from '@nestjs/testing';
+
+import { mockConfigModule } from '../../../config/__tests__/mockConfig.js';
+import { AgentModule } from '../../agent.module.js';
+import { DidsController } from '../dids.controller.js';
+import { DidsService } from '../dids.service.js';
+
+describe('DidsController', () => {
+  let didsController: DidsController;
+  let didsService: DidsService;
+
+  beforeEach(async () => {
+    const moduleRef = await Test.createTestingModule({
+      imports: [mockConfigModule(), AgentModule],
+      controllers: [DidsController],
+      providers: [DidsService],
+    }).compile();
+
+    didsService = moduleRef.get(DidsService);
+    didsController = moduleRef.get(DidsController);
+  });
+
+  describe('resolve', () => {
+    it('should resolve a basic did', async () => {
+      const result = new DidDocument({ id: 'did:key:foo' });
+      jest.spyOn(didsService, 'resolve').mockResolvedValue(result);
+
+      const event = await didsController.resolve({
+        did: 'did:key:foo',
+      });
+
+      expect(event.data).toStrictEqual(result);
+    });
+  });
+});
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.controller.ts b/apps/ssi-abstraction/src/agent/dids/dids.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..70074c7dab0d350bf381f0dffc50bfd1e34f5694
--- /dev/null
+++ b/apps/ssi-abstraction/src/agent/dids/dids.controller.ts
@@ -0,0 +1,15 @@
+import { Controller } from '@nestjs/common';
+import { MessagePattern } from '@nestjs/microservices';
+import { EventDidsResolve } from '@ocm/shared';
+
+import { DidsService } from './dids.service.js';
+
+@Controller('dids')
+export class DidsController {
+  public constructor(private didsService: DidsService) {}
+
+  @MessagePattern('dids.resolve')
+  public async resolve({ did }: { did: string }) {
+    return new EventDidsResolve(await this.didsService.resolve(did));
+  }
+}
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.module.ts b/apps/ssi-abstraction/src/agent/dids/dids.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d4428a9a7ca832ede5039c5ca52ada9e8750fe4a
--- /dev/null
+++ b/apps/ssi-abstraction/src/agent/dids/dids.module.ts
@@ -0,0 +1,13 @@
+import { Module } from '@nestjs/common';
+
+import { AgentModule } from '../agent.module.js';
+
+import { DidsController } from './dids.controller.js';
+import { DidsService } from './dids.service.js';
+
+@Module({
+  imports: [AgentModule],
+  providers: [DidsService],
+  controllers: [DidsController],
+})
+export class DidsModule {}
diff --git a/apps/ssi-abstraction/src/agent/dids/dids.service.ts b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d1c4e8676dedd3d87e0b0726e9afc6e8865cba18
--- /dev/null
+++ b/apps/ssi-abstraction/src/agent/dids/dids.service.ts
@@ -0,0 +1,31 @@
+import type { AppAgent } from '../agent.service.js';
+
+import { Injectable } from '@nestjs/common';
+
+import { AgentService } from '../agent.service.js';
+
+@Injectable()
+export class DidsService {
+  public agent: AppAgent;
+
+  public constructor(agentService: AgentService) {
+    this.agent = agentService.agent;
+  }
+
+  public async resolve(did: string) {
+    const {
+      didDocument,
+      didResolutionMetadata: { message, error },
+    } = await this.agent.dids.resolve(did);
+
+    if (!didDocument) {
+      throw new Error(
+        `Could not resolve did: '${did}'. Error: ${error ?? 'None'} Message: ${
+          message ?? 'None'
+        }`,
+      );
+    }
+
+    return didDocument;
+  }
+}
diff --git a/apps/ssi-abstraction/test/connections.e2e-spec.ts b/apps/ssi-abstraction/test/connections.e2e-spec.ts
index 8fa8364d9dd5ec34e366cccdfe3c1e43f541bfff..3f52769ae31e430e6621f072a774fa26dadfe612 100644
--- a/apps/ssi-abstraction/test/connections.e2e-spec.ts
+++ b/apps/ssi-abstraction/test/connections.e2e-spec.ts
@@ -8,6 +8,7 @@ import {
   EventDidcommConnectionsGetById,
   EventDidcommConnectionsGetAll,
   EventDidcommConnectionsCreateWithSelf,
+  EventDidcommConnectionsBlock,
 } from '@ocm/shared';
 import { firstValueFrom } from 'rxjs';
 
@@ -83,4 +84,16 @@ describe('Connections', () => {
     );
     expect(metadata).toMatchObject({ trusted: true });
   });
+
+  it(EventDidcommConnectionsBlock.token, async () => {
+    const response$: Observable<EventDidcommConnectionsBlock> = client.send(
+      EventDidcommConnectionsBlock.token,
+      { idOrDid: 'some-id' },
+    );
+
+    const response = await firstValueFrom(response$);
+    const eventInstance = EventDidcommConnectionsBlock.fromEvent(response);
+
+    expect(eventInstance.instance).toBeNull();
+  });
 });
diff --git a/apps/ssi-abstraction/test/dids.e2e-spec.ts b/apps/ssi-abstraction/test/dids.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e276f368de9ff9a215e4ddef581ac94bfc32faec
--- /dev/null
+++ b/apps/ssi-abstraction/test/dids.e2e-spec.ts
@@ -0,0 +1,97 @@
+import type { INestApplication } from '@nestjs/common';
+import type { ClientProxy } from '@nestjs/microservices';
+import type { Observable } from 'rxjs';
+
+import { ClientsModule, Transport } from '@nestjs/microservices';
+import { Test } from '@nestjs/testing';
+import {
+  EventDidsResolve,
+} from '@ocm/shared';
+import { firstValueFrom } from 'rxjs';
+
+import { AgentModule } from '../src/agent/agent.module.js';
+import { DidsModule } from '../src/agent/dids/dids.module.js';
+import { mockConfigModule } from '../src/config/__tests__/mockConfig.js';
+
+describe('Dids', () => {
+  const TOKEN = 'DIDS_CLIENT_SERVICE';
+  let app: INestApplication;
+  let client: ClientProxy;
+
+  beforeAll(async () => {
+    const moduleRef = await Test.createTestingModule({
+      imports: [
+        mockConfigModule(3005),
+        AgentModule,
+        DidsModule,
+        ClientsModule.register([{ name: TOKEN, transport: Transport.NATS }]),
+      ],
+    }).compile();
+
+    app = moduleRef.createNestApplication();
+
+    app.connectMicroservice({ transport: Transport.NATS });
+
+    await app.startAllMicroservices();
+    await app.init();
+
+    client = app.get(TOKEN);
+    await client.connect();
+  });
+
+  afterAll(async () => {
+    await app.close();
+    client.close();
+  });
+
+  it(EventDidsResolve.token, async () => {
+    const response$: Observable<EventDidsResolve> = client.send(
+      EventDidsResolve.token,
+      {
+        did: 'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      },
+    );
+
+    const response = await firstValueFrom(response$);
+    const eventInstance = EventDidsResolve.fromEvent(response);
+
+    expect(eventInstance.instance.toJSON()).toStrictEqual({
+      '@context': [
+        'https://w3id.org/did/v1',
+        'https://w3id.org/security/suites/ed25519-2018/v1',
+        'https://w3id.org/security/suites/x25519-2019/v1',
+      ],
+      id: 'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      verificationMethod: [
+        {
+          id: 'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+          type: 'Ed25519VerificationKey2018',
+          controller:
+            'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+          publicKeyBase58: 'B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u',
+        },
+      ],
+      authentication: [
+        'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      ],
+      assertionMethod: [
+        'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      ],
+      keyAgreement: [
+        {
+          id: 'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc',
+          type: 'X25519KeyAgreementKey2019',
+          controller:
+            'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+          publicKeyBase58: 'JhNWeSVLMYccCk7iopQW4guaSJTojqpMEELgSLhKwRr',
+        },
+      ],
+      capabilityInvocation: [
+        'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      ],
+      capabilityDelegation: [
+        'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH',
+      ],
+    });
+  });
+});