@inrupt/solid-client-authn-browser 1.13.2 → 1.13.4

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": "1.13.2",
3
+ "version": "1.13.4",
4
4
  "license": "MIT",
5
5
  "types": "dist/index",
6
6
  "browser": "dist/index.js",
@@ -25,11 +25,11 @@
25
25
  "cross-fetch": "^3.1.5"
26
26
  },
27
27
  "dependencies": {
28
- "@inrupt/oidc-client-ext": "^1.13.2",
29
- "@inrupt/solid-client-authn-core": "^1.13.2",
28
+ "@inrupt/oidc-client-ext": "^1.13.4",
29
+ "@inrupt/solid-client-authn-core": "^1.13.4",
30
30
  "@types/lodash.clonedeep": "^4.5.6",
31
31
  "@types/node": "^18.0.3",
32
- "@types/uuid": "^8.3.0",
32
+ "@types/uuid": "^9.0.1",
33
33
  "events": "^3.3.0",
34
34
  "jose": "^4.3.7",
35
35
  "lodash.clonedeep": "^4.5.0",
@@ -41,5 +41,5 @@
41
41
  "engines": {
42
42
  "node": "^14.0.0 || ^16.0.0"
43
43
  },
44
- "gitHead": "76a536b31ba87632891d726b5179bfde9afed7be"
44
+ "gitHead": "ab437bbfb613f4f64b82b17e3a38177998a1762a"
45
45
  }
@@ -32,6 +32,7 @@ import { Session } from "./Session";
32
32
  import { LocalStorageMock } from "./storage/__mocks__/LocalStorage";
33
33
  import { mockSessionInfoManager } from "./sessionInfo/__mocks__/SessionInfoManager";
34
34
  import { KEY_CURRENT_SESSION, KEY_CURRENT_URL } from "./constant";
35
+ import type ClientAuthentication from "./ClientAuthentication";
35
36
 
36
37
  /* eslint-disable @typescript-eslint/ban-ts-comment */
37
38
 
