@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inrupt/solid-client-authn-browser",
3
- "version": "3.0.0",
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.0.7",
29
+ "@types/node": "^24.9.1",
30
30
  "@types/uuid": "^10.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "@inrupt/oidc-client-ext": "^3.0.0",
34
- "@inrupt/solid-client-authn-core": "^3.0.0",
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
  }
@@ -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 const fetch: Session["fetch"] = (...args) => {
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 const login: Session["login"] = (...args) => {
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 const logout: Session["logout"] = (...args) => {
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 const handleIncomingRedirect: Session["handleIncomingRedirect"] = (
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 const events = (): Session["events"] => {
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 type { IOidcOptions } from "@inrupt/solid-client-authn-core";
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("requests both openid, offline_access and webid scopes", async () => {
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 offline_access webid",
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: DEFAULT_SCOPES,
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