diff --git a/apps/shared/src/events/connectionEvents.ts b/apps/shared/src/events/connectionEvents.ts
index 22177f11d50f62c43265e5f978330e6e92c16d3f..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>
 > {
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 10bcad88fa13ee5fd2ecadf0af64baac1a9ba33f..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 }),
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/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',
+      ],
+    });
+  });
+});