@awiki/dsh-pap 0.0.0-stage → 0.1.1

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.
Files changed (64) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +184 -2
  3. package/README.zh-CN.md +271 -0
  4. package/cordis.patch.yml +15 -0
  5. package/docs/verification.md +217 -0
  6. package/lib/auth-challenge.d.ts +19 -0
  7. package/lib/auth-challenge.js +136 -0
  8. package/lib/browser-client.js +81 -0
  9. package/lib/browser-client.js.map +6 -0
  10. package/lib/callback-handoff.d.ts +55 -0
  11. package/lib/callback-handoff.js +33 -0
  12. package/lib/client/controller.d.ts +107 -0
  13. package/lib/client/controller.js +106 -0
  14. package/lib/client/index.d.ts +6 -0
  15. package/lib/client/index.js +28 -0
  16. package/lib/client/views.d.ts +5 -0
  17. package/lib/client/views.js +57 -0
  18. package/lib/client.d.ts +108 -0
  19. package/lib/client.js +833 -0
  20. package/lib/cooldown.d.ts +11 -0
  21. package/lib/cooldown.js +88 -0
  22. package/lib/credential-history.d.ts +33 -0
  23. package/lib/credential-history.js +109 -0
  24. package/lib/delegation.d.ts +16 -0
  25. package/lib/delegation.js +59 -0
  26. package/lib/discovery.d.ts +8 -0
  27. package/lib/discovery.js +227 -0
  28. package/lib/errors.d.ts +14 -0
  29. package/lib/errors.js +17 -0
  30. package/lib/file-secrets.d.ts +14 -0
  31. package/lib/file-secrets.js +148 -0
  32. package/lib/host-secrets.d.ts +16 -0
  33. package/lib/host-secrets.js +22 -0
  34. package/lib/host.d.ts +83 -0
  35. package/lib/host.js +1 -0
  36. package/lib/index.d.ts +21 -0
  37. package/lib/index.js +13 -0
  38. package/lib/keyring.d.ts +10 -0
  39. package/lib/keyring.js +64 -0
  40. package/lib/management-remote.d.ts +13 -0
  41. package/lib/management-remote.js +69 -0
  42. package/lib/network.d.ts +23 -0
  43. package/lib/network.js +91 -0
  44. package/lib/plugin.d.ts +75 -0
  45. package/lib/plugin.js +473 -0
  46. package/lib/product-api.d.ts +89 -0
  47. package/lib/product-api.js +25 -0
  48. package/lib/product-operations.d.ts +16 -0
  49. package/lib/product-operations.js +120 -0
  50. package/lib/protocol-adapter.d.ts +90 -0
  51. package/lib/protocol-adapter.js +75 -0
  52. package/lib/remote.d.ts +3 -0
  53. package/lib/remote.js +17 -0
  54. package/lib/store.d.ts +14 -0
  55. package/lib/store.js +128 -0
  56. package/lib/strict-json.d.ts +2 -0
  57. package/lib/strict-json.js +111 -0
  58. package/lib/tools.d.ts +5 -0
  59. package/lib/tools.js +29 -0
  60. package/lib/types.d.ts +202 -0
  61. package/lib/types.js +1 -0
  62. package/lib/util.d.ts +17 -0
  63. package/lib/util.js +66 -0
  64. package/package.json +156 -4