@@ -264,21 +265,21 @@ describe("Session", () => {
264
265
 
265
266
  it("updates the session's info if relevant", async () => {
266
267
  const clientAuthentication = mockClientAuthentication();
267
- clientAuthentication.handleIncomingRedirect = jest.fn(
268
- async (_url: string) => {
269
- return {
270
- isLoggedIn: true,
271
- sessionId: "a session ID",
272
- webId: "https://some.webid#them",
273
- };
274
- }
275
- );
268
+ clientAuthentication.handleIncomingRedirect = jest
269
+ .fn<ClientAuthentication["handleIncomingRedirect"]>()
270
+ .mockResolvedValueOnce({
271
+ isLoggedIn: true,
272
+ sessionId: "a session ID",
273
+ webId: "https://some.webid#them",
274
+ expirationDate: Date.now() + 3600,
275
+ });
276
276
  const mySession = new Session({ clientAuthentication });
277
277
  expect(mySession.info.isLoggedIn).toBe(false);
278
278
  await mySession.handleIncomingRedirect("https://some.url");
279
279
  expect(mySession.info.isLoggedIn).toBe(true);
280
280
  expect(mySession.info.sessionId).toBe("a session ID");
281
281
  expect(mySession.info.webId).toBe("https://some.webid#them");
282
+ expect(mySession.info.expirationDate).toBeGreaterThan(Date.now());
282
283
  });
283
284
 
284
285
  it("updates the localStorage if the login is completed", async () => {
@@ -119,4 +119,42 @@ describe("IssuerConfigFetcher", () => {
119
119
  );
120
120
  expect(fetchedConfig.scopesSupported).toContain("openid");
121
121
  });
122
+
123
+ it("should append the .well-known/openid-configuration path at the end of the issuer URL", async () => {
124
+ // The response value is irrelevant to this test.
125
+ const mockFetch = jest.fn<typeof fetch>().mockImplementation(
126
+ async () =>
127
+ new NodeResponse(
128
+ JSON.stringify({
129
+ issuer: "https://example.com",
130
+ // eslint-disable-next-line camelcase
131
+ claim_types_supported: "oidc",
132
+ })
133
+ )
134
+ );
135
+ window.fetch = mockFetch as typeof window.fetch;
136
+ const configFetcher = getIssuerConfigFetcher({
137
+ storageUtility: mockStorageUtility({}),
138
+ });
139
+ // No trailing slash
140
+ await configFetcher.fetchConfig("https://arbitrary.url");
141
+ expect(mockFetch).toHaveBeenLastCalledWith(
142
+ "https://arbitrary.url/.well-known/openid-configuration"
143
+ );
144
+ // A trailing slash
145
+ await configFetcher.fetchConfig("https://arbitrary.url/");
146
+ expect(mockFetch).toHaveBeenLastCalledWith(
147
+ "https://arbitrary.url/.well-known/openid-configuration"
148
+ );
149
+ // A path without a trailing slash
150
+ await configFetcher.fetchConfig("https://arbitrary.url/path");
151
+ expect(mockFetch).toHaveBeenLastCalledWith(
152
+ "https://arbitrary.url/path/.well-known/openid-configuration"
153
+ );
154
+ // A path with a trailing slash
155
+ await configFetcher.fetchConfig("https://arbitrary.url/path/");
156
+ expect(mockFetch).toHaveBeenLastCalledWith(
157
+ "https://arbitrary.url/path/.well-known/openid-configuration"
158
+ );
159
+ });
122
160
  });
@@ -159,7 +159,12 @@ export default class IssuerConfigFetcher implements IIssuerConfigFetcher {
159
159
  async fetchConfig(issuer: string): Promise<IIssuerConfig> {
160
160
  let issuerConfig: IIssuerConfig;
161
161
 
162
- const openIdConfigUrl = new URL(WELL_KNOWN_OPENID_CONFIG, issuer).href;
162
+ const openIdConfigUrl = new URL(
163
+ WELL_KNOWN_OPENID_CONFIG,
164
+ // Make sure to append a slash at issuer URL, so that the .well-known URL
165
+ // includes the full issuer path. See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig.
166
+ issuer.endsWith("/") ? issuer : `${issuer}/`
167
+ ).href;
163
168
  const issuerConfigRequestBody = await window.fetch(openIdConfigUrl);
164
169
  // Check the validity of the fetched config
165
170
  try {
@@ -35,7 +35,7 @@ import type * as SolidClientAuthnCore from "@inrupt/solid-client-authn-core";
35
35
  import { jest, it, describe, expect } from "@jest/globals";
36
36
  import { CodeExchangeResult, getBearerToken } from "@inrupt/oidc-client-ext";
37
37
  import type * as OidcClientExt from "@inrupt/oidc-client-ext";
38
- import { Response } from "cross-fetch";
38
+ import { Response, Headers } from "cross-fetch";
39
39
  import { JWK, importJWK } from "jose";
40
40
  import { KeyObject } from "crypto";
41
41
  import { AuthCodeRedirectHandler } from "./AuthCodeRedirectHandler";
@@ -470,11 +470,6 @@ describe("AuthCodeRedirectHandler", () => {
470
470
  storageUtility: mockedStorage,
471
471
  });
472
472
  await authCodeRedirectHandler.handle(mockRedirectUrl());
473
- await expect(
474
- mockedStorage.getForUser("mySession", "redirectUrl", {
475
- secure: false,
476
- })
477
- ).resolves.toBe("https://some.redirect.uri/?state=oauth2StateValue");
478
473
 
479
474
  // The ID token should not have been stored
480
475
  await expect(
@@ -484,7 +479,7 @@ describe("AuthCodeRedirectHandler", () => {
484
479
  ).resolves.toBeUndefined();
485
480
  });
486
481
 
487
- it("preserves any query strings from the redirect URI", async () => {
482
+ it("does not override the previously stored redirect URL", async () => {
488
483
  mockOidcClient();
489
484
 
490
485
  window.fetch = (jest.fn() as any).mockReturnValue(
@@ -509,9 +504,8 @@ describe("AuthCodeRedirectHandler", () => {
509
504
  mockedStorage.getForUser("mySession", "redirectUrl", {
510
505
  secure: false,
511
506
  })
512
- ).resolves.toBe(
513
- "https://some.redirect.uri/?state=oauth2StateValue&someKey=someValue"
514
- );
507
+ // The redirect URL already in storage shouldn't be overriden on redirect.
508
+ ).resolves.toBe(DEFAULT_REDIRECT_URL);
515
509
  });
516
510
 
517
511
  it("returns the expiration time normalised to the current time", async () => {
@@ -175,19 +175,6 @@ export class AuthCodeRedirectHandler implements IIncomingRedirectHandler {
175
175
  },
176
176
  { secure: true }
177
177
  );
178
- // Clear the code query param from the redirect URL before storing it, but
179
- // preserve any state that my have been provided by the client and returned
180
- // by the IdP.
181
- url.searchParams.delete("code");
182
- await this.storageUtility.setForUser(
183
- storedSessionId,
184
- {
185
- redirectUrl: url.toString(),
186
- },
187
- {
188
- secure: false,
189
- }
190
- );
191
178
 
192
179
  const sessionInfo = await this.sessionInfoManager.get(storedSessionId);
193
180
  if (!sessionInfo) {
package/tsconfig.json CHANGED
@@ -9,7 +9,8 @@
9
9
  "typedocOptions": {
10
10
  "out": "website/docs/api/browser",
11
11
  "entryPoints": ["./src/index.ts"],
12
- "entryDocument": "index.md"
12
+ "entryDocument": "index.md",
13
+ "hideInPageTOC": true,
13
14
  },
14
15
 
15
16
  "include": ["src/**/*"],