@inrupt/solid-client-authn-browser 3.0.0 → 3.1.0

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.0",
4
4
  "license": "MIT",
5
5
  "types": "dist/index.d.ts",
6
6
  "browser": "dist/index.js",
@@ -26,12 +26,12 @@
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.0.10",
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.0",
34
+ "@inrupt/solid-client-authn-core": "^3.1.0",
35
35
  "events": "^3.3.0",
36
36
  "jose": "^5.1.3",
37
37
  "uuid": "^11.1.0"
@@ -39,5 +39,5 @@
39
39
  "publishConfig": {
40
40
  "access": "public"
41
41
  },
42
- "gitHead": "af698e70dec2fe50f82ec6b85f7192161bbef482"
42
+ "gitHead": "c30be8b6ddd243ed45ef93cbb3a27daf4e3faab0"
43
43
  }
@@ -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