@@ -0,0 +1,136 @@
1
+ import { responseHeader } from './cooldown.js';
2
+ import { httpsUrl, parseJson } from './util.js';
3
+ const token = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
4
+ const allowedErrors = new Set(['invalid_request', 'invalid_client', 'invalid_grant', 'invalid_scope', 'invalid_target', 'invalid_token', 'insufficient_scope', 'unauthorized_client', 'invalid_dpop_proof', 'use_dpop_nonce', 'invalid_session', 'session_ended', 'access_denied', 'extension_required']);
5
+ const challengeErrors = new Set(['invalid_request', 'invalid_client', 'invalid_grant', 'invalid_scope', 'invalid_target', 'invalid_token', 'insufficient_scope', 'unauthorized_client', 'invalid_dpop_proof', 'use_dpop_nonce', 'access_denied']);
6
+ function parameter(value) {
7
+ const equals = value.indexOf('=');
8
+ if (equals < 1)
9
+ return undefined;
10
+ const key = value.slice(0, equals).trim().toLowerCase();
11
+ const raw = value.slice(equals + 1).trim();
12
+ if (!token.test(key))
13
+ return undefined;
14
+ if (raw.startsWith('"')) {
15
+ let decoded = '';
16
+ let at = 1;
17
+ while (at < raw.length) {
18
+ const char = raw[at++];
19
+ if (char === '"')
20
+ return raw.slice(at).trim() === '' ? [key, decoded] : undefined;
21
+ if (char === '\\') {
22
+ if (at === raw.length)
23
+ return undefined;
24
+ decoded += raw[at++];
25
+ }
26
+ else
27
+ decoded += char;
28
+ }
29
+ return undefined;
30
+ }
31
+ return token.test(raw) ? [key, raw] : undefined;
32
+ }
33
+ export function parseAuthenticate(value) {
34
+ if (!value || value.length > 16384 || /[\x00-\x08\x0a-\x1f\x7f]/.test(value))
35
+ return { challenges: [], relevant: false };
36
+ const segments = [];
37
+ let start = 0;
38
+ let quoted = false;
39
+ let escaped = false;
40
+ for (let at = 0; at < value.length; at++) {
41
+ const char = value[at];
42
+ if (escaped) {
43
+ escaped = false;
44
+ continue;
45
+ }
46
+ if (quoted && char === '\\') {
47
+ escaped = true;
48
+ continue;
49
+ }
50
+ if (char === '"')
51
+ quoted = !quoted;
52
+ if (char === ',' && !quoted) {
53
+ segments.push(value.slice(start, at).trim());
54
+ start = at + 1;
55
+ }
56
+ }
57
+ if (quoted || escaped)
58
+ return { challenges: [], relevant: /\b(?:Bearer|DPoP)\b/i.test(value) };
59
+ segments.push(value.slice(start).trim());
60
+ const challenges = [];
61
+ let current;
62
+ let seen = new Set();
63
+ let relevant = false;
64
+ const take = (part) => { const parsed = parameter(part); if (!current)
65
+ return; if (!parsed || seen.has(parsed[0])) {
66
+ current.invalid = true;
67
+ return;
68
+ } seen.add(parsed[0]); const [key, content] = parsed; if (key === 'error')
69
+ current.error = content;
70
+ else if (key === 'scope')
71
+ current.scope = content;
72
+ else if (key === 'resource_metadata')
73
+ current.metadata = content; };
74
+ for (const part of segments) {
75
+ if (/^[!#$%&'*+.^_`|~0-9A-Za-z-]+[ \t]*=/.test(part)) {
76
+ take(part);
77
+ continue;
78
+ }
79
+ const match = part.match(/^([!#$%&'*+.^_`|~0-9A-Za-z-]+)(?:[ \t]+(.*))?$/);
80
+ current = undefined;
81
+ seen = new Set();
82
+ if (!match)
83
+ continue;
84
+ const scheme = match[1].toLowerCase();
85
+ if (scheme !== 'bearer' && scheme !== 'dpop')
86
+ continue;
87
+ relevant = true;
88
+ current = { scheme: scheme === 'dpop' ? 'DPoP' : 'Bearer', invalid: false };
89
+ challenges.push(current);
90
+ if (match[2])
91
+ take(match[2]);
92
+ }
93
+ return { challenges: challenges.filter(item => !item.invalid), relevant };
94
+ }
95
+ function metadataUrl(resource) { const url = httpsUrl(resource); return `${url.origin}/.well-known/oauth-protected-resource${url.pathname === '/' ? '' : url.pathname}`; }
96
+ function safeHint(challenge, company, resource) {
97
+ const hint = { scheme: challenge.scheme };
98
+ if (challenge.scope && challenge.scope.length <= 2048) {
99
+ const scopes = [...new Set(challenge.scope.split(' '))].sort();
100
+ if (scopes.length > 0 && scopes.length <= 64 && scopes.every(scope => /^[\x21\x23-\x5b\x5d-\x7e]{1,128}$/.test(scope) && company.scopes.includes(scope)))
101
+ hint.scope = scopes;
102
+ }
103
+ if (challenge.metadata && challenge.metadata.length <= 2048) {
104
+ try {
105
+ const url = httpsUrl(challenge.metadata);
106
+ const allowed = metadataUrl(resource);
107
+ if (!url.search && url.href === challenge.metadata && url.href === allowed)
108
+ hint.resourceMetadataUrl = url.href;
109
+ }
110
+ catch { /* An untrusted metadata hint is dropped; it is never fetched. */ }
111
+ }
112
+ return hint;
113
+ }
114
+ export function protocolFailure(response, company, resource, preferred) {
115
+ if (response.status === 401 || response.status === 403) {
116
+ const parsed = parseAuthenticate(responseHeader(response, 'www-authenticate'));
117
+ const preferredItems = parsed.challenges.filter(item => item.scheme === preferred);
118
+ const candidates = preferredItems.length ? preferredItems : parsed.challenges;
119
+ const selected = candidates[0];
120
+ if (selected && candidates.filter(item => item.scheme === selected.scheme).some(item => item.error !== selected.error || item.scope !== selected.scope || item.metadata !== selected.metadata))
121
+ return { code: 'oauth_error', challenge: true };
122
+ if (selected) {
123
+ const code = selected.error === undefined ? (response.status === 401 ? 'invalid_token' : 'insufficient_scope') : challengeErrors.has(selected.error) ? selected.error : 'oauth_error';
124
+ return { code, hint: company && resource ? safeHint(selected, company, resource) : undefined, challenge: true };
125
+ }
126
+ if (parsed.relevant)
127
+ return { code: 'oauth_error', challenge: true };
128
+ }
129
+ try {
130
+ const body = parseJson(response);
131
+ if (typeof body.error === 'string' && allowedErrors.has(body.error))
132
+ return { code: body.error, challenge: false };
133
+ }
134
+ catch { }
135
+ return { challenge: false };
136
+ }