trustflows-client 0.1.0-alpha.0 → 0.1.0-alpha.2
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/dist/auth.d.ts +3 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +74 -54
- package/package.json +9 -2
package/dist/auth.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ClaimResolver, ClaimResolverDefinition, ClaimResolverRegistry } from './uma/claims/types';
|
|
2
2
|
export interface AuthOptions {
|
|
3
3
|
fetch?: typeof fetch;
|
|
4
|
+
redirect?: (url: string) => void;
|
|
4
5
|
storage?: Storage;
|
|
5
6
|
claimResolvers?: ClaimResolverRegistry;
|
|
6
7
|
persistTokens?: boolean;
|
|
@@ -24,10 +25,12 @@ export declare class Auth {
|
|
|
24
25
|
webId?: string;
|
|
25
26
|
umaPermissionTokens: Map<string, UmaTokenCacheEntry>;
|
|
26
27
|
private readonly fetchFn;
|
|
28
|
+
private readonly redirectFn;
|
|
27
29
|
private readonly storage?;
|
|
28
30
|
private readonly claimResolvers;
|
|
29
31
|
private readonly persistTokens;
|
|
30
32
|
private oidcIssuer?;
|
|
33
|
+
private handleRedirectPromise?;
|
|
31
34
|
constructor(options?: AuthOptions);
|
|
32
35
|
addClaimResolver(format: string | ClaimResolverDefinition, resolver?: ClaimResolver): void;
|
|
33
36
|
get accessToken(): string | undefined;
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAO5B,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,iBAAiB;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,IAAI;IACR,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,kCAAyC;IAEnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,UAAU,CAAC,CAAS;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.js
CHANGED
|
@@ -8,12 +8,18 @@ export class Auth {
|
|
|
8
8
|
webId;
|
|
9
9
|
umaPermissionTokens = new Map();
|
|
10
10
|
fetchFn;
|
|
11
|
+
redirectFn;
|
|
11
12
|
storage;
|
|
12
13
|
claimResolvers;
|
|
13
14
|
persistTokens;
|
|
14
15
|
oidcIssuer;
|
|
16
|
+
handleRedirectPromise;
|
|
15
17
|
constructor(options = {}) {
|
|
16
|
-
|
|
18
|
+
const rawFetch = options.fetch ?? fetch;
|
|
19
|
+
this.fetchFn = rawFetch === fetch ? rawFetch.bind(globalThis) : rawFetch;
|
|
20
|
+
this.redirectFn = options.redirect ?? ((url) => {
|
|
21
|
+
window.location.href = url;
|
|
22
|
+
});
|
|
17
23
|
this.storage =
|
|
18
24
|
options.storage ??
|
|
19
25
|
(typeof sessionStorage === 'undefined' ? undefined : sessionStorage);
|
|
@@ -71,7 +77,7 @@ export class Auth {
|
|
|
71
77
|
prompt: 'consent',
|
|
72
78
|
response_mode: 'query',
|
|
73
79
|
});
|
|
74
|
-
|
|
80
|
+
this.redirectFn(`${config.authorization_endpoint}?${params.toString()}`);
|
|
75
81
|
}
|
|
76
82
|
async logout(postLogoutRedirectUri) {
|
|
77
83
|
const resolvedIssuer = this.oidcIssuer ?? this.storage?.getItem('oidc_issuer') ?? undefined;
|
|
@@ -98,64 +104,78 @@ export class Auth {
|
|
|
98
104
|
const logoutUrl = params.toString() ?
|
|
99
105
|
`${config.end_session_endpoint}?${params.toString()}` :
|
|
100
106
|
config.end_session_endpoint;
|
|
101
|
-
|
|
107
|
+
this.redirectFn(logoutUrl);
|
|
102
108
|
}
|
|
103
109
|
async handleIncomingRedirect() {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.
|
|
110
|
+
if (this.handleRedirectPromise) {
|
|
111
|
+
return this.handleRedirectPromise;
|
|
112
|
+
}
|
|
113
|
+
this.handleRedirectPromise = (async () => {
|
|
114
|
+
const url = new URL(window.location.href);
|
|
115
|
+
const code = url.searchParams.get('code');
|
|
116
|
+
const state = url.searchParams.get('state');
|
|
117
|
+
if (!code) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
const storage = this.getStorage();
|
|
121
|
+
const storedState = storage.getItem('oidc_state');
|
|
122
|
+
if (!state || state !== storedState) {
|
|
123
|
+
throw new Error('OIDC state mismatch');
|
|
124
|
+
}
|
|
125
|
+
const issuer = storage.getItem('oidc_issuer');
|
|
126
|
+
const clientId = storage.getItem('oidc_client_id');
|
|
127
|
+
const redirectUri = storage.getItem('oidc_redirect_uri');
|
|
128
|
+
const codeVerifier = storage.getItem('oidc_code_verifier');
|
|
129
|
+
if (!issuer || !clientId || !redirectUri || !codeVerifier) {
|
|
130
|
+
throw new Error('Missing stored OIDC parameters');
|
|
131
|
+
}
|
|
132
|
+
this.oidcIssuer = issuer;
|
|
133
|
+
const config = await this.getOidcConfig(issuer);
|
|
134
|
+
if (!config.token_endpoint) {
|
|
135
|
+
throw new Error('Missing token_endpoint in OIDC configuration');
|
|
136
|
+
}
|
|
137
|
+
const bodyParams = new URLSearchParams({
|
|
138
|
+
grant_type: 'authorization_code',
|
|
139
|
+
code,
|
|
140
|
+
redirect_uri: redirectUri,
|
|
141
|
+
client_id: clientId,
|
|
142
|
+
code_verifier: codeVerifier,
|
|
143
|
+
});
|
|
144
|
+
const tokenResp = await this.fetchFn(config.token_endpoint, {
|
|
145
|
+
method: 'POST',
|
|
146
|
+
headers: {
|
|
147
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
148
|
+
},
|
|
149
|
+
body: bodyParams.toString(),
|
|
150
|
+
});
|
|
151
|
+
if (!tokenResp.ok) {
|
|
152
|
+
throw new Error(`Token endpoint error ${tokenResp.status}`);
|
|
153
|
+
}
|
|
154
|
+
const tokenJson = (await tokenResp.json());
|
|
155
|
+
this.oidcAccessToken = tokenJson.access_token;
|
|
156
|
+
this.oidcToken = tokenJson.id_token;
|
|
157
|
+
this.oidcRefreshToken = tokenJson.refresh_token;
|
|
158
|
+
if (tokenJson.expires_in) {
|
|
159
|
+
this.oidcTokenExpiry = Date.now() + tokenJson.expires_in * 1000;
|
|
160
|
+
}
|
|
161
|
+
if (tokenJson.id_token) {
|
|
162
|
+
this.webId = this.extractWebId(tokenJson.id_token);
|
|
163
|
+
}
|
|
164
|
+
this.persistOidcTokens();
|
|
165
|
+
window.history.replaceState({}, document.title, redirectUri);
|
|
166
|
+
return true;
|
|
167
|
+
})();
|
|
168
|
+
try {
|
|
169
|
+
return await this.handleRedirectPromise;
|
|
150
170
|
}
|
|
151
|
-
|
|
152
|
-
this.
|
|
171
|
+
finally {
|
|
172
|
+
this.handleRedirectPromise = undefined;
|
|
153
173
|
}
|
|
154
|
-
this.persistOidcTokens();
|
|
155
|
-
window.history.replaceState({}, document.title, redirectUri);
|
|
156
|
-
return true;
|
|
157
174
|
}
|
|
158
175
|
async isLoggedIn() {
|
|
176
|
+
if (this.handleRedirectPromise) {
|
|
177
|
+
await this.handleRedirectPromise;
|
|
178
|
+
}
|
|
159
179
|
try {
|
|
160
180
|
await this.ensureValidToken();
|
|
161
181
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trustflows-client",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Trustflows client helpers for Solid applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,13 +22,20 @@
|
|
|
22
22
|
"dev": "tsc -p tsconfig.json --watch",
|
|
23
23
|
"lint": "eslint . --cache --max-warnings 0",
|
|
24
24
|
"lint:fix": "eslint . --cache --max-warnings 0 --fix",
|
|
25
|
-
"test": "
|
|
25
|
+
"test": "npm run test:node && npm run test:browser",
|
|
26
|
+
"test:node": "vitest run --environment node",
|
|
27
|
+
"test:browser": "npm run test:browser:chromium && npm run test:browser:firefox && npm run test:browser:webkit",
|
|
28
|
+
"test:browser:chromium": "vitest run --browser --browser.name=chromium",
|
|
29
|
+
"test:browser:firefox": "vitest run --browser --browser.name=firefox",
|
|
30
|
+
"test:browser:webkit": "vitest run --browser --browser.name=webkit",
|
|
26
31
|
"test:watch": "vitest"
|
|
27
32
|
},
|
|
28
33
|
"dependencies": {},
|
|
29
34
|
"devDependencies": {
|
|
35
|
+
"@vitest/browser": "^2.0.5",
|
|
30
36
|
"eslint": "^9.0.0",
|
|
31
37
|
"opinionated-eslint-config": "^0.2.0",
|
|
38
|
+
"playwright": "^1.45.0",
|
|
32
39
|
"typescript": "^5.5.0",
|
|
33
40
|
"vitest": "^2.0.5"
|
|
34
41
|
}
|