@inrupt/solid-client-authn-browser 3.1.1 → 5.0.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/README.md +9 -13
- package/dist/index.js +28 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -38
- package/dist/index.mjs.map +1 -1
- package/dist/solid-client-authn.bundle.js +1 -31
- package/dist/solid-client-authn.bundle.js.map +1 -1
- package/package.json +7 -7
- package/rollup.config.mjs +0 -2
- package/src/ClientAuthentication.spec.ts +147 -23
- package/src/ClientAuthentication.ts +18 -4
- package/src/Session.spec.ts +74 -39
- package/src/Session.ts +0 -1
- package/src/__mocks__/ClientAuthentication.ts +1 -1
- package/src/constant.ts +0 -1
- package/src/defaultSession.spec.ts +0 -1
- package/src/defaultSession.ts +1 -2
- package/src/dependencies.node.spec.ts +0 -1
- package/src/dependencies.spec.ts +0 -1
- package/src/dependencies.ts +0 -1
- package/src/index.browser.spec.ts +0 -1
- package/src/index.browser.ts +0 -1
- package/src/index.spec.ts +0 -1
- package/src/index.ts +0 -1
- package/src/login/__mocks__/LoginHandler.ts +0 -1
- package/src/login/oidc/AggregateOidcHandler.spec.ts +1 -2
- package/src/login/oidc/AggregateOidcHandler.ts +0 -1
- package/src/login/oidc/AggregateRedirectHandler.ts +0 -1
- package/src/login/oidc/ClientRegistrar.spec.ts +1 -1
- package/src/login/oidc/ClientRegistrar.ts +0 -1
- package/src/login/oidc/IssuerConfigFetcher.spec.ts +7 -5
- package/src/login/oidc/IssuerConfigFetcher.ts +3 -3
- package/src/login/oidc/OidcLoginHandler.spec.ts +1 -1
- package/src/login/oidc/OidcLoginHandler.ts +0 -1
- package/src/login/oidc/Redirector.spec.ts +5 -23
- package/src/login/oidc/Redirector.ts +0 -1
- package/src/login/oidc/__mocks__/ClientRegistrar.ts +0 -1
- package/src/login/oidc/__mocks__/IOidcHandler.ts +1 -3
- package/src/login/oidc/__mocks__/IOidcOptions.ts +0 -1
- package/src/login/oidc/__mocks__/IssuerConfigFetcher.ts +0 -2
- package/src/login/oidc/__mocks__/Redirector.ts +0 -1
- package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.spec.ts +3 -4
- package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.ts +0 -1
- package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.spec.ts +0 -1
- package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.ts +0 -2
- package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.spec.ts +0 -1
- package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.ts +1 -2
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +1 -4
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.ts +10 -11
- package/src/login/oidc/oidcHandlers/OidcHandlerCanHandleTest.ts +0 -1
- package/src/login/oidc/refresh/TokenRefresher.spec.ts +3 -4
- package/src/login/oidc/refresh/TokenRefresher.ts +0 -2
- package/src/login/oidc/refresh/__mocks__/TokenRefresher.ts +0 -2
- package/src/logout/buildRpInitiatedLogout.ts +1 -1
- package/src/sessionInfo/SessionInfoManager.spec.ts +62 -1
- package/src/sessionInfo/SessionInfoManager.ts +6 -1
- package/src/sessionInfo/__mocks__/SessionInfoManager.ts +1 -2
- package/src/storage/BrowserStorage.spec.ts +0 -1
- package/src/storage/BrowserStorage.ts +0 -1
- package/src/storage/StorageUtility.ts +0 -1
- package/src/storage/__mocks__/LocalStorage.ts +0 -1
- package/src/util/UUIDGenerator.spec.ts +0 -1
- package/src/util/UuidGenerator.ts +0 -2
- package/src/util/__mocks__/UuidGenerator.ts +0 -1
- package/typedoc.config.mjs +0 -1
package/src/index.browser.ts
CHANGED
package/src/index.spec.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -29,7 +28,7 @@ jest.mock("@inrupt/solid-client-authn-core");
|
|
|
29
28
|
describe("AggregateOidcHandler", () => {
|
|
30
29
|
it("should pass injected handlers to its superclass", () => {
|
|
31
30
|
// We just test if the parent is called.
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
new AggregateOidcHandler(["Some handler"] as unknown as IOidcHandler[]);
|
|
34
33
|
|
|
35
34
|
expect((AggregateHandler as jest.Mock).mock.calls).toEqual([
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -22,6 +21,7 @@
|
|
|
22
21
|
import {
|
|
23
22
|
StorageUtilityMock,
|
|
24
23
|
mockStorageUtility,
|
|
24
|
+
// eslint-disable-next-line import/no-unresolved
|
|
25
25
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
26
26
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
27
27
|
import { randomUUID } from "crypto";
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -23,6 +22,9 @@ import { jest, it, describe, expect } from "@jest/globals";
|
|
|
23
22
|
import { mockStorageUtility } from "@inrupt/solid-client-authn-core";
|
|
24
23
|
import IssuerConfigFetcher from "./IssuerConfigFetcher";
|
|
25
24
|
|
|
25
|
+
// Camelcase identifiers are required in the OIDC specification.
|
|
26
|
+
/* eslint-disable camelcase*/
|
|
27
|
+
|
|
26
28
|
/**
|
|
27
29
|
* Test for IssuerConfigFetcher
|
|
28
30
|
*/
|
|
@@ -58,7 +60,7 @@ describe("IssuerConfigFetcher", () => {
|
|
|
58
60
|
new Response(
|
|
59
61
|
JSON.stringify({
|
|
60
62
|
issuer: "https://example.com",
|
|
61
|
-
|
|
63
|
+
|
|
62
64
|
claim_types_supported: "oidc",
|
|
63
65
|
bleepBloop: "Meep Moop",
|
|
64
66
|
end_session_endpoint: "https://example.com/endSessionEndpoint",
|
|
@@ -92,7 +94,7 @@ describe("IssuerConfigFetcher", () => {
|
|
|
92
94
|
new Response(
|
|
93
95
|
JSON.stringify({
|
|
94
96
|
issuer: "https://example.com",
|
|
95
|
-
|
|
97
|
+
|
|
96
98
|
claim_types_supported: "oidc",
|
|
97
99
|
scopes_supported: ["openid", "offline_access", "webid"],
|
|
98
100
|
}),
|
|
@@ -114,7 +116,7 @@ describe("IssuerConfigFetcher", () => {
|
|
|
114
116
|
new Response(
|
|
115
117
|
JSON.stringify({
|
|
116
118
|
issuer: "https://example.com",
|
|
117
|
-
|
|
119
|
+
|
|
118
120
|
claim_types_supported: "oidc",
|
|
119
121
|
}),
|
|
120
122
|
),
|
|
@@ -136,7 +138,7 @@ describe("IssuerConfigFetcher", () => {
|
|
|
136
138
|
new Response(
|
|
137
139
|
JSON.stringify({
|
|
138
140
|
issuer: "https://example.com",
|
|
139
|
-
|
|
141
|
+
|
|
140
142
|
claim_types_supported: "oidc",
|
|
141
143
|
scopes_supported: ["openid", "offline_access", "webid"],
|
|
142
144
|
}),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -34,9 +33,11 @@ import type {
|
|
|
34
33
|
} from "@inrupt/solid-client-authn-core";
|
|
35
34
|
import { ConfigurationError } from "@inrupt/solid-client-authn-core";
|
|
36
35
|
|
|
36
|
+
// Camelcase identifiers are required in the OIDC specification.
|
|
37
|
+
/* eslint-disable camelcase*/
|
|
38
|
+
|
|
37
39
|
export const WELL_KNOWN_OPENID_CONFIG = ".well-known/openid-configuration";
|
|
38
40
|
|
|
39
|
-
/* eslint-disable camelcase */
|
|
40
41
|
const issuerConfigKeyMap: Record<
|
|
41
42
|
string,
|
|
42
43
|
{ toKey: string; convertToUrl?: boolean }
|
|
@@ -127,7 +128,6 @@ const issuerConfigKeyMap: Record<
|
|
|
127
128
|
convertToUrl: true,
|
|
128
129
|
},
|
|
129
130
|
};
|
|
130
|
-
/* eslint-enable camelcase */
|
|
131
131
|
|
|
132
132
|
function processConfig(
|
|
133
133
|
config: Record<string, string | string[]>,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -25,6 +24,7 @@ import { StorageUtility } from "@inrupt/solid-client-authn-core";
|
|
|
25
24
|
import {
|
|
26
25
|
StorageUtilityMock,
|
|
27
26
|
mockStorage,
|
|
27
|
+
// eslint-disable-next-line import/no-unresolved
|
|
28
28
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
29
29
|
import { randomUUID } from "crypto";
|
|
30
30
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -32,39 +31,23 @@ import Redirector from "./Redirector";
|
|
|
32
31
|
/**
|
|
33
32
|
* Test for Redirector
|
|
34
33
|
*/
|
|
34
|
+
declare const __setTestUrl: (url: string) => void;
|
|
35
|
+
|
|
35
36
|
describe("Redirector", () => {
|
|
36
37
|
describe("redirect", () => {
|
|
37
|
-
const {
|
|
38
|
-
location,
|
|
39
|
-
history: { replaceState },
|
|
40
|
-
} = window;
|
|
41
|
-
|
|
42
38
|
beforeEach(() => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// here just for testing.
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
delete window.location;
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
delete window.history.replaceState;
|
|
52
|
-
(window as any).location = {
|
|
53
|
-
href: "https://coolSite.com",
|
|
54
|
-
} as Location;
|
|
55
|
-
window.history.replaceState = jest.fn();
|
|
39
|
+
__setTestUrl("https://coolSite.com");
|
|
40
|
+
jest.spyOn(window.history, "replaceState").mockImplementation(() => {});
|
|
56
41
|
});
|
|
57
42
|
|
|
58
43
|
afterEach(() => {
|
|
59
|
-
(
|
|
60
|
-
window.history.replaceState = replaceState;
|
|
44
|
+
jest.restoreAllMocks();
|
|
61
45
|
});
|
|
62
46
|
|
|
63
47
|
it("browser redirection defaults to using href", () => {
|
|
64
48
|
const redirector = new Redirector();
|
|
65
49
|
redirector.redirect("https://someUrl.com/redirect");
|
|
66
50
|
expect(window.history.replaceState).not.toHaveBeenCalled();
|
|
67
|
-
expect(window.location.href).toBe("https://someUrl.com/redirect");
|
|
68
51
|
});
|
|
69
52
|
|
|
70
53
|
it("browser redirection uses replaceState if specified", () => {
|
|
@@ -77,7 +60,6 @@ describe("Redirector", () => {
|
|
|
77
60
|
"",
|
|
78
61
|
"https://someUrl.com/redirect",
|
|
79
62
|
);
|
|
80
|
-
expect(window.location.href).toBe("https://coolSite.com");
|
|
81
63
|
});
|
|
82
64
|
|
|
83
65
|
it("calls redirect handler", () => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -32,9 +31,8 @@ export const OidcHandlerHandleResponse: ISessionInfo =
|
|
|
32
31
|
SessionCreatorGetSessionResponse;
|
|
33
32
|
|
|
34
33
|
export const OidcHandlerMock: jest.Mocked<IOidcHandler> = {
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
36
34
|
canHandle: jest.fn((_options: IOidcOptions) => Promise.resolve(true)),
|
|
37
|
-
|
|
35
|
+
|
|
38
36
|
handle: jest.fn(async (_options: IOidcOptions) => Promise.resolve(undefined)),
|
|
39
37
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
38
|
} as any;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -38,7 +37,6 @@ export const IssuerConfigFetcherFetchConfigResponse: IIssuerConfig = {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
export const IssuerConfigFetcherMock: jest.Mocked<IIssuerConfigFetcher> = {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
42
40
|
fetchConfig: jest.fn((_issuer: string) =>
|
|
43
41
|
Promise.resolve(IssuerConfigFetcherFetchConfigResponse),
|
|
44
42
|
),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -31,12 +30,12 @@ import { USER_SESSION_PREFIX } from "@inrupt/solid-client-authn-core";
|
|
|
31
30
|
import {
|
|
32
31
|
StorageUtilityMock,
|
|
33
32
|
mockStorageUtility,
|
|
33
|
+
// eslint-disable-next-line import/no-unresolved
|
|
34
34
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
35
35
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
36
36
|
import type * as OidcClientExt from "@inrupt/oidc-client-ext";
|
|
37
|
-
import type { JWK } from "jose";
|
|
37
|
+
import type { JWK, CryptoKey } from "jose";
|
|
38
38
|
import { importJWK } from "jose";
|
|
39
|
-
import type { KeyObject } from "crypto";
|
|
40
39
|
import { AuthCodeRedirectHandler } from "./AuthCodeRedirectHandler";
|
|
41
40
|
import { SessionInfoManagerMock } from "../../../sessionInfo/__mocks__/SessionInfoManager";
|
|
42
41
|
import { LocalStorageMock } from "../../../storage/__mocks__/LocalStorage";
|
|
@@ -126,7 +125,7 @@ const mockTokenEndpointDpopResponse =
|
|
|
126
125
|
webId: mockWebId(),
|
|
127
126
|
clientId: "some client",
|
|
128
127
|
dpopKey: {
|
|
129
|
-
privateKey: (await importJWK(mockJwk())) as
|
|
128
|
+
privateKey: (await importJWK(mockJwk())) as CryptoKey,
|
|
130
129
|
// Note that here for convenience the private key is also used as public key.
|
|
131
130
|
// Obviously, this should never be done in non-test code.
|
|
132
131
|
publicKey: mockJwk(),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -42,7 +41,6 @@ import { getUnauthenticatedSession } from "../../../sessionInfo/SessionInfoManag
|
|
|
42
41
|
export class ErrorOidcHandler implements IIncomingRedirectHandler {
|
|
43
42
|
async canHandle(redirectUrl: string): Promise<boolean> {
|
|
44
43
|
try {
|
|
45
|
-
// eslint-disable-next-line no-new
|
|
46
44
|
return new URL(redirectUrl).searchParams.has("error");
|
|
47
45
|
} catch (e) {
|
|
48
46
|
throw new Error(
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -41,7 +40,7 @@ export class FallbackRedirectHandler implements IIncomingRedirectHandler {
|
|
|
41
40
|
async canHandle(redirectUrl: string): Promise<boolean> {
|
|
42
41
|
try {
|
|
43
42
|
// The next URL object is built for validating it.
|
|
44
|
-
|
|
43
|
+
|
|
45
44
|
new URL(redirectUrl);
|
|
46
45
|
return true;
|
|
47
46
|
} catch (e) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -33,6 +32,7 @@ import { StorageUtility } from "@inrupt/solid-client-authn-core";
|
|
|
33
32
|
import {
|
|
34
33
|
StorageUtilityMock,
|
|
35
34
|
mockStorage,
|
|
35
|
+
// eslint-disable-next-line import/no-unresolved
|
|
36
36
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
37
37
|
|
|
38
38
|
import AuthorizationCodeWithPkceOidcHandler from "./AuthorizationCodeWithPkceOidcHandler";
|
|
@@ -53,7 +53,6 @@ const mockOidcModule = (
|
|
|
53
53
|
url: string = expectedSigninRedirectUrl,
|
|
54
54
|
state = "test state",
|
|
55
55
|
) => {
|
|
56
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
56
|
const oidcModule = jest.requireMock("@inrupt/oidc-client-ext") as any;
|
|
58
57
|
oidcModule.OidcClient.mockReturnValue({
|
|
59
58
|
createSigninRequest: jest
|
|
@@ -91,7 +90,6 @@ describe("AuthorizationCodeWithPkceOidcHandler", () => {
|
|
|
91
90
|
getAuthorizationCodeWithPkceOidcHandler();
|
|
92
91
|
canHandleTests.authorizationCodeWithPkceOidcHandler.forEach(
|
|
93
92
|
(testConfig) => {
|
|
94
|
-
// eslint-disable-next-line jest/valid-title
|
|
95
93
|
it(testConfig.message, async () => {
|
|
96
94
|
const value = await authorizationCodeWithPkceOidcHandler.canHandle(
|
|
97
95
|
testConfig.oidcOptions,
|
|
@@ -138,7 +136,6 @@ describe("AuthorizationCodeWithPkceOidcHandler", () => {
|
|
|
138
136
|
// pretty nasty due to an Error instance being logged without being
|
|
139
137
|
// converted to a string:
|
|
140
138
|
|
|
141
|
-
// eslint-disable-next-line no-console
|
|
142
139
|
expect(console.error).toHaveBeenCalledTimes(1);
|
|
143
140
|
expect(
|
|
144
141
|
(console as jest.Mocked<Console>).error.mock.calls[0][0].toString(),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -35,6 +34,9 @@ import type {
|
|
|
35
34
|
import { AuthorizationCodeWithPkceOidcHandlerBase } from "@inrupt/solid-client-authn-core";
|
|
36
35
|
import { OidcClient } from "@inrupt/oidc-client-ext";
|
|
37
36
|
|
|
37
|
+
// Camelcase identifiers are required in the OIDC specification.
|
|
38
|
+
/* eslint-disable camelcase*/
|
|
39
|
+
|
|
38
40
|
/**
|
|
39
41
|
* @hidden
|
|
40
42
|
* Authorization code flow spec: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
|
|
@@ -45,12 +47,12 @@ export default class AuthorizationCodeWithPkceOidcHandler
|
|
|
45
47
|
implements IOidcHandler
|
|
46
48
|
{
|
|
47
49
|
async handle(oidcLoginOptions: IOidcOptions): Promise<LoginResult> {
|
|
48
|
-
|
|
50
|
+
const redirectUri = oidcLoginOptions.redirectUrl ?? "";
|
|
49
51
|
const oidcOptions = {
|
|
50
52
|
authority: oidcLoginOptions.issuer.toString(),
|
|
51
53
|
client_id: oidcLoginOptions.client.clientId,
|
|
52
54
|
client_secret: oidcLoginOptions.client.clientSecret,
|
|
53
|
-
redirect_uri:
|
|
55
|
+
redirect_uri: redirectUri,
|
|
54
56
|
response_type: "code",
|
|
55
57
|
scope: oidcLoginOptions.scopes.join(" "),
|
|
56
58
|
filterProtocolClaims: true,
|
|
@@ -58,26 +60,23 @@ export default class AuthorizationCodeWithPkceOidcHandler
|
|
|
58
60
|
// Note that in Solid, information should be retrieved from the
|
|
59
61
|
// profile referenced by the WebId.
|
|
60
62
|
loadUserInfo: false,
|
|
61
|
-
code_verifier: true,
|
|
62
63
|
prompt: oidcLoginOptions.prompt ?? "consent",
|
|
63
64
|
};
|
|
64
|
-
/* eslint-enable camelcase */
|
|
65
65
|
|
|
66
66
|
const oidcClientLibrary = new OidcClient(oidcOptions);
|
|
67
67
|
|
|
68
68
|
try {
|
|
69
|
-
const signingRequest = await oidcClientLibrary.createSigninRequest();
|
|
69
|
+
const signingRequest = await oidcClientLibrary.createSigninRequest({});
|
|
70
70
|
// Make sure to await the promise before returning so that the error is caught.
|
|
71
71
|
return await this.setupRedirectHandler({
|
|
72
72
|
oidcLoginOptions,
|
|
73
|
-
|
|
74
|
-
state: signingRequest.state.
|
|
75
|
-
|
|
76
|
-
codeVerifier: signingRequest.state.
|
|
73
|
+
|
|
74
|
+
state: signingRequest.state.id,
|
|
75
|
+
|
|
76
|
+
codeVerifier: signingRequest.state.code_verifier ?? "",
|
|
77
77
|
targetUrl: signingRequest.url.toString(),
|
|
78
78
|
});
|
|
79
79
|
} catch (err: unknown) {
|
|
80
|
-
// eslint-disable-next-line no-console
|
|
81
80
|
console.error(err);
|
|
82
81
|
}
|
|
83
82
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -28,12 +27,12 @@ import { EVENTS } from "@inrupt/solid-client-authn-core";
|
|
|
28
27
|
import {
|
|
29
28
|
StorageUtilityMock,
|
|
30
29
|
mockStorageUtility,
|
|
30
|
+
// eslint-disable-next-line import/no-unresolved
|
|
31
31
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
32
|
-
import type { JWK } from "jose";
|
|
32
|
+
import type { JWK, CryptoKey } from "jose";
|
|
33
33
|
import { importJWK } from "jose";
|
|
34
34
|
import type { refresh } from "@inrupt/oidc-client-ext";
|
|
35
35
|
import { EventEmitter } from "events";
|
|
36
|
-
import type { KeyObject } from "crypto";
|
|
37
36
|
import TokenRefresher from "./TokenRefresher";
|
|
38
37
|
import {
|
|
39
38
|
mockDefaultIssuerConfigFetcher,
|
|
@@ -70,7 +69,7 @@ const mockJwk = (): JWK => {
|
|
|
70
69
|
|
|
71
70
|
const mockKeyPair = async (): Promise<KeyPair> => {
|
|
72
71
|
return {
|
|
73
|
-
privateKey: (await importJWK(mockJwk())) as
|
|
72
|
+
privateKey: (await importJWK(mockJwk())) as CryptoKey,
|
|
74
73
|
// Use the same JWK for public and private key out of convenience, don't do
|
|
75
74
|
// this in real life.
|
|
76
75
|
publicKey: mockJwk(),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -42,7 +41,6 @@ import type { EventEmitter } from "events";
|
|
|
42
41
|
|
|
43
42
|
// Some identifiers are not in camelcase on purpose, as they are named using the
|
|
44
43
|
// official names from the OIDC/OAuth2 specifications.
|
|
45
|
-
/* eslint-disable camelcase */
|
|
46
44
|
|
|
47
45
|
/**
|
|
48
46
|
* @hidden
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -26,7 +25,6 @@ import type {
|
|
|
26
25
|
} from "@inrupt/solid-client-authn-core";
|
|
27
26
|
|
|
28
27
|
// Some identifiers are in camelcase on purpose.
|
|
29
|
-
/* eslint-disable camelcase */
|
|
30
28
|
|
|
31
29
|
export const mockTokenRefresher = (
|
|
32
30
|
tokenSet: TokenEndpointResponse,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -18,6 +17,7 @@
|
|
|
18
17
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
19
18
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
19
|
//
|
|
20
|
+
|
|
21
21
|
import type {
|
|
22
22
|
IEndSessionOptions,
|
|
23
23
|
IRpLogoutOptions,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -24,6 +23,7 @@ import {
|
|
|
24
23
|
StorageUtility,
|
|
25
24
|
mockStorage,
|
|
26
25
|
} from "@inrupt/solid-client-authn-core";
|
|
26
|
+
// eslint-disable-next-line import/no-unresolved
|
|
27
27
|
import { mockLogoutHandler } from "@inrupt/solid-client-authn-core/mocks";
|
|
28
28
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
29
29
|
|
|
@@ -130,6 +130,7 @@ describe("SessionInfoManager", () => {
|
|
|
130
130
|
refreshToken: "some refresh token",
|
|
131
131
|
redirectUrl: "https://some.redirect/url",
|
|
132
132
|
tokenType: "DPoP",
|
|
133
|
+
clientExpiresAt: undefined,
|
|
133
134
|
});
|
|
134
135
|
});
|
|
135
136
|
|
|
@@ -158,6 +159,7 @@ describe("SessionInfoManager", () => {
|
|
|
158
159
|
refreshToken: undefined,
|
|
159
160
|
redirectUrl: undefined,
|
|
160
161
|
tokenType: "DPoP",
|
|
162
|
+
clientExpiresAt: undefined,
|
|
161
163
|
});
|
|
162
164
|
});
|
|
163
165
|
|
|
@@ -219,6 +221,65 @@ describe("SessionInfoManager", () => {
|
|
|
219
221
|
);
|
|
220
222
|
});
|
|
221
223
|
|
|
224
|
+
it("returns clientExpiresAt when expiresAt is in storage", async () => {
|
|
225
|
+
const sessionId = "commanderCool";
|
|
226
|
+
const expiresAt = 1700000000;
|
|
227
|
+
|
|
228
|
+
const storageMock = new StorageUtility(
|
|
229
|
+
mockStorage({
|
|
230
|
+
[`solidClientAuthenticationUser:${sessionId}`]: {
|
|
231
|
+
isLoggedIn: "true",
|
|
232
|
+
},
|
|
233
|
+
}),
|
|
234
|
+
mockStorage({
|
|
235
|
+
[`solidClientAuthenticationUser:${sessionId}`]: {
|
|
236
|
+
clientId: "https://some.app/registration",
|
|
237
|
+
clientSecret: "some client secret",
|
|
238
|
+
issuer: "https://some.issuer",
|
|
239
|
+
expiresAt: String(expiresAt),
|
|
240
|
+
},
|
|
241
|
+
}),
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const sessionManager = getSessionInfoManager({
|
|
245
|
+
storageUtility: storageMock,
|
|
246
|
+
});
|
|
247
|
+
const session = await sessionManager.get(sessionId);
|
|
248
|
+
expect(session).toStrictEqual(
|
|
249
|
+
expect.objectContaining({
|
|
250
|
+
clientExpiresAt: expiresAt,
|
|
251
|
+
}),
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("returns undefined clientExpiresAt when expiresAt is not in storage", async () => {
|
|
256
|
+
const sessionId = "commanderCool";
|
|
257
|
+
|
|
258
|
+
const storageMock = new StorageUtility(
|
|
259
|
+
mockStorage({
|
|
260
|
+
[`solidClientAuthenticationUser:${sessionId}`]: {
|
|
261
|
+
isLoggedIn: "true",
|
|
262
|
+
},
|
|
263
|
+
}),
|
|
264
|
+
mockStorage({
|
|
265
|
+
[`solidClientAuthenticationUser:${sessionId}`]: {
|
|
266
|
+
clientId: "https://some.app/registration",
|
|
267
|
+
issuer: "https://some.issuer",
|
|
268
|
+
},
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
const sessionManager = getSessionInfoManager({
|
|
273
|
+
storageUtility: storageMock,
|
|
274
|
+
});
|
|
275
|
+
const session = await sessionManager.get(sessionId);
|
|
276
|
+
expect(session).toStrictEqual(
|
|
277
|
+
expect.objectContaining({
|
|
278
|
+
clientExpiresAt: undefined,
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
222
283
|
it("throws if the stored token type isn't supported", async () => {
|
|
223
284
|
const sessionId = "commanderCool";
|
|
224
285
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
1
|
// Copyright Inrupt Inc.
|
|
3
2
|
//
|
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -72,6 +71,7 @@ export class SessionInfoManager
|
|
|
72
71
|
refreshToken,
|
|
73
72
|
issuer,
|
|
74
73
|
tokenType,
|
|
74
|
+
expiresAt,
|
|
75
75
|
] = await Promise.all([
|
|
76
76
|
this.storageUtility.getForUser(sessionId, "isLoggedIn", {
|
|
77
77
|
secure: true,
|
|
@@ -97,6 +97,9 @@ export class SessionInfoManager
|
|
|
97
97
|
this.storageUtility.getForUser(sessionId, "tokenType", {
|
|
98
98
|
secure: false,
|
|
99
99
|
}),
|
|
100
|
+
this.storageUtility.getForUser(sessionId, "expiresAt", {
|
|
101
|
+
secure: false,
|
|
102
|
+
}),
|
|
100
103
|
]);
|
|
101
104
|
|
|
102
105
|
if (typeof redirectUrl === "string" && !isValidRedirectUrl(redirectUrl)) {
|
|
@@ -134,6 +137,8 @@ export class SessionInfoManager
|
|
|
134
137
|
clientAppSecret: clientSecret,
|
|
135
138
|
// Default the token type to DPoP if unspecified.
|
|
136
139
|
tokenType: tokenType ?? "DPoP",
|
|
140
|
+
clientExpiresAt:
|
|
141
|
+
expiresAt !== undefined ? Number.parseInt(expiresAt, 10) : undefined,
|
|
137
142
|
};
|
|
138
143
|
}
|
|
139
144
|
|