@inrupt/solid-client-authn-browser 3.0.0 → 3.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.
- package/README.md +1 -1
- package/dist/defaultSession.d.ts +5 -5
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -12
- package/dist/index.mjs.map +1 -1
- package/dist/login/oidc/__mocks__/IOidcOptions.d.ts +1 -1
- package/dist/solid-client-authn.bundle.js +2 -2
- package/dist/solid-client-authn.bundle.js.map +1 -1
- package/package.json +5 -6
- package/src/defaultSession.ts +18 -12
- package/src/login/oidc/OidcLoginHandler.spec.ts +75 -0
- package/src/login/oidc/OidcLoginHandler.ts +2 -0
- package/src/login/oidc/__mocks__/IOidcOptions.ts +5 -1
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +3 -2
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.ts +2 -5
- package/tsconfig.json +0 -8
- package/typedoc.config.mjs +39 -0
- package/LICENSE +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inrupt/solid-client-authn-browser",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"browser": "dist/index.js",
|
|
@@ -26,18 +26,17 @@
|
|
|
26
26
|
"build-docs-preview-site": "npm run build-api-docs; cd docs/api; make html"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/node": "^24.
|
|
29
|
+
"@types/node": "^24.9.1",
|
|
30
30
|
"@types/uuid": "^10.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@inrupt/oidc-client-ext": "^3.
|
|
34
|
-
"@inrupt/solid-client-authn-core": "^3.
|
|
33
|
+
"@inrupt/oidc-client-ext": "^3.1.1",
|
|
34
|
+
"@inrupt/solid-client-authn-core": "^3.1.1",
|
|
35
35
|
"events": "^3.3.0",
|
|
36
36
|
"jose": "^5.1.3",
|
|
37
37
|
"uuid": "^11.1.0"
|
|
38
38
|
},
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
|
-
}
|
|
42
|
-
"gitHead": "af698e70dec2fe50f82ec6b85f7192161bbef482"
|
|
41
|
+
}
|
|
43
42
|
}
|
package/src/defaultSession.ts
CHANGED
|
@@ -49,10 +49,12 @@ export function getDefaultSession(): Session {
|
|
|
49
49
|
* @since 1.3.0
|
|
50
50
|
*/
|
|
51
51
|
/* eslint-disable-next-line no-shadow */
|
|
52
|
-
export
|
|
52
|
+
export function fetch(
|
|
53
|
+
...args: Parameters<Session["fetch"]>
|
|
54
|
+
): ReturnType<Session["fetch"]> {
|
|
53
55
|
const session = getDefaultSession();
|
|
54
56
|
return session.fetch(...args);
|
|
55
|
-
}
|
|
57
|
+
}
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* Triggers the login process. Note that this method will redirect the user away from your app.
|
|
@@ -61,10 +63,12 @@ export const fetch: Session["fetch"] = (...args) => {
|
|
|
61
63
|
* @returns This method should redirect the user away from the app: it does not return anything. The login process is completed by [[handleIncomingRedirect]].
|
|
62
64
|
* @since 1.3.0
|
|
63
65
|
*/
|
|
64
|
-
export
|
|
66
|
+
export function login(
|
|
67
|
+
...args: Parameters<Session["login"]>
|
|
68
|
+
): ReturnType<Session["login"]> {
|
|
65
69
|
const session = getDefaultSession();
|
|
66
70
|
return session.login(...args);
|
|
67
|
-
}
|
|
71
|
+
}
|
|
68
72
|
|
|
69
73
|
/**
|
|
70
74
|
* Logs the user out of the application.
|
|
@@ -75,10 +79,12 @@ export const login: Session["login"] = (...args) => {
|
|
|
75
79
|
*
|
|
76
80
|
* @since 1.3.0
|
|
77
81
|
*/
|
|
78
|
-
export
|
|
82
|
+
export function logout(
|
|
83
|
+
...args: Parameters<Session["logout"]>
|
|
84
|
+
): ReturnType<Session["logout"]> {
|
|
79
85
|
const session = getDefaultSession();
|
|
80
86
|
return session.logout(...args);
|
|
81
|
-
}
|
|
87
|
+
}
|
|
82
88
|
|
|
83
89
|
/**
|
|
84
90
|
* Completes the login process by processing the information provided by the Solid identity provider through redirect.
|
|
@@ -86,18 +92,18 @@ export const logout: Session["logout"] = (...args) => {
|
|
|
86
92
|
* @param url The URL of the page handling the redirect, including the query parameters — these contain the information to process the login.
|
|
87
93
|
* @since 1.3.0
|
|
88
94
|
*/
|
|
89
|
-
export
|
|
90
|
-
...args
|
|
91
|
-
)
|
|
95
|
+
export function handleIncomingRedirect(
|
|
96
|
+
...args: Parameters<Session["handleIncomingRedirect"]>
|
|
97
|
+
): ReturnType<Session["handleIncomingRedirect"]> {
|
|
92
98
|
const session = getDefaultSession();
|
|
93
99
|
return session.handleIncomingRedirect(...args);
|
|
94
|
-
}
|
|
100
|
+
}
|
|
95
101
|
|
|
96
102
|
/**
|
|
97
103
|
* {@link SessionEventEmitter} instance to subscribe to events by the default session.
|
|
98
104
|
*
|
|
99
105
|
* @since 1.14.0
|
|
100
106
|
*/
|
|
101
|
-
export
|
|
107
|
+
export function events(): Session["events"] {
|
|
102
108
|
return getDefaultSession().events;
|
|
103
|
-
}
|
|
109
|
+
}
|
|
@@ -58,6 +58,18 @@ describe("OidcLoginHandler", () => {
|
|
|
58
58
|
);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
const oidcHandlerWithMocks = () => {
|
|
62
|
+
const actualHandler = defaultMocks.oidcHandler;
|
|
63
|
+
const issuerConfig = IssuerConfigFetcherFetchConfigResponse;
|
|
64
|
+
const handler = getInitialisedHandler({
|
|
65
|
+
issuerConfigFetcher: mockIssuerConfigFetcher(
|
|
66
|
+
issuerConfig,
|
|
67
|
+
) as jest.Mocked<IIssuerConfigFetcher>,
|
|
68
|
+
oidcHandler: actualHandler,
|
|
69
|
+
});
|
|
70
|
+
return { handler, mockOidcHandler: actualHandler };
|
|
71
|
+
};
|
|
72
|
+
|
|
61
73
|
it("should call the actual handler when an Oidc Issuer is provided", async () => {
|
|
62
74
|
const actualHandler = defaultMocks.oidcHandler;
|
|
63
75
|
const handler = getInitialisedHandler({ oidcHandler: actualHandler });
|
|
@@ -322,4 +334,67 @@ describe("OidcLoginHandler", () => {
|
|
|
322
334
|
}),
|
|
323
335
|
);
|
|
324
336
|
});
|
|
337
|
+
|
|
338
|
+
it("ignores malformed scopes", async () => {
|
|
339
|
+
const { handler, mockOidcHandler } = oidcHandlerWithMocks();
|
|
340
|
+
await handler.handle({
|
|
341
|
+
sessionId: "mySession",
|
|
342
|
+
oidcIssuer: "https://arbitrary.url",
|
|
343
|
+
redirectUrl: "https://app.com/redirect",
|
|
344
|
+
tokenType: "DPoP",
|
|
345
|
+
keepAlive: false,
|
|
346
|
+
customScopes: [
|
|
347
|
+
// @ts-expect-error This tests misuse of the API.
|
|
348
|
+
{ not: "a string" },
|
|
349
|
+
"some invalid scope including spaces",
|
|
350
|
+
"valid_scope",
|
|
351
|
+
],
|
|
352
|
+
});
|
|
353
|
+
expect(mockOidcHandler.handle).toHaveBeenCalledWith(
|
|
354
|
+
expect.objectContaining({
|
|
355
|
+
scopes: ["openid", "offline_access", "webid", "valid_scope"],
|
|
356
|
+
}),
|
|
357
|
+
);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("adds provided scopes to default ones", async () => {
|
|
361
|
+
const { handler, mockOidcHandler } = oidcHandlerWithMocks();
|
|
362
|
+
await handler.handle({
|
|
363
|
+
sessionId: "mySession",
|
|
364
|
+
oidcIssuer: "https://arbitrary.url",
|
|
365
|
+
redirectUrl: "https://app.com/redirect",
|
|
366
|
+
tokenType: "DPoP",
|
|
367
|
+
keepAlive: false,
|
|
368
|
+
customScopes: ["scope_1", "scope_2", "scope_3"],
|
|
369
|
+
});
|
|
370
|
+
expect(mockOidcHandler.handle).toHaveBeenCalledWith(
|
|
371
|
+
expect.objectContaining({
|
|
372
|
+
scopes: [
|
|
373
|
+
"openid",
|
|
374
|
+
"offline_access",
|
|
375
|
+
"webid",
|
|
376
|
+
"scope_1",
|
|
377
|
+
"scope_2",
|
|
378
|
+
"scope_3",
|
|
379
|
+
],
|
|
380
|
+
}),
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("de-dupes scopes", async () => {
|
|
385
|
+
const { handler, mockOidcHandler } = oidcHandlerWithMocks();
|
|
386
|
+
await handler.handle({
|
|
387
|
+
sessionId: "mySession",
|
|
388
|
+
oidcIssuer: "https://arbitrary.url",
|
|
389
|
+
redirectUrl: "https://app.com/redirect",
|
|
390
|
+
tokenType: "DPoP",
|
|
391
|
+
keepAlive: false,
|
|
392
|
+
customScopes: ["webid", "custom_scope", "custom_scope"],
|
|
393
|
+
});
|
|
394
|
+
expect(mockOidcHandler.handle).toHaveBeenCalledWith(
|
|
395
|
+
expect.objectContaining({
|
|
396
|
+
scopes: ["openid", "offline_access", "webid", "custom_scope"],
|
|
397
|
+
}),
|
|
398
|
+
);
|
|
399
|
+
});
|
|
325
400
|
});
|
|
@@ -42,6 +42,7 @@ import type {
|
|
|
42
42
|
import {
|
|
43
43
|
ConfigurationError,
|
|
44
44
|
handleRegistration,
|
|
45
|
+
normalizeScopes,
|
|
45
46
|
} from "@inrupt/solid-client-authn-core";
|
|
46
47
|
|
|
47
48
|
function hasIssuer(
|
|
@@ -116,6 +117,7 @@ export default class OidcLoginHandler implements ILoginHandler {
|
|
|
116
117
|
...options,
|
|
117
118
|
issuerConfiguration: issuerConfig,
|
|
118
119
|
client: clientRegistration,
|
|
120
|
+
scopes: normalizeScopes(options.customScopes),
|
|
119
121
|
};
|
|
120
122
|
|
|
121
123
|
// Call proper OIDC Handler
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
20
|
//
|
|
21
21
|
|
|
22
|
-
import
|
|
22
|
+
import {
|
|
23
|
+
DEFAULT_SCOPES,
|
|
24
|
+
type IOidcOptions,
|
|
25
|
+
} from "@inrupt/solid-client-authn-core";
|
|
23
26
|
import { jest } from "@jest/globals";
|
|
24
27
|
|
|
25
28
|
export const standardOidcOptions: IOidcOptions = {
|
|
@@ -42,4 +45,5 @@ export const standardOidcOptions: IOidcOptions = {
|
|
|
42
45
|
clientId: "coolApp",
|
|
43
46
|
clientType: "dynamic",
|
|
44
47
|
},
|
|
48
|
+
scopes: DEFAULT_SCOPES,
|
|
45
49
|
};
|
|
@@ -235,7 +235,7 @@ describe("AuthorizationCodeWithPkceOidcHandler", () => {
|
|
|
235
235
|
);
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
it("
|
|
238
|
+
it("includes the provided scopes in the authorization request", async () => {
|
|
239
239
|
const oidcModule = mockOidcModule();
|
|
240
240
|
const authorizationCodeWithPkceOidcHandler =
|
|
241
241
|
getAuthorizationCodeWithPkceOidcHandler();
|
|
@@ -245,11 +245,12 @@ describe("AuthorizationCodeWithPkceOidcHandler", () => {
|
|
|
245
245
|
...standardOidcOptions.issuerConfiguration,
|
|
246
246
|
grantTypesSupported: ["authorization_code"],
|
|
247
247
|
},
|
|
248
|
+
scopes: ["openid", "webid", "custom_scope"],
|
|
248
249
|
};
|
|
249
250
|
await authorizationCodeWithPkceOidcHandler.handle(oidcOptions);
|
|
250
251
|
expect(oidcModule.OidcClient).toHaveBeenCalledWith(
|
|
251
252
|
expect.objectContaining({
|
|
252
|
-
scope: "openid
|
|
253
|
+
scope: "openid webid custom_scope",
|
|
253
254
|
}),
|
|
254
255
|
);
|
|
255
256
|
});
|
|
@@ -32,10 +32,7 @@ import type {
|
|
|
32
32
|
IOidcOptions,
|
|
33
33
|
LoginResult,
|
|
34
34
|
} from "@inrupt/solid-client-authn-core";
|
|
35
|
-
import {
|
|
36
|
-
DEFAULT_SCOPES,
|
|
37
|
-
AuthorizationCodeWithPkceOidcHandlerBase,
|
|
38
|
-
} from "@inrupt/solid-client-authn-core";
|
|
35
|
+
import { AuthorizationCodeWithPkceOidcHandlerBase } from "@inrupt/solid-client-authn-core";
|
|
39
36
|
import { OidcClient } from "@inrupt/oidc-client-ext";
|
|
40
37
|
|
|
41
38
|
/**
|
|
@@ -55,7 +52,7 @@ export default class AuthorizationCodeWithPkceOidcHandler
|
|
|
55
52
|
client_secret: oidcLoginOptions.client.clientSecret,
|
|
56
53
|
redirect_uri: oidcLoginOptions.redirectUrl,
|
|
57
54
|
response_type: "code",
|
|
58
|
-
scope:
|
|
55
|
+
scope: oidcLoginOptions.scopes.join(" "),
|
|
59
56
|
filterProtocolClaims: true,
|
|
60
57
|
// The userinfo endpoint on NSS fails, so disable this for now
|
|
61
58
|
// Note that in Solid, information should be retrieved from the
|
package/tsconfig.json
CHANGED
|
@@ -6,14 +6,6 @@
|
|
|
6
6
|
"outDir": "./dist"
|
|
7
7
|
},
|
|
8
8
|
|
|
9
|
-
"typedocOptions": {
|
|
10
|
-
"out": "website/docs/api/browser",
|
|
11
|
-
"entryPoints": ["./src/index.ts"],
|
|
12
|
-
"entryDocument": "index.rst",
|
|
13
|
-
"hideInPageTOC": true,
|
|
14
|
-
"plugin": ["typedoc-plugin-markdown"]
|
|
15
|
-
},
|
|
16
|
-
|
|
17
9
|
"include": ["src/**/*"],
|
|
18
10
|
"exclude": ["src/**/*.spec.ts", "**/__mocks__/*"]
|
|
19
11
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright Inrupt Inc.
|
|
3
|
+
//
|
|
4
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
// of this software and associated documentation files (the "Software"), to deal in
|
|
6
|
+
// the Software without restriction, including without limitation the rights to use,
|
|
7
|
+
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
8
|
+
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
9
|
+
// subject to the following conditions:
|
|
10
|
+
//
|
|
11
|
+
// The above copyright notice and this permission notice shall be included in
|
|
12
|
+
// all copies or substantial portions of the Software.
|
|
13
|
+
//
|
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
15
|
+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
16
|
+
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
18
|
+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
19
|
+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
|
+
//
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
compilerOptions: {
|
|
24
|
+
skipLibCheck: true,
|
|
25
|
+
},
|
|
26
|
+
out: "../../docs/api/browser",
|
|
27
|
+
entryPoints: ["./src/index.ts"],
|
|
28
|
+
exclude: [
|
|
29
|
+
"node_modules/**",
|
|
30
|
+
"**/*.test.ts",
|
|
31
|
+
// Internal helpers:
|
|
32
|
+
"**/*.internal.ts",
|
|
33
|
+
// End-to-end tests:
|
|
34
|
+
"e2e/**",
|
|
35
|
+
],
|
|
36
|
+
navigation: {
|
|
37
|
+
includeCategories: true,
|
|
38
|
+
},
|
|
39
|
+
};
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
Begin license text.
|
|
2
|
-
Copyright Inrupt Inc.
|
|
3
|
-
|
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
-
of this software and associated documentation files (the "Software"), to deal in
|
|
6
|
-
the Software without restriction, including without limitation the rights to use,
|
|
7
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
8
|
-
Software, and to permit persons to whom the Software is furnished to do so,
|
|
9
|
-
subject to the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be included in
|
|
12
|
-
all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
15
|
-
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
16
|
-
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
18
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
19
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
|
-
|
|
21
|
-
End license text.Source Distributions
|