@atproto-labs/identity-resolver 0.1.19 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/identity-resolver-error.d.ts +4 -0
- package/dist/identity-resolver-error.d.ts.map +1 -0
- package/dist/identity-resolver-error.js +16 -0
- package/dist/identity-resolver-error.js.map +1 -0
- package/dist/identity-resolver.d.ts +10 -5
- package/dist/identity-resolver.d.ts.map +1 -1
- package/dist/identity-resolver.js +36 -36
- package/dist/identity-resolver.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/util.d.ts +13 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +43 -0
- package/dist/util.js.map +1 -0
- package/package.json +2 -3
- package/src/identity-resolver-error.ts +3 -0
- package/src/identity-resolver.ts +56 -60
- package/src/index.ts +2 -0
- package/src/util.ts +51 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atproto-labs/identity-resolver
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Return the whole did document when resolving an identity
|
|
8
|
+
|
|
9
|
+
- [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Reject did documents containing invalid `alsoKnownAs` ATProto handles
|
|
10
|
+
|
|
11
|
+
- [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use `IdentityResolverError` instances instead of `TypeError`
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Perform a bi-directional check when resolving identity from did
|
|
16
|
+
|
|
17
|
+
- [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Allow non-normalized handles in did documents
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47), [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47)]:
|
|
20
|
+
- @atproto-labs/handle-resolver@0.3.0
|
|
21
|
+
|
|
3
22
|
## 0.1.19
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-resolver-error.d.ts","sourceRoot":"","sources":["../src/identity-resolver-error.ts"],"names":[],"mappings":"AAAA,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,IAAI,SAA0B;CAC/B"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IdentityResolverError = void 0;
|
|
4
|
+
class IdentityResolverError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
Object.defineProperty(this, "name", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: 'IdentityResolverError'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.IdentityResolverError = IdentityResolverError;
|
|
16
|
+
//# sourceMappingURL=identity-resolver-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-resolver-error.js","sourceRoot":"","sources":["../src/identity-resolver-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,qBAAsB,SAAQ,KAAK;IAAhD;;QACE;;;;mBAAO,uBAAuB;WAAA;IAChC,CAAC;CAAA;AAFD,sDAEC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { DidDocument, DidResolver, ResolveDidOptions } from '@atproto-labs/did-resolver';
|
|
2
|
-
import {
|
|
1
|
+
import { AtprotoDid, AtprotoIdentityDidMethods, DidDocument, DidResolver, ResolveDidOptions } from '@atproto-labs/did-resolver';
|
|
2
|
+
import { HandleResolver, ResolveHandleOptions } from '@atproto-labs/handle-resolver';
|
|
3
3
|
export type ResolvedIdentity = {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
document: DidDocument<AtprotoIdentityDidMethods>;
|
|
5
|
+
/**
|
|
6
|
+
* Will be defined if the document contains a handle alias that resolves
|
|
7
|
+
* to the document's DID.
|
|
8
|
+
*/
|
|
6
9
|
handle?: string;
|
|
7
10
|
};
|
|
8
11
|
export type ResolveIdentityOptions = ResolveDidOptions & ResolveHandleOptions;
|
|
@@ -11,7 +14,9 @@ export declare class IdentityResolver {
|
|
|
11
14
|
readonly handleResolver: HandleResolver;
|
|
12
15
|
constructor(didResolver: DidResolver<AtprotoIdentityDidMethods>, handleResolver: HandleResolver);
|
|
13
16
|
resolve(input: string, options?: ResolveIdentityOptions): Promise<ResolvedIdentity>;
|
|
14
|
-
|
|
17
|
+
resolveFromDid(did: AtprotoDid, options?: ResolveDidOptions): Promise<ResolvedIdentity>;
|
|
18
|
+
resolveFromHandle(handle: string, options?: ResolveHandleOptions): Promise<ResolvedIdentity>;
|
|
19
|
+
getDocumentFromDid(did: AtprotoDid, options?: ResolveDidOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
|
|
15
20
|
getDocumentFromHandle(input: string, options?: ResolveHandleOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
|
|
16
21
|
}
|
|
17
22
|
//# sourceMappingURL=identity-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-resolver.d.ts","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"identity-resolver.d.ts","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,WAAW,EACX,WAAW,EACX,iBAAiB,EAElB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACL,cAAc,EACd,oBAAoB,EACrB,MAAM,+BAA+B,CAAA;AAItC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,CAAA;IAEhD;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GAAG,oBAAoB,CAAA;AAE7E,qBAAa,gBAAgB;IAEzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC;IAC5D,QAAQ,CAAC,cAAc,EAAE,cAAc;gBAD9B,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC,EACnD,cAAc,EAAE,cAAc;IAG5B,OAAO,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAMf,cAAc,CACzB,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC;IAoBf,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,gBAAgB,CAAC;IAWf,kBAAkB,CAC7B,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;IAIrC,qBAAqB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;CA8BnD"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IdentityResolver = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const did_resolver_1 = require("@atproto-labs/did-resolver");
|
|
5
|
+
const identity_resolver_error_1 = require("./identity-resolver-error");
|
|
6
|
+
const util_1 = require("./util");
|
|
6
7
|
class IdentityResolver {
|
|
7
8
|
constructor(didResolver, handleResolver) {
|
|
8
9
|
Object.defineProperty(this, "didResolver", {
|
|
@@ -19,57 +20,56 @@ class IdentityResolver {
|
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
async resolve(input, options) {
|
|
22
|
-
|
|
23
|
-
?
|
|
24
|
-
:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
return (0, did_resolver_1.isAtprotoDid)(input)
|
|
24
|
+
? this.resolveFromDid(input, options)
|
|
25
|
+
: this.resolveFromHandle(input, options);
|
|
26
|
+
}
|
|
27
|
+
async resolveFromDid(did, options) {
|
|
28
|
+
const document = await this.getDocumentFromDid(did, options);
|
|
29
|
+
options?.signal?.throwIfAborted();
|
|
30
|
+
// We will only return the document's handle alias if it resolves to the
|
|
31
|
+
// same DID as the input.
|
|
32
|
+
const handle = (0, util_1.extractNormalizedHandle)(document);
|
|
33
|
+
const resolvedDid = handle
|
|
34
|
+
? await this.handleResolver
|
|
35
|
+
.resolve(handle, options)
|
|
36
|
+
.catch(() => undefined) // Ignore errors (temporarily unavailable)
|
|
37
|
+
: undefined;
|
|
38
|
+
return {
|
|
39
|
+
document,
|
|
40
|
+
handle: resolvedDid === did ? handle : undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async resolveFromHandle(handle, options) {
|
|
44
|
+
const document = await this.getDocumentFromHandle(handle, options);
|
|
45
|
+
// @NOTE bi-directional resolution enforced in getDocumentFromHandle()
|
|
29
46
|
return {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
handle: extractHandle(document),
|
|
47
|
+
document,
|
|
48
|
+
handle: (0, util_1.extractNormalizedHandle)(document),
|
|
33
49
|
};
|
|
34
50
|
}
|
|
35
51
|
async getDocumentFromDid(did, options) {
|
|
36
52
|
return this.didResolver.resolve(did, options);
|
|
37
53
|
}
|
|
38
54
|
async getDocumentFromHandle(input, options) {
|
|
39
|
-
const handle = (0,
|
|
55
|
+
const handle = (0, util_1.asNormalizedHandle)(input);
|
|
56
|
+
if (!handle) {
|
|
57
|
+
throw new identity_resolver_error_1.IdentityResolverError(`Invalid handle "${input}" provided.`);
|
|
58
|
+
}
|
|
40
59
|
const did = await this.handleResolver.resolve(handle, options);
|
|
41
60
|
if (!did) {
|
|
42
|
-
throw new
|
|
61
|
+
throw new identity_resolver_error_1.IdentityResolverError(`Handle "${handle}" does not resolve to a DID`);
|
|
43
62
|
}
|
|
44
63
|
options?.signal?.throwIfAborted();
|
|
45
64
|
// Note: Not using "return this.resolveDid(did, options)" to make the extra
|
|
46
65
|
// check for the handle in the DID document:
|
|
47
66
|
const document = await this.didResolver.resolve(did, options);
|
|
48
|
-
//
|
|
49
|
-
if (
|
|
50
|
-
throw new
|
|
67
|
+
// Enforce bi-directional resolution
|
|
68
|
+
if (handle !== (0, util_1.extractNormalizedHandle)(document)) {
|
|
69
|
+
throw new identity_resolver_error_1.IdentityResolverError(`Did document for "${did}" does not include the handle "${handle}"`);
|
|
51
70
|
}
|
|
52
71
|
return document;
|
|
53
72
|
}
|
|
54
73
|
}
|
|
55
74
|
exports.IdentityResolver = IdentityResolver;
|
|
56
|
-
function extractHandle(document) {
|
|
57
|
-
if (document.alsoKnownAs) {
|
|
58
|
-
for (const h of document.alsoKnownAs) {
|
|
59
|
-
if (h.startsWith('at://')) {
|
|
60
|
-
const handle = h.slice(5);
|
|
61
|
-
if ((0, syntax_1.isValidHandle)(handle))
|
|
62
|
-
return handle;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
function isAtprotoPersonalDataServerService(s) {
|
|
69
|
-
return (typeof s.serviceEndpoint === 'string' &&
|
|
70
|
-
s.type === 'AtprotoPersonalDataServer' &&
|
|
71
|
-
(s.id.startsWith('#')
|
|
72
|
-
? s.id === '#atproto_pds'
|
|
73
|
-
: s.id === `${this.id}#atproto_pds`));
|
|
74
|
-
}
|
|
75
75
|
//# sourceMappingURL=identity-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-resolver.js","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"identity-resolver.js","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":";;;AAAA,6DAOmC;AAKnC,uEAAiE;AACjE,iCAAoE;AAcpE,MAAa,gBAAgB;IAC3B,YACW,WAAmD,EACnD,cAA8B;QADvC;;;;mBAAS,WAAW;WAAwC;QAC5D;;;;mBAAS,cAAc;WAAgB;IACtC,CAAC;IAEG,KAAK,CAAC,OAAO,CAClB,KAAa,EACb,OAAgC;QAEhC,OAAO,IAAA,2BAAY,EAAC,KAAK,CAAC;YACxB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC;YACrC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;IAEM,KAAK,CAAC,cAAc,CACzB,GAAe,EACf,OAA2B;QAE3B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAE5D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA;QAEjC,wEAAwE;QACxE,yBAAyB;QACzB,MAAM,MAAM,GAAG,IAAA,8BAAuB,EAAC,QAAQ,CAAC,CAAA;QAChD,MAAM,WAAW,GAAG,MAAM;YACxB,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc;iBACtB,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;iBACxB,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,0CAA0C;YACtE,CAAC,CAAC,SAAS,CAAA;QAEb,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,WAAW,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SACjD,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAC5B,MAAc,EACd,OAA8B;QAE9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAElE,sEAAsE;QAEtE,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,IAAA,8BAAuB,EAAC,QAAQ,CAAC;SAC1C,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,GAAe,EACf,OAA2B;QAE3B,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC/C,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAChC,KAAa,EACb,OAA8B;QAE9B,MAAM,MAAM,GAAG,IAAA,yBAAkB,EAAC,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,+CAAqB,CAAC,mBAAmB,KAAK,aAAa,CAAC,CAAA;QACxE,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAE9D,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,+CAAqB,CAC7B,WAAW,MAAM,6BAA6B,CAC/C,CAAA;QACH,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA;QAEjC,2EAA2E;QAC3E,4CAA4C;QAE5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAE7D,oCAAoC;QACpC,IAAI,MAAM,KAAK,IAAA,8BAAuB,EAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,+CAAqB,CAC7B,qBAAqB,GAAG,kCAAkC,MAAM,GAAG,CACpE,CAAA;QACH,CAAC;QAED,OAAO,QAAQ,CAAA;IACjB,CAAC;CACF;AA5FD,4CA4FC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -14,5 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./identity-resolver-error.js"), exports);
|
|
17
18
|
__exportStar(require("./identity-resolver.js"), exports);
|
|
19
|
+
__exportStar(require("./util.js"), exports);
|
|
18
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAsC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+DAA4C;AAC5C,yDAAsC;AACtC,4CAAyB"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AtprotoIdentityDidMethods, DidDocument } from '@atproto-labs/did-resolver';
|
|
2
|
+
/**
|
|
3
|
+
* Extract the raw, un-validated, Atproto handle from a DID document.
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractAtprotoHandle(document: DidDocument<AtprotoIdentityDidMethods>): string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts a validated, normalized Atproto handle from a DID document.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractNormalizedHandle(document: DidDocument<AtprotoIdentityDidMethods>): string | undefined;
|
|
10
|
+
export declare function asNormalizedHandle(input: string): string | undefined;
|
|
11
|
+
export declare function normalizeHandle(handle: string): string;
|
|
12
|
+
export declare function isValidHandle(handle: string): boolean;
|
|
13
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,WAAW,EACZ,MAAM,4BAA4B,CAAA;AAEnC;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,GAC/C,MAAM,GAAG,SAAS,CAUpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,GAC/C,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQrD"}
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractAtprotoHandle = extractAtprotoHandle;
|
|
4
|
+
exports.extractNormalizedHandle = extractNormalizedHandle;
|
|
5
|
+
exports.asNormalizedHandle = asNormalizedHandle;
|
|
6
|
+
exports.normalizeHandle = normalizeHandle;
|
|
7
|
+
exports.isValidHandle = isValidHandle;
|
|
8
|
+
/**
|
|
9
|
+
* Extract the raw, un-validated, Atproto handle from a DID document.
|
|
10
|
+
*/
|
|
11
|
+
function extractAtprotoHandle(document) {
|
|
12
|
+
if (document.alsoKnownAs) {
|
|
13
|
+
for (const h of document.alsoKnownAs) {
|
|
14
|
+
if (h.startsWith('at://')) {
|
|
15
|
+
// strip off "at://" prefix
|
|
16
|
+
return h.slice(5);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extracts a validated, normalized Atproto handle from a DID document.
|
|
24
|
+
*/
|
|
25
|
+
function extractNormalizedHandle(document) {
|
|
26
|
+
const handle = extractAtprotoHandle(document);
|
|
27
|
+
if (!handle)
|
|
28
|
+
return undefined;
|
|
29
|
+
return asNormalizedHandle(handle);
|
|
30
|
+
}
|
|
31
|
+
function asNormalizedHandle(input) {
|
|
32
|
+
const handle = normalizeHandle(input);
|
|
33
|
+
return isValidHandle(handle) ? handle : undefined;
|
|
34
|
+
}
|
|
35
|
+
function normalizeHandle(handle) {
|
|
36
|
+
return handle.toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
function isValidHandle(handle) {
|
|
39
|
+
return (handle.length > 0 &&
|
|
40
|
+
handle.length < 254 &&
|
|
41
|
+
/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(handle));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAQA,oDAYC;AAKD,0DAMC;AAED,gDAGC;AAED,0CAEC;AAED,sCAQC;AA7CD;;GAEG;AACH,SAAgB,oBAAoB,CAClC,QAAgD;IAEhD,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,2BAA2B;gBAC3B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CACrC,QAAgD;IAEhD,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7B,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACrC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;AACnD,CAAC;AAED,SAAgB,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM,CAAC,WAAW,EAAE,CAAA;AAC7B,CAAC;AAED,SAAgB,aAAa,CAAC,MAAc;IAC1C,OAAO,CACL,MAAM,CAAC,MAAM,GAAG,CAAC;QACjB,MAAM,CAAC,MAAM,GAAG,GAAG;QACnB,4FAA4F,CAAC,IAAI,CAC/F,MAAM,CACP,CACF,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto-labs/identity-resolver",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "A library resolving ATPROTO identities",
|
|
6
6
|
"keywords": [
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@atproto-labs/did-resolver": "0.2.0",
|
|
29
|
-
"@atproto-labs/handle-resolver": "0.
|
|
30
|
-
"@atproto/syntax": "0.4.0"
|
|
29
|
+
"@atproto-labs/handle-resolver": "0.3.0"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"typescript": "^5.6.3"
|
package/src/identity-resolver.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { isValidHandle, normalizeAndEnsureValidHandle } from '@atproto/syntax'
|
|
2
1
|
import {
|
|
3
|
-
|
|
2
|
+
AtprotoDid,
|
|
3
|
+
AtprotoIdentityDidMethods,
|
|
4
4
|
DidDocument,
|
|
5
5
|
DidResolver,
|
|
6
|
-
DidService,
|
|
7
6
|
ResolveDidOptions,
|
|
7
|
+
isAtprotoDid,
|
|
8
8
|
} from '@atproto-labs/did-resolver'
|
|
9
9
|
import {
|
|
10
|
-
AtprotoIdentityDidMethods,
|
|
11
10
|
HandleResolver,
|
|
12
11
|
ResolveHandleOptions,
|
|
13
|
-
ResolvedHandle,
|
|
14
|
-
isResolvedHandle,
|
|
15
12
|
} from '@atproto-labs/handle-resolver'
|
|
13
|
+
import { IdentityResolverError } from './identity-resolver-error'
|
|
14
|
+
import { asNormalizedHandle, extractNormalizedHandle } from './util'
|
|
16
15
|
|
|
17
16
|
export type ResolvedIdentity = {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
document: DidDocument<AtprotoIdentityDidMethods>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Will be defined if the document contains a handle alias that resolves
|
|
21
|
+
* to the document's DID.
|
|
22
|
+
*/
|
|
20
23
|
handle?: string
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -32,30 +35,50 @@ export class IdentityResolver {
|
|
|
32
35
|
input: string,
|
|
33
36
|
options?: ResolveIdentityOptions,
|
|
34
37
|
): Promise<ResolvedIdentity> {
|
|
35
|
-
|
|
36
|
-
?
|
|
37
|
-
:
|
|
38
|
+
return isAtprotoDid(input)
|
|
39
|
+
? this.resolveFromDid(input, options)
|
|
40
|
+
: this.resolveFromHandle(input, options)
|
|
41
|
+
}
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
public async resolveFromDid(
|
|
44
|
+
did: AtprotoDid,
|
|
45
|
+
options?: ResolveDidOptions,
|
|
46
|
+
): Promise<ResolvedIdentity> {
|
|
47
|
+
const document = await this.getDocumentFromDid(did, options)
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
options?.signal?.throwIfAborted()
|
|
50
|
+
|
|
51
|
+
// We will only return the document's handle alias if it resolves to the
|
|
52
|
+
// same DID as the input.
|
|
53
|
+
const handle = extractNormalizedHandle(document)
|
|
54
|
+
const resolvedDid = handle
|
|
55
|
+
? await this.handleResolver
|
|
56
|
+
.resolve(handle, options)
|
|
57
|
+
.catch(() => undefined) // Ignore errors (temporarily unavailable)
|
|
58
|
+
: undefined
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
document,
|
|
62
|
+
handle: resolvedDid === did ? handle : undefined,
|
|
48
63
|
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public async resolveFromHandle(
|
|
67
|
+
handle: string,
|
|
68
|
+
options?: ResolveHandleOptions,
|
|
69
|
+
): Promise<ResolvedIdentity> {
|
|
70
|
+
const document = await this.getDocumentFromHandle(handle, options)
|
|
71
|
+
|
|
72
|
+
// @NOTE bi-directional resolution enforced in getDocumentFromHandle()
|
|
49
73
|
|
|
50
74
|
return {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
handle: extractHandle(document),
|
|
75
|
+
document,
|
|
76
|
+
handle: extractNormalizedHandle(document),
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
79
|
|
|
57
80
|
public async getDocumentFromDid(
|
|
58
|
-
did:
|
|
81
|
+
did: AtprotoDid,
|
|
59
82
|
options?: ResolveDidOptions,
|
|
60
83
|
): Promise<DidDocument<AtprotoIdentityDidMethods>> {
|
|
61
84
|
return this.didResolver.resolve(did, options)
|
|
@@ -65,12 +88,17 @@ export class IdentityResolver {
|
|
|
65
88
|
input: string,
|
|
66
89
|
options?: ResolveHandleOptions,
|
|
67
90
|
): Promise<DidDocument<AtprotoIdentityDidMethods>> {
|
|
68
|
-
const handle =
|
|
91
|
+
const handle = asNormalizedHandle(input)
|
|
92
|
+
if (!handle) {
|
|
93
|
+
throw new IdentityResolverError(`Invalid handle "${input}" provided.`)
|
|
94
|
+
}
|
|
69
95
|
|
|
70
96
|
const did = await this.handleResolver.resolve(handle, options)
|
|
71
97
|
|
|
72
98
|
if (!did) {
|
|
73
|
-
throw new
|
|
99
|
+
throw new IdentityResolverError(
|
|
100
|
+
`Handle "${handle}" does not resolve to a DID`,
|
|
101
|
+
)
|
|
74
102
|
}
|
|
75
103
|
|
|
76
104
|
options?.signal?.throwIfAborted()
|
|
@@ -80,9 +108,9 @@ export class IdentityResolver {
|
|
|
80
108
|
|
|
81
109
|
const document = await this.didResolver.resolve(did, options)
|
|
82
110
|
|
|
83
|
-
//
|
|
84
|
-
if (
|
|
85
|
-
throw new
|
|
111
|
+
// Enforce bi-directional resolution
|
|
112
|
+
if (handle !== extractNormalizedHandle(document)) {
|
|
113
|
+
throw new IdentityResolverError(
|
|
86
114
|
`Did document for "${did}" does not include the handle "${handle}"`,
|
|
87
115
|
)
|
|
88
116
|
}
|
|
@@ -90,35 +118,3 @@ export class IdentityResolver {
|
|
|
90
118
|
return document
|
|
91
119
|
}
|
|
92
120
|
}
|
|
93
|
-
|
|
94
|
-
function extractHandle(
|
|
95
|
-
document: DidDocument<AtprotoIdentityDidMethods>,
|
|
96
|
-
): string | undefined {
|
|
97
|
-
if (document.alsoKnownAs) {
|
|
98
|
-
for (const h of document.alsoKnownAs) {
|
|
99
|
-
if (h.startsWith('at://')) {
|
|
100
|
-
const handle = h.slice(5)
|
|
101
|
-
if (isValidHandle(handle)) return handle
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return undefined
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function isAtprotoPersonalDataServerService<M extends string>(
|
|
110
|
-
this: DidDocument<M>,
|
|
111
|
-
s: DidService,
|
|
112
|
-
): s is {
|
|
113
|
-
id: '#atproto_pds' | `${Did<M>}#atproto_pds`
|
|
114
|
-
type: 'AtprotoPersonalDataServer'
|
|
115
|
-
serviceEndpoint: string
|
|
116
|
-
} {
|
|
117
|
-
return (
|
|
118
|
-
typeof s.serviceEndpoint === 'string' &&
|
|
119
|
-
s.type === 'AtprotoPersonalDataServer' &&
|
|
120
|
-
(s.id.startsWith('#')
|
|
121
|
-
? s.id === '#atproto_pds'
|
|
122
|
-
: s.id === `${this.id}#atproto_pds`)
|
|
123
|
-
)
|
|
124
|
-
}
|
package/src/index.ts
CHANGED
package/src/util.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AtprotoIdentityDidMethods,
|
|
3
|
+
DidDocument,
|
|
4
|
+
} from '@atproto-labs/did-resolver'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extract the raw, un-validated, Atproto handle from a DID document.
|
|
8
|
+
*/
|
|
9
|
+
export function extractAtprotoHandle(
|
|
10
|
+
document: DidDocument<AtprotoIdentityDidMethods>,
|
|
11
|
+
): string | undefined {
|
|
12
|
+
if (document.alsoKnownAs) {
|
|
13
|
+
for (const h of document.alsoKnownAs) {
|
|
14
|
+
if (h.startsWith('at://')) {
|
|
15
|
+
// strip off "at://" prefix
|
|
16
|
+
return h.slice(5)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extracts a validated, normalized Atproto handle from a DID document.
|
|
25
|
+
*/
|
|
26
|
+
export function extractNormalizedHandle(
|
|
27
|
+
document: DidDocument<AtprotoIdentityDidMethods>,
|
|
28
|
+
): string | undefined {
|
|
29
|
+
const handle = extractAtprotoHandle(document)
|
|
30
|
+
if (!handle) return undefined
|
|
31
|
+
return asNormalizedHandle(handle)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function asNormalizedHandle(input: string): string | undefined {
|
|
35
|
+
const handle = normalizeHandle(input)
|
|
36
|
+
return isValidHandle(handle) ? handle : undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function normalizeHandle(handle: string): string {
|
|
40
|
+
return handle.toLowerCase()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isValidHandle(handle: string): boolean {
|
|
44
|
+
return (
|
|
45
|
+
handle.length > 0 &&
|
|
46
|
+
handle.length < 254 &&
|
|
47
|
+
/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(
|
|
48
|
+
handle,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/identity-resolver.ts","./src/index.ts"],"version":"5.8.2"}
|
|
1
|
+
{"root":["./src/identity-resolver-error.ts","./src/identity-resolver.ts","./src/index.ts","./src/util.ts"],"version":"5.8.2"}
|