@toa.io/extensions.exposition 1.0.0-alpha.282 → 1.0.0-alpha.283
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 +27 -0
- package/components/exposition.octets/manifest.toa.yaml +11 -0
- package/components/exposition.octets/types/index.d.ts +3 -0
- package/components/exposition.octets/types/toa.d.ts +41 -0
- package/components/identity.bans/types/index.d.ts +3 -0
- package/components/identity.bans/types/toa.d.ts +34 -0
- package/components/identity.basic/manifest.toa.yaml +13 -2
- package/components/identity.basic/operations/add.d.ts +3 -3
- package/components/identity.basic/operations/authenticate.d.ts +2 -2
- package/components/identity.basic/operations/check.d.ts +1 -1
- package/components/identity.basic/operations/delete.d.ts +2 -2
- package/components/identity.basic/operations/incept.d.ts +2 -2
- package/components/identity.basic/operations/info.d.ts +1 -1
- package/components/identity.basic/operations/transit.d.ts +4 -3
- package/components/identity.basic/operations/transit.js +2 -1
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/source/add.ts +3 -3
- package/components/identity.basic/source/authenticate.ts +2 -2
- package/components/identity.basic/source/check.ts +1 -1
- package/components/identity.basic/source/delete.ts +2 -2
- package/components/identity.basic/source/incept.ts +2 -2
- package/components/identity.basic/source/info.ts +1 -1
- package/components/identity.basic/source/transit.ts +6 -4
- package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/types/index.d.ts +21 -0
- package/components/identity.basic/types/toa.d.ts +121 -0
- package/components/identity.clients/manifest.toa.yaml +243 -0
- package/components/identity.clients/operations/describe.d.ts +27 -0
- package/components/identity.clients/operations/describe.js +44 -0
- package/components/identity.clients/operations/describe.js.map +1 -0
- package/components/identity.clients/operations/lib/Context.d.ts +29 -0
- package/components/identity.clients/operations/lib/Context.js +2 -0
- package/components/identity.clients/operations/lib/Context.js.map +1 -0
- package/components/identity.clients/operations/lib/Entity.d.ts +29 -0
- package/components/identity.clients/operations/lib/Entity.js +2 -0
- package/components/identity.clients/operations/lib/Entity.js.map +1 -0
- package/components/identity.clients/operations/lib/canonical.d.ts +11 -0
- package/components/identity.clients/operations/lib/canonical.js +24 -0
- package/components/identity.clients/operations/lib/canonical.js.map +1 -0
- package/components/identity.clients/operations/lib/cimd.d.ts +8 -0
- package/components/identity.clients/operations/lib/cimd.js +86 -0
- package/components/identity.clients/operations/lib/cimd.js.map +1 -0
- package/components/identity.clients/operations/lib/errors.d.ts +7 -0
- package/components/identity.clients/operations/lib/errors.js +5 -0
- package/components/identity.clients/operations/lib/errors.js.map +1 -0
- package/components/identity.clients/operations/lib/index.d.ts +6 -0
- package/components/identity.clients/operations/lib/index.js +7 -0
- package/components/identity.clients/operations/lib/index.js.map +1 -0
- package/components/identity.clients/operations/lib/redirect.d.ts +10 -0
- package/components/identity.clients/operations/lib/redirect.js +32 -0
- package/components/identity.clients/operations/lib/redirect.js.map +1 -0
- package/components/identity.clients/operations/register.d.ts +37 -0
- package/components/identity.clients/operations/register.js +84 -0
- package/components/identity.clients/operations/register.js.map +1 -0
- package/components/identity.clients/source/describe.ts +65 -0
- package/components/identity.clients/source/lib/Context.ts +38 -0
- package/components/identity.clients/source/lib/Entity.ts +31 -0
- package/components/identity.clients/source/lib/canonical.test.ts +43 -0
- package/components/identity.clients/source/lib/canonical.ts +27 -0
- package/components/identity.clients/source/lib/cimd.test.ts +120 -0
- package/components/identity.clients/source/lib/cimd.ts +107 -0
- package/components/identity.clients/source/lib/errors.ts +4 -0
- package/components/identity.clients/source/lib/index.ts +6 -0
- package/components/identity.clients/source/lib/redirect.test.ts +41 -0
- package/components/identity.clients/source/lib/redirect.ts +35 -0
- package/components/identity.clients/source/register.ts +125 -0
- package/components/identity.clients/tsconfig.json +10 -0
- package/components/identity.clients/tsconfig.tsbuildinfo +1 -0
- package/components/identity.clients/types/index.d.ts +3 -0
- package/components/identity.clients/types/toa.d.ts +109 -0
- package/components/identity.credentials/operations/list.d.ts +2 -1
- package/components/identity.credentials/operations/list.js.map +1 -1
- package/components/identity.credentials/source/list.ts +2 -1
- package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
- package/components/identity.credentials/types/index.d.ts +3 -0
- package/components/identity.credentials/types/toa.d.ts +30 -0
- package/components/identity.federation/manifest.toa.yaml +37 -1
- package/components/identity.federation/operations/authenticate.d.ts +1 -1
- package/components/identity.federation/operations/lib/Ctx.d.ts +2 -2
- package/components/identity.federation/operations/lib/decode.js +22 -8
- package/components/identity.federation/operations/lib/decode.js.map +1 -1
- package/components/identity.federation/operations/lib/errors.d.ts +7 -0
- package/components/identity.federation/operations/lib/errors.js +4 -0
- package/components/identity.federation/operations/lib/errors.js.map +1 -1
- package/components/identity.federation/operations/lib/exchange.js +11 -6
- package/components/identity.federation/operations/lib/exchange.js.map +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +1 -1
- package/components/identity.federation/operations/types/context.d.ts +3 -2
- package/components/identity.federation/source/authenticate.ts +1 -1
- package/components/identity.federation/source/lib/Ctx.ts +2 -2
- package/components/identity.federation/source/lib/decode.ts +25 -9
- package/components/identity.federation/source/lib/errors.ts +5 -0
- package/components/identity.federation/source/lib/exchange.ts +11 -7
- package/components/identity.federation/source/types/configuration.ts +1 -1
- package/components/identity.federation/source/types/context.ts +3 -2
- package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/types/index.d.ts +3 -0
- package/components/identity.federation/types/toa.d.ts +127 -0
- package/components/identity.grants/manifest.toa.yaml +245 -0
- package/components/identity.grants/operations/authorize.d.ts +35 -0
- package/components/identity.grants/operations/authorize.js +54 -0
- package/components/identity.grants/operations/authorize.js.map +1 -0
- package/components/identity.grants/operations/exchange.d.ts +37 -0
- package/components/identity.grants/operations/exchange.js +89 -0
- package/components/identity.grants/operations/exchange.js.map +1 -0
- package/components/identity.grants/operations/lib/code.d.ts +15 -0
- package/components/identity.grants/operations/lib/code.js +30 -0
- package/components/identity.grants/operations/lib/code.js.map +1 -0
- package/components/identity.grants/operations/lib/identify.d.ts +6 -0
- package/components/identity.grants/operations/lib/identify.js +15 -0
- package/components/identity.grants/operations/lib/identify.js.map +1 -0
- package/components/identity.grants/operations/lib/index.d.ts +3 -0
- package/components/identity.grants/operations/lib/index.js +3 -0
- package/components/identity.grants/operations/lib/index.js.map +1 -0
- package/components/identity.grants/operations/list.d.ts +13 -0
- package/components/identity.grants/operations/list.js +18 -0
- package/components/identity.grants/operations/list.js.map +1 -0
- package/components/identity.grants/operations/revoke.d.ts +18 -0
- package/components/identity.grants/operations/revoke.js +25 -0
- package/components/identity.grants/operations/revoke.js.map +1 -0
- package/components/identity.grants/source/authorize.ts +90 -0
- package/components/identity.grants/source/exchange.ts +130 -0
- package/components/identity.grants/source/lib/code.ts +39 -0
- package/components/identity.grants/source/lib/identify.ts +16 -0
- package/components/identity.grants/source/lib/index.ts +3 -0
- package/components/identity.grants/source/list.ts +28 -0
- package/components/identity.grants/source/revoke.ts +38 -0
- package/components/identity.grants/tsconfig.json +10 -0
- package/components/identity.grants/tsconfig.tsbuildinfo +1 -0
- package/components/identity.grants/types/index.d.ts +60 -0
- package/components/identity.grants/types/toa.d.ts +108 -0
- package/components/identity.keys/manifest.toa.yaml +1 -0
- package/components/identity.keys/operations/create.d.ts +1 -1
- package/components/identity.keys/operations/revoke.d.ts +1 -1
- package/components/identity.keys/source/create.ts +1 -1
- package/components/identity.keys/source/revoke.ts +1 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.keys/types/index.d.ts +3 -0
- package/components/identity.keys/types/toa.d.ts +47 -0
- package/components/identity.otp/operations/lib/Context.d.ts +4 -2
- package/components/identity.otp/source/lib/Context.ts +4 -2
- package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/types/index.d.ts +3 -0
- package/components/identity.otp/types/toa.d.ts +56 -0
- package/components/identity.passkeys/manifest.toa.yaml +3 -0
- package/components/identity.passkeys/operations/authenticate.d.ts +1 -1
- package/components/identity.passkeys/operations/challenge.d.ts +1 -1
- package/components/identity.passkeys/operations/create.d.ts +1 -1
- package/components/identity.passkeys/operations/types/Context.d.ts +2 -1
- package/components/identity.passkeys/operations/use.d.ts +1 -1
- package/components/identity.passkeys/source/authenticate.ts +1 -1
- package/components/identity.passkeys/source/challenge.ts +1 -1
- package/components/identity.passkeys/source/create.ts +1 -1
- package/components/identity.passkeys/source/types/Context.ts +2 -1
- package/components/identity.passkeys/source/use.ts +1 -1
- package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/types/index.d.ts +3 -0
- package/components/identity.passkeys/types/toa.d.ts +120 -0
- package/components/identity.roles/operations/principal.d.ts +1 -1
- package/components/identity.roles/source/principal.ts +1 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/types/index.d.ts +3 -0
- package/components/identity.roles/types/toa.d.ts +43 -0
- package/components/identity.tokens/manifest.toa.yaml +34 -3
- package/components/identity.tokens/operations/authenticate.d.ts +2 -1
- package/components/identity.tokens/operations/authenticate.js +8 -0
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.d.ts +2 -1
- package/components/identity.tokens/operations/decrypt.js +2 -2
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.d.ts +2 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/issue.d.ts +2 -1
- package/components/identity.tokens/operations/issue.js +2 -1
- package/components/identity.tokens/operations/issue.js.map +1 -1
- package/components/identity.tokens/operations/lib/form.d.ts +8 -0
- package/components/identity.tokens/operations/lib/form.js +24 -0
- package/components/identity.tokens/operations/lib/form.js.map +1 -0
- package/components/identity.tokens/operations/lib/index.d.ts +2 -1
- package/components/identity.tokens/operations/lib/index.js +1 -1
- package/components/identity.tokens/operations/lib/index.js.map +1 -1
- package/components/identity.tokens/source/authenticate.test.ts +8 -5
- package/components/identity.tokens/source/authenticate.ts +12 -1
- package/components/identity.tokens/source/decrypt.test.ts +1 -1
- package/components/identity.tokens/source/decrypt.ts +4 -3
- package/components/identity.tokens/source/encrypt.test.ts +1 -1
- package/components/identity.tokens/source/encrypt.ts +2 -1
- package/components/identity.tokens/source/issue.test.ts +71 -0
- package/components/identity.tokens/source/issue.ts +4 -2
- package/components/identity.tokens/source/lib/form.test.ts +25 -0
- package/components/identity.tokens/source/lib/form.ts +31 -0
- package/components/identity.tokens/source/lib/index.ts +2 -1
- package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/types/index.d.ts +61 -0
- package/components/identity.tokens/types/toa.d.ts +113 -0
- package/documentation/cache.md +10 -1
- package/documentation/consent.md +101 -0
- package/documentation/identity.md +3 -1
- package/documentation/io.md +36 -2
- package/documentation/oauth.md +179 -0
- package/documentation/protocol.md +4 -0
- package/features/auth.bearer.feature +120 -0
- package/features/cache.feature +46 -0
- package/features/oauth.clients.feature +195 -0
- package/features/oauth.discovery.feature +165 -0
- package/features/oauth.grants.feature +286 -0
- package/features/steps/Gateway.ts +6 -1
- package/features/steps/Parameters.ts +4 -0
- package/features/steps/components/echo/manifest.toa.yaml +2 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +2 -0
- package/features/steps/components/octets.tester/operations/redirect.js +6 -1
- package/features/steps/components/users/manifest.toa.yaml +1 -0
- package/package.json +8 -6
- package/readme.md +3 -0
- package/schemas/annotation.cos.yaml +30 -0
- package/source/Annotation.ts +23 -0
- package/source/Factory.ts +1 -1
- package/source/HTTP/Server.ts +9 -5
- package/source/HTTP/formats/form.ts +21 -0
- package/source/HTTP/formats/index.ts +17 -2
- package/source/HTTP/messages.test.ts +25 -1
- package/source/HTTP/messages.ts +10 -3
- package/source/Interception.ts +8 -2
- package/source/deployment.ts +4 -1
- package/source/directives/auth/Authorization.ts +46 -19
- package/source/directives/auth/Incept.ts +14 -9
- package/source/directives/auth/schemes.test.ts +8 -4
- package/source/directives/auth/schemes.ts +22 -9
- package/source/directives/auth/types.ts +5 -2
- package/source/directives/cache/Cache.ts +13 -4
- package/source/directives/cache/Control.ts +0 -3
- package/source/directives/flow/Fetch.ts +1 -1
- package/source/directives/index.ts +2 -1
- package/source/directives/io/IO.ts +2 -0
- package/source/directives/io/Output.ts +4 -1
- package/source/directives/io/Status.test.ts +84 -0
- package/source/directives/io/Status.ts +46 -0
- package/source/directives/oauth/Discovery.ts +76 -0
- package/source/directives/oauth/documents.ts +113 -0
- package/source/directives/oauth/index.ts +3 -0
- package/source/directives/octets/Delete.ts +1 -1
- package/source/directives/octets/Get.ts +1 -1
- package/source/directives/octets/Workflow.ts +1 -1
- package/source/directives/octets/workflows/Execution.ts +1 -1
- package/source/index.ts +6 -0
- package/source/octets.d.ts +17 -0
- package/source/userland.ts +47 -0
- package/transpiled/Annotation.d.ts +17 -0
- package/transpiled/Factory.js +1 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +4 -1
- package/transpiled/HTTP/Server.js +4 -3
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/formats/form.d.ts +9 -0
- package/transpiled/HTTP/formats/form.js +18 -0
- package/transpiled/HTTP/formats/form.js.map +1 -0
- package/transpiled/HTTP/formats/index.d.ts +10 -2
- package/transpiled/HTTP/formats/index.js +10 -0
- package/transpiled/HTTP/formats/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +6 -0
- package/transpiled/HTTP/messages.js +3 -3
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Interception.d.ts +4 -1
- package/transpiled/Interception.js +4 -2
- package/transpiled/Interception.js.map +1 -1
- package/transpiled/deployment.js +2 -0
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.d.ts +1 -1
- package/transpiled/directives/auth/Authorization.js +38 -18
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Incept.d.ts +1 -1
- package/transpiled/directives/auth/Incept.js +11 -7
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/schemes.d.ts +16 -4
- package/transpiled/directives/auth/schemes.js +20 -8
- package/transpiled/directives/auth/schemes.js.map +1 -1
- package/transpiled/directives/auth/types.d.ts +4 -2
- package/transpiled/directives/cache/Cache.js +9 -2
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.js +0 -2
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/index.js +2 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/IO.js +2 -0
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/io/Output.js +4 -1
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/io/Status.d.ts +19 -0
- package/transpiled/directives/io/Status.js +34 -0
- package/transpiled/directives/io/Status.js.map +1 -0
- package/transpiled/directives/oauth/Discovery.d.ts +23 -0
- package/transpiled/directives/oauth/Discovery.js +58 -0
- package/transpiled/directives/oauth/Discovery.js.map +1 -0
- package/transpiled/directives/oauth/documents.d.ts +9 -0
- package/transpiled/directives/oauth/documents.js +82 -0
- package/transpiled/directives/oauth/documents.js.map +1 -0
- package/transpiled/directives/oauth/index.d.ts +2 -0
- package/transpiled/directives/oauth/index.js +3 -0
- package/transpiled/directives/oauth/index.js.map +1 -0
- package/transpiled/index.d.ts +2 -0
- package/transpiled/userland.d.ts +39 -0
- package/transpiled/userland.js +7 -0
- package/transpiled/userland.js.map +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +0 -61
- package/components/identity.basic/operations/types.js +0 -2
- package/components/identity.basic/operations/types.js.map +0 -1
- package/components/identity.basic/source/types.ts +0 -69
- package/components/identity.tokens/operations/lib/types.d.ts +0 -88
- package/components/identity.tokens/operations/lib/types.js +0 -2
- package/components/identity.tokens/operations/lib/types.js.map +0 -1
- package/components/identity.tokens/source/lib/types.ts +0 -102
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
namespace: identity
|
|
2
|
+
name: clients
|
|
3
|
+
|
|
4
|
+
# A registration is addressed by the hash of what it says, so the same metadata is the
|
|
5
|
+
# same client however many times it arrives. `associated` is what lets a transition create
|
|
6
|
+
# the record at an id decided outside the storage.
|
|
7
|
+
entity:
|
|
8
|
+
associated: true
|
|
9
|
+
schema:
|
|
10
|
+
type: object
|
|
11
|
+
properties:
|
|
12
|
+
authority:
|
|
13
|
+
type: string
|
|
14
|
+
name:
|
|
15
|
+
description: client_name
|
|
16
|
+
type: string
|
|
17
|
+
maxLength: 128
|
|
18
|
+
uris:
|
|
19
|
+
description: redirect_uris
|
|
20
|
+
type: array
|
|
21
|
+
minItems: 1
|
|
22
|
+
maxItems: 8
|
|
23
|
+
items:
|
|
24
|
+
type: string
|
|
25
|
+
maxLength: 2048
|
|
26
|
+
uri:
|
|
27
|
+
description: client_uri
|
|
28
|
+
type: string
|
|
29
|
+
maxLength: 2048
|
|
30
|
+
logo:
|
|
31
|
+
description: logo_uri
|
|
32
|
+
type: string
|
|
33
|
+
maxLength: 2048
|
|
34
|
+
scope:
|
|
35
|
+
type: string
|
|
36
|
+
maxLength: 512
|
|
37
|
+
expires:
|
|
38
|
+
description: When a registration nothing has used is swept
|
|
39
|
+
type: number
|
|
40
|
+
required:
|
|
41
|
+
- authority
|
|
42
|
+
- uris
|
|
43
|
+
index:
|
|
44
|
+
authority:
|
|
45
|
+
authority: asc
|
|
46
|
+
|
|
47
|
+
operations:
|
|
48
|
+
transit:
|
|
49
|
+
concurrency: retry
|
|
50
|
+
input:
|
|
51
|
+
type: object
|
|
52
|
+
properties:
|
|
53
|
+
authority:
|
|
54
|
+
type: string
|
|
55
|
+
name:
|
|
56
|
+
type: string
|
|
57
|
+
uri:
|
|
58
|
+
type: string
|
|
59
|
+
logo:
|
|
60
|
+
type: string
|
|
61
|
+
scope:
|
|
62
|
+
type: string
|
|
63
|
+
uris:
|
|
64
|
+
type: array
|
|
65
|
+
items:
|
|
66
|
+
type: string
|
|
67
|
+
expires:
|
|
68
|
+
type: number
|
|
69
|
+
required:
|
|
70
|
+
- authority
|
|
71
|
+
- uris
|
|
72
|
+
|
|
73
|
+
register:
|
|
74
|
+
query: false
|
|
75
|
+
input:
|
|
76
|
+
type: object
|
|
77
|
+
properties:
|
|
78
|
+
authority:
|
|
79
|
+
type: string
|
|
80
|
+
client_name:
|
|
81
|
+
type: string
|
|
82
|
+
maxLength: 128
|
|
83
|
+
client_uri:
|
|
84
|
+
type: string
|
|
85
|
+
maxLength: 2048
|
|
86
|
+
logo_uri:
|
|
87
|
+
type: string
|
|
88
|
+
maxLength: 2048
|
|
89
|
+
redirect_uris:
|
|
90
|
+
type: array
|
|
91
|
+
minItems: 1
|
|
92
|
+
maxItems: 8
|
|
93
|
+
items:
|
|
94
|
+
type: string
|
|
95
|
+
maxLength: 2048
|
|
96
|
+
scope:
|
|
97
|
+
type: string
|
|
98
|
+
maxLength: 512
|
|
99
|
+
grant_types:
|
|
100
|
+
type: array
|
|
101
|
+
items:
|
|
102
|
+
type: string
|
|
103
|
+
response_types:
|
|
104
|
+
type: array
|
|
105
|
+
items:
|
|
106
|
+
type: string
|
|
107
|
+
token_endpoint_auth_method:
|
|
108
|
+
type: string
|
|
109
|
+
required:
|
|
110
|
+
- authority
|
|
111
|
+
- redirect_uris
|
|
112
|
+
# RFC 7591 §3.2.2 states a registration error as a body, not as a status of its own
|
|
113
|
+
output:
|
|
114
|
+
type: object
|
|
115
|
+
properties:
|
|
116
|
+
status:
|
|
117
|
+
description: Read and removed by `map:status`
|
|
118
|
+
type: number
|
|
119
|
+
client_id:
|
|
120
|
+
type: string
|
|
121
|
+
client_id_issued_at:
|
|
122
|
+
type: number
|
|
123
|
+
client_name:
|
|
124
|
+
type: string
|
|
125
|
+
client_uri:
|
|
126
|
+
type: string
|
|
127
|
+
logo_uri:
|
|
128
|
+
type: string
|
|
129
|
+
redirect_uris:
|
|
130
|
+
type: array
|
|
131
|
+
items:
|
|
132
|
+
type: string
|
|
133
|
+
grant_types:
|
|
134
|
+
type: array
|
|
135
|
+
items:
|
|
136
|
+
type: string
|
|
137
|
+
response_types:
|
|
138
|
+
type: array
|
|
139
|
+
items:
|
|
140
|
+
type: string
|
|
141
|
+
token_endpoint_auth_method:
|
|
142
|
+
type: string
|
|
143
|
+
error:
|
|
144
|
+
type: string
|
|
145
|
+
error_description:
|
|
146
|
+
type: string
|
|
147
|
+
|
|
148
|
+
describe:
|
|
149
|
+
query: false
|
|
150
|
+
input:
|
|
151
|
+
type: object
|
|
152
|
+
properties:
|
|
153
|
+
authority:
|
|
154
|
+
type: string
|
|
155
|
+
id:
|
|
156
|
+
description: client_id, which is an https URL when the client publishes its own metadata
|
|
157
|
+
type: string
|
|
158
|
+
maxLength: 2048
|
|
159
|
+
redirect:
|
|
160
|
+
description: Asked about together with the client, since only this component may answer it
|
|
161
|
+
type: string
|
|
162
|
+
maxLength: 2048
|
|
163
|
+
required:
|
|
164
|
+
- authority
|
|
165
|
+
- id
|
|
166
|
+
output:
|
|
167
|
+
type: object
|
|
168
|
+
properties:
|
|
169
|
+
client_id:
|
|
170
|
+
type: string
|
|
171
|
+
client_name:
|
|
172
|
+
type: string
|
|
173
|
+
client_uri:
|
|
174
|
+
type: string
|
|
175
|
+
logo_uri:
|
|
176
|
+
type: string
|
|
177
|
+
redirect_uris:
|
|
178
|
+
type: array
|
|
179
|
+
items:
|
|
180
|
+
type: string
|
|
181
|
+
permitted:
|
|
182
|
+
description: Whether `redirect` is one this client may receive a code at
|
|
183
|
+
type: boolean
|
|
184
|
+
errors:
|
|
185
|
+
- UNKNOWN_CLIENT
|
|
186
|
+
|
|
187
|
+
configuration:
|
|
188
|
+
schema:
|
|
189
|
+
type: object
|
|
190
|
+
properties:
|
|
191
|
+
trust:
|
|
192
|
+
description: Origins whose Client ID Metadata Documents may be read; none are without one
|
|
193
|
+
type: array
|
|
194
|
+
items:
|
|
195
|
+
type: string
|
|
196
|
+
pattern: ^https://
|
|
197
|
+
default: []
|
|
198
|
+
lifetime:
|
|
199
|
+
description: Seconds a Client ID Metadata Document is held before it is read again
|
|
200
|
+
type: integer
|
|
201
|
+
minimum: 1
|
|
202
|
+
default: 3600
|
|
203
|
+
ttl:
|
|
204
|
+
description: Seconds a registration nothing has used is kept
|
|
205
|
+
type: integer
|
|
206
|
+
minimum: 1
|
|
207
|
+
default: 2592000
|
|
208
|
+
size:
|
|
209
|
+
description: Bytes of a Client ID Metadata Document that are read
|
|
210
|
+
type: integer
|
|
211
|
+
minimum: 1
|
|
212
|
+
default: 16384
|
|
213
|
+
timeout:
|
|
214
|
+
description: Milliseconds a Client ID Metadata Document has to arrive
|
|
215
|
+
type: integer
|
|
216
|
+
minimum: 1
|
|
217
|
+
default: 3000
|
|
218
|
+
|
|
219
|
+
stash: ~
|
|
220
|
+
|
|
221
|
+
exposition:
|
|
222
|
+
isolated: true
|
|
223
|
+
/:
|
|
224
|
+
POST:
|
|
225
|
+
anonymous: true
|
|
226
|
+
map:authority: authority
|
|
227
|
+
io:input: [client_name, client_uri, logo_uri, redirect_uris, scope, grant_types, response_types, token_endpoint_auth_method]
|
|
228
|
+
io:output: true
|
|
229
|
+
io:throttle:
|
|
230
|
+
key: ip
|
|
231
|
+
requests: 10
|
|
232
|
+
interval: 3600
|
|
233
|
+
io:status: status
|
|
234
|
+
cache:exact: no-store
|
|
235
|
+
endpoint: register
|
|
236
|
+
/:id:
|
|
237
|
+
GET:
|
|
238
|
+
anyone: true
|
|
239
|
+
map:authority: authority
|
|
240
|
+
map:segments:
|
|
241
|
+
id: id
|
|
242
|
+
io:output: [client_id, client_name, client_uri, logo_uri, redirect_uris]
|
|
243
|
+
endpoint: describe
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Maybe } from '@toa.io/core';
|
|
2
|
+
import type { Operation } from '@toa.io/bridges.node';
|
|
3
|
+
import type { Client, Context } from './lib/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a client is, whichever way it came to be known: a `client_id` that is an https URL
|
|
6
|
+
* publishes its own metadata, and anything else was registered here. The caller is not told
|
|
7
|
+
* which, and neither mechanism is visible past this operation.
|
|
8
|
+
*
|
|
9
|
+
* Whether a redirect is one the client may receive a code at is answered here too. The rule
|
|
10
|
+
* is this component's — nothing else knows a loopback port is ignored — and asking for it
|
|
11
|
+
* with the client saves a second call on the path a person is waiting on.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Computation implements Operation {
|
|
14
|
+
private context;
|
|
15
|
+
mount(context: Context): void;
|
|
16
|
+
execute(input: Input): Promise<Maybe<Output>>;
|
|
17
|
+
private registered;
|
|
18
|
+
}
|
|
19
|
+
interface Input {
|
|
20
|
+
authority: string;
|
|
21
|
+
id: string;
|
|
22
|
+
redirect?: string;
|
|
23
|
+
}
|
|
24
|
+
interface Output extends Client {
|
|
25
|
+
permitted?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ERR_UNKNOWN_CLIENT, permits, read } from './lib/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* What a client is, whichever way it came to be known: a `client_id` that is an https URL
|
|
4
|
+
* publishes its own metadata, and anything else was registered here. The caller is not told
|
|
5
|
+
* which, and neither mechanism is visible past this operation.
|
|
6
|
+
*
|
|
7
|
+
* Whether a redirect is one the client may receive a code at is answered here too. The rule
|
|
8
|
+
* is this component's — nothing else knows a loopback port is ignored — and asking for it
|
|
9
|
+
* with the client saves a second call on the path a person is waiting on.
|
|
10
|
+
*/
|
|
11
|
+
export class Computation {
|
|
12
|
+
context;
|
|
13
|
+
mount(context) {
|
|
14
|
+
this.context = context;
|
|
15
|
+
}
|
|
16
|
+
async execute(input) {
|
|
17
|
+
const client = input.id.startsWith(HTTPS)
|
|
18
|
+
? await read(input.id, this.context)
|
|
19
|
+
: await this.registered(input);
|
|
20
|
+
if (client instanceof Error)
|
|
21
|
+
return client;
|
|
22
|
+
return {
|
|
23
|
+
...client,
|
|
24
|
+
...(input.redirect === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: { permitted: permits(client.redirect_uris, input.redirect) })
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async registered(input) {
|
|
30
|
+
const entity = await this.context.local.observe({ query: { id: input.id } });
|
|
31
|
+
// credentials are scoped to an authority, and so is what may act for them
|
|
32
|
+
if (entity === null || entity.authority !== input.authority)
|
|
33
|
+
return ERR_UNKNOWN_CLIENT;
|
|
34
|
+
return {
|
|
35
|
+
client_id: entity.id,
|
|
36
|
+
client_name: entity.name,
|
|
37
|
+
client_uri: entity.uri,
|
|
38
|
+
logo_uri: entity.logo,
|
|
39
|
+
redirect_uris: entity.uris
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const HTTPS = 'https://';
|
|
44
|
+
//# sourceMappingURL=describe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../source/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAKlE;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IACd,OAAO,CAAU;IAElB,KAAK,CAAE,OAAgB;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAE,KAAY;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC;YACvC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC;YACpC,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QAEhC,IAAI,MAAM,YAAY,KAAK;YACzB,OAAO,MAAM,CAAA;QAEf,OAAO;YACL,GAAG,MAAM;YACT,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;gBAC9B,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;SAClE,CAAA;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAE,KAAY;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAE5E,0EAA0E;QAC1E,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS;YACzD,OAAO,kBAAkB,CAAA;QAE3B,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,EAAE;YACpB,WAAW,EAAE,MAAM,CAAC,IAAI;YACxB,UAAU,EAAE,MAAM,CAAC,GAAG;YACtB,QAAQ,EAAE,MAAM,CAAC,IAAI;YACrB,aAAa,EAAE,MAAM,CAAC,IAAI;SAC3B,CAAA;IACH,CAAC;CACF;AAED,MAAM,KAAK,GAAG,UAAU,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Call, Observation, Transition } from '@toa.io/core';
|
|
2
|
+
import type { Stash } from '@toa.io/extensions.stash';
|
|
3
|
+
import type { Logs } from '@toa.io/extensions.telemetry';
|
|
4
|
+
import type { Entity } from './Entity.js';
|
|
5
|
+
export interface Context {
|
|
6
|
+
stash: Stash;
|
|
7
|
+
fetch: Fetch;
|
|
8
|
+
logs: Logs;
|
|
9
|
+
local: {
|
|
10
|
+
observe: Observation<Entity>;
|
|
11
|
+
transit: Call<Entity, TransitInput>;
|
|
12
|
+
};
|
|
13
|
+
configuration: Configuration;
|
|
14
|
+
}
|
|
15
|
+
export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
16
|
+
export type TransitInput = Omit<Entity, 'id' | '_created'>;
|
|
17
|
+
export interface Configuration {
|
|
18
|
+
/** Origins whose Client ID Metadata Documents may be read. Empty admits nobody. */
|
|
19
|
+
readonly trust: string[];
|
|
20
|
+
/** Seconds a document is held before it is read again. */
|
|
21
|
+
readonly lifetime: number;
|
|
22
|
+
/** Seconds a registration nothing has used is kept. */
|
|
23
|
+
readonly ttl: number;
|
|
24
|
+
/** Bytes of a document that are read. */
|
|
25
|
+
readonly size: number;
|
|
26
|
+
/** Milliseconds a document has to arrive. */
|
|
27
|
+
readonly timeout: number;
|
|
28
|
+
}
|
|
29
|
+
export type { Transition };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Context.js","sourceRoot":"","sources":["../../source/lib/Context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface Entity {
|
|
2
|
+
id: string;
|
|
3
|
+
authority: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
uris: string[];
|
|
6
|
+
uri?: string;
|
|
7
|
+
logo?: string;
|
|
8
|
+
scope?: string;
|
|
9
|
+
expires?: number;
|
|
10
|
+
_created?: number;
|
|
11
|
+
}
|
|
12
|
+
/** What a client says about itself, in the shape both mechanisms carry it. */
|
|
13
|
+
export interface Metadata {
|
|
14
|
+
client_name?: string;
|
|
15
|
+
client_uri?: string;
|
|
16
|
+
logo_uri?: string;
|
|
17
|
+
redirect_uris: string[];
|
|
18
|
+
scope?: string;
|
|
19
|
+
token_endpoint_auth_method?: string;
|
|
20
|
+
}
|
|
21
|
+
/** A client, however it came to be known. */
|
|
22
|
+
export interface Client {
|
|
23
|
+
client_id: string;
|
|
24
|
+
client_name?: string;
|
|
25
|
+
client_uri?: string;
|
|
26
|
+
logo_uri?: string;
|
|
27
|
+
redirect_uris: string[];
|
|
28
|
+
issued?: number;
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.js","sourceRoot":"","sources":["../../source/lib/Entity.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Metadata } from './Entity.js';
|
|
2
|
+
/**
|
|
3
|
+
* The id of a registration: a hash of what it says, so identical metadata is one client
|
|
4
|
+
* however many times it arrives. A client cannot remember that it registered here, and
|
|
5
|
+
* registers again on every fresh connection; without this the registry only grows.
|
|
6
|
+
*
|
|
7
|
+
* Only what is honoured is hashed. A field this component ignores would otherwise mint a
|
|
8
|
+
* client per release of whoever sends it, and the authority is in there because credentials
|
|
9
|
+
* are scoped to one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function identify(authority: string, metadata: Metadata): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* The id of a registration: a hash of what it says, so identical metadata is one client
|
|
4
|
+
* however many times it arrives. A client cannot remember that it registered here, and
|
|
5
|
+
* registers again on every fresh connection; without this the registry only grows.
|
|
6
|
+
*
|
|
7
|
+
* Only what is honoured is hashed. A field this component ignores would otherwise mint a
|
|
8
|
+
* client per release of whoever sends it, and the authority is in there because credentials
|
|
9
|
+
* are scoped to one.
|
|
10
|
+
*/
|
|
11
|
+
export function identify(authority, metadata) {
|
|
12
|
+
const canonical = JSON.stringify([
|
|
13
|
+
authority,
|
|
14
|
+
metadata.client_name ?? null,
|
|
15
|
+
metadata.client_uri ?? null,
|
|
16
|
+
metadata.logo_uri ?? null,
|
|
17
|
+
metadata.scope ?? null,
|
|
18
|
+
[...metadata.redirect_uris].sort()
|
|
19
|
+
]);
|
|
20
|
+
return createHash('sha256').update(canonical).digest('hex').slice(0, LENGTH);
|
|
21
|
+
}
|
|
22
|
+
/** What the entity prototype accepts as an id. */
|
|
23
|
+
const LENGTH = 32;
|
|
24
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../source/lib/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAE,SAAiB,EAAE,QAAkB;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC/B,SAAS;QACT,QAAQ,CAAC,WAAW,IAAI,IAAI;QAC5B,QAAQ,CAAC,UAAU,IAAI,IAAI;QAC3B,QAAQ,CAAC,QAAQ,IAAI,IAAI;QACzB,QAAQ,CAAC,KAAK,IAAI,IAAI;QACtB,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE;KACnC,CAAC,CAAA;IAEF,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AAC9E,CAAC;AAED,kDAAkD;AAClD,MAAM,MAAM,GAAG,EAAE,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Context } from './Context.js';
|
|
2
|
+
import type { Client } from './Entity.js';
|
|
3
|
+
/**
|
|
4
|
+
* A Client ID Metadata Document: the client publishes what it is at an https URL, and that
|
|
5
|
+
* URL is its `client_id`. Control of the origin is what proves the identity, so nothing is
|
|
6
|
+
* registered and nothing is written — the document is read and held for a while.
|
|
7
|
+
*/
|
|
8
|
+
export declare function read(id: string, context: Context): Promise<Client | Error>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { ERR_UNKNOWN_CLIENT } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* A Client ID Metadata Document: the client publishes what it is at an https URL, and that
|
|
5
|
+
* URL is its `client_id`. Control of the origin is what proves the identity, so nothing is
|
|
6
|
+
* registered and nothing is written — the document is read and held for a while.
|
|
7
|
+
*/
|
|
8
|
+
export async function read(id, context) {
|
|
9
|
+
// before anything is fetched: the id is the caller's to choose, and this runs inside
|
|
10
|
+
// the cluster. An origin the configuration does not name is not reached at all.
|
|
11
|
+
if (!trusted(id, context.configuration.trust))
|
|
12
|
+
return ERR_UNKNOWN_CLIENT;
|
|
13
|
+
const key = CACHE + createHash('sha256').update(id).digest('hex');
|
|
14
|
+
const cached = await context.stash.get(key);
|
|
15
|
+
if (cached !== null)
|
|
16
|
+
return cached === MISS ? ERR_UNKNOWN_CLIENT : JSON.parse(cached);
|
|
17
|
+
const client = await fetch(id, context);
|
|
18
|
+
// a document that does not answer is remembered too, or a bad id is fetched per request
|
|
19
|
+
await context.stash.set(key, client instanceof Error ? MISS : JSON.stringify(client), 'EX', context.configuration.lifetime);
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* An https URL whose origin the configuration names. Compared by origin so that a path on a
|
|
24
|
+
* trusted host cannot be escaped by one that merely starts the same way.
|
|
25
|
+
*/
|
|
26
|
+
function trusted(id, trust) {
|
|
27
|
+
let url;
|
|
28
|
+
try {
|
|
29
|
+
url = new URL(id);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (url.protocol !== 'https:')
|
|
35
|
+
return false;
|
|
36
|
+
return trust.some((origin) => {
|
|
37
|
+
try {
|
|
38
|
+
return new URL(origin).origin === url.origin;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function fetch(id, context) {
|
|
46
|
+
const { size, timeout } = context.configuration;
|
|
47
|
+
try {
|
|
48
|
+
const response = await context.fetch(id, {
|
|
49
|
+
redirect: 'error', // a redirect leaves the origin that was trusted
|
|
50
|
+
signal: AbortSignal.timeout(timeout),
|
|
51
|
+
headers: { accept: 'application/json' }
|
|
52
|
+
});
|
|
53
|
+
if (!response.ok)
|
|
54
|
+
return ERR_UNKNOWN_CLIENT;
|
|
55
|
+
const text = await response.text();
|
|
56
|
+
if (text.length > size)
|
|
57
|
+
return ERR_UNKNOWN_CLIENT;
|
|
58
|
+
return validate(id, JSON.parse(text));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
context.logs.debug('Client metadata document is unreadable', {
|
|
62
|
+
client: id,
|
|
63
|
+
error: error?.toString?.()
|
|
64
|
+
});
|
|
65
|
+
return ERR_UNKNOWN_CLIENT;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function validate(id, metadata) {
|
|
69
|
+
// the document names itself, so one client's cannot claim another's identity
|
|
70
|
+
if (metadata.client_id !== id)
|
|
71
|
+
return ERR_UNKNOWN_CLIENT;
|
|
72
|
+
if (!Array.isArray(metadata.redirect_uris) || metadata.redirect_uris.length === 0 ||
|
|
73
|
+
metadata.redirect_uris.some((uri) => typeof uri !== 'string'))
|
|
74
|
+
return ERR_UNKNOWN_CLIENT;
|
|
75
|
+
return {
|
|
76
|
+
client_id: id,
|
|
77
|
+
client_name: metadata.client_name,
|
|
78
|
+
client_uri: metadata.client_uri,
|
|
79
|
+
logo_uri: metadata.logo_uri,
|
|
80
|
+
redirect_uris: metadata.redirect_uris
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const CACHE = 'cimd:';
|
|
84
|
+
/** Held in place of a document that could not be read, so a bad id is not refetched. */
|
|
85
|
+
const MISS = '';
|
|
86
|
+
//# sourceMappingURL=cimd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd.js","sourceRoot":"","sources":["../../source/lib/cimd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../source/lib/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,kBAAmB,SAAQ,KAAK;IAC3D,IAAI,GAAG,gBAAgB,CAAA;IACd,OAAO,GAAG,gBAAgB,CAAA;CACpD,CAAC,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a client may receive a code at this address.
|
|
3
|
+
*
|
|
4
|
+
* Exact string comparison, which RFC 6749 §3.1.2.3 requires, except for a loopback
|
|
5
|
+
* address: a native client binds whatever port is free when it starts, so RFC 8252 §7.3
|
|
6
|
+
* has the port ignored there. Claude Code registers `http://localhost/callback` and
|
|
7
|
+
* `http://127.0.0.1/callback` and comes back on an ephemeral port; comparing those
|
|
8
|
+
* literally would refuse every one of them.
|
|
9
|
+
*/
|
|
10
|
+
export declare function permits(registered: string[], redirect: string): boolean;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a client may receive a code at this address.
|
|
3
|
+
*
|
|
4
|
+
* Exact string comparison, which RFC 6749 §3.1.2.3 requires, except for a loopback
|
|
5
|
+
* address: a native client binds whatever port is free when it starts, so RFC 8252 §7.3
|
|
6
|
+
* has the port ignored there. Claude Code registers `http://localhost/callback` and
|
|
7
|
+
* `http://127.0.0.1/callback` and comes back on an ephemeral port; comparing those
|
|
8
|
+
* literally would refuse every one of them.
|
|
9
|
+
*/
|
|
10
|
+
export function permits(registered, redirect) {
|
|
11
|
+
return registered.some((uri) => uri === redirect || loopback(uri, redirect));
|
|
12
|
+
}
|
|
13
|
+
function loopback(registered, redirect) {
|
|
14
|
+
const a = parse(registered);
|
|
15
|
+
const b = parse(redirect);
|
|
16
|
+
if (a === null || b === null)
|
|
17
|
+
return false;
|
|
18
|
+
return a.protocol === 'http:' && b.protocol === 'http:' &&
|
|
19
|
+
LOOPBACK.has(a.hostname) && a.hostname === b.hostname &&
|
|
20
|
+
a.pathname === b.pathname && a.search === b.search;
|
|
21
|
+
}
|
|
22
|
+
function parse(value) {
|
|
23
|
+
try {
|
|
24
|
+
return new URL(value);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** `localhost` resolves through the host's own configuration, which RFC 8252 §8.3 warns of. */
|
|
31
|
+
const LOOPBACK = new Set(['127.0.0.1', '[::1]', 'localhost']);
|
|
32
|
+
//# sourceMappingURL=redirect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.js","sourceRoot":"","sources":["../../source/lib/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAE,UAAoB,EAAE,QAAgB;IAC7D,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAA;AAC9E,CAAC;AAED,SAAS,QAAQ,CAAE,UAAkB,EAAE,QAAgB;IACrD,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;IAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;IAEzB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;QAC1B,OAAO,KAAK,CAAA;IAEd,OAAO,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;QACrD,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;QACrD,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAA;AACtD,CAAC;AAED,SAAS,KAAK,CAAE,KAAa;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,+FAA+F;AAC/F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Maybe } from '@toa.io/core';
|
|
2
|
+
import type { Operation } from '@toa.io/bridges.node';
|
|
3
|
+
import type { Context, Metadata } from './lib/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Dynamic Client Registration, RFC 7591: the client sends what it is and is given an
|
|
6
|
+
* identifier for it. Unauthenticated, as the specification has it — a registration grants
|
|
7
|
+
* nothing on its own, and stays inert until a user consents to the client on a page that
|
|
8
|
+
* shows them its name and where it would send them.
|
|
9
|
+
*
|
|
10
|
+
* The identifier is a hash of the metadata, so registering the same thing twice is the
|
|
11
|
+
* same client rather than another row. A client cannot remember it registered here.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Effect implements Operation {
|
|
14
|
+
private transit;
|
|
15
|
+
private ttl;
|
|
16
|
+
mount(context: Context): void;
|
|
17
|
+
execute(input: Input): Promise<Maybe<Output>>;
|
|
18
|
+
}
|
|
19
|
+
interface Input extends Metadata {
|
|
20
|
+
authority: string;
|
|
21
|
+
}
|
|
22
|
+
interface Output {
|
|
23
|
+
/** Read and removed by `map:status`; absent on a success, which answers 201. */
|
|
24
|
+
status?: number;
|
|
25
|
+
client_id?: string;
|
|
26
|
+
client_id_issued_at?: number;
|
|
27
|
+
client_name?: string;
|
|
28
|
+
client_uri?: string;
|
|
29
|
+
logo_uri?: string;
|
|
30
|
+
redirect_uris?: string[];
|
|
31
|
+
grant_types?: string[];
|
|
32
|
+
response_types?: string[];
|
|
33
|
+
token_endpoint_auth_method?: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
error_description?: string;
|
|
36
|
+
}
|
|
37
|
+
export {};
|