@inrupt/solid-client-authn-browser 1.17.4 → 2.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/dist/ClientAuthentication.d.ts +1 -0
- package/dist/Session.d.ts +4 -67
- package/dist/defaultSession.d.ts +0 -28
- package/dist/dependencies.d.ts +1 -2
- package/dist/index.d.ts +2 -3
- package/dist/index.js +16 -124
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -113
- package/dist/index.mjs.map +1 -1
- package/dist/login/oidc/__mocks__/IOidcOptions.d.ts +2 -0
- package/dist/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.d.ts +4 -0
- package/dist/solid-client-authn.bundle.js +19 -19
- package/dist/solid-client-authn.bundle.js.map +1 -1
- package/package.json +6 -7
- package/rollup.config.mjs +28 -14
- package/src/ClientAuthentication.spec.ts +1 -12
- package/src/Session.spec.ts +11 -178
- package/src/Session.ts +6 -98
- package/src/defaultSession.spec.ts +0 -18
- package/src/defaultSession.ts +0 -40
- package/src/dependencies.ts +1 -2
- package/src/index.spec.ts +1 -2
- package/src/index.ts +9 -3
- package/src/login/oidc/ClientRegistrar.spec.ts +8 -9
- package/src/login/oidc/IssuerConfigFetcher.spec.ts +17 -32
- package/src/login/oidc/IssuerConfigFetcher.ts +1 -5
- package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.spec.ts +9 -29
- package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.ts +6 -19
- package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.spec.ts +0 -11
- package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.spec.ts +1 -12
- package/.prettierignore +0 -3
- package/sampleFlows/SolidAuthClientArchitecture.png +0 -0
- package/sampleFlows/authorization-code-with-pkce.png +0 -0
- package/sampleFlows/authorization-code-with-pkce.seqdiag +0 -46
- package/sampleFlows/authorization-code.png +0 -0
- package/sampleFlows/authorization-code.seqdiag +0 -50
- package/sampleFlows/client-credentials.png +0 -0
- package/sampleFlows/client-credentials.seqdiag +0 -38
- package/sampleFlows/legacy-implicit-flow.png +0 -0
- package/sampleFlows/legacy-implicit-flow.seqdiag +0 -43
- package/sampleFlows/self-signed.png +0 -0
- package/sampleFlows/self-signed.seqdiag +0 -49
- package/sampleFlows/signatory-access-control.seqdiag +0 -36
- package/sampleFlows/signatory-access-control.svg +0 -1
- package/sonar-project.properties +0 -15
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
mockStorageUtility,
|
|
25
25
|
} from "@inrupt/solid-client-authn-core/mocks";
|
|
26
26
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
27
|
-
import { Response as NodeResponse } from "@inrupt/universal-fetch";
|
|
28
27
|
import ClientRegistrar from "./ClientRegistrar";
|
|
29
28
|
import { IssuerConfigFetcherFetchConfigResponse } from "./__mocks__/IssuerConfigFetcher";
|
|
30
29
|
|
|
@@ -47,14 +46,14 @@ describe("ClientRegistrar", () => {
|
|
|
47
46
|
// actual OIDC provider response.
|
|
48
47
|
const mockFetch = (jest.fn() as any).mockResolvedValueOnce(
|
|
49
48
|
/* eslint-disable camelcase */
|
|
50
|
-
new
|
|
49
|
+
new Response(
|
|
51
50
|
JSON.stringify({
|
|
52
51
|
client_id: "abcd",
|
|
53
52
|
client_secret: "1234",
|
|
54
53
|
redirect_uris: ["https://example.com"],
|
|
55
54
|
id_token_signed_response_alg: "RS256",
|
|
56
55
|
}),
|
|
57
|
-
)
|
|
56
|
+
),
|
|
58
57
|
/* eslint-enable camelcase */
|
|
59
58
|
);
|
|
60
59
|
global.fetch = mockFetch;
|
|
@@ -98,12 +97,12 @@ describe("ClientRegistrar", () => {
|
|
|
98
97
|
it("can register a public client without secret", async () => {
|
|
99
98
|
const mockFetch = (jest.fn() as any).mockResolvedValueOnce(
|
|
100
99
|
/* eslint-disable camelcase */
|
|
101
|
-
new
|
|
100
|
+
new Response(
|
|
102
101
|
JSON.stringify({
|
|
103
102
|
client_id: "abcd",
|
|
104
103
|
redirect_uris: ["https://example.com"],
|
|
105
104
|
}),
|
|
106
|
-
)
|
|
105
|
+
),
|
|
107
106
|
/* eslint-enable camelcase */
|
|
108
107
|
);
|
|
109
108
|
global.fetch = mockFetch;
|
|
@@ -144,9 +143,9 @@ describe("ClientRegistrar", () => {
|
|
|
144
143
|
it("handles a failure to dynamically register elegantly", async () => {
|
|
145
144
|
const mockFetch = (jest.fn() as any).mockResolvedValueOnce(
|
|
146
145
|
/* eslint-disable camelcase */
|
|
147
|
-
new
|
|
146
|
+
new Response('{"error":"bad stuff that\'s an error"}', {
|
|
148
147
|
status: 400,
|
|
149
|
-
})
|
|
148
|
+
}),
|
|
150
149
|
/* eslint-enable camelcase */
|
|
151
150
|
);
|
|
152
151
|
global.fetch = mockFetch;
|
|
@@ -198,13 +197,13 @@ describe("ClientRegistrar", () => {
|
|
|
198
197
|
it("saves dynamic registration information", async () => {
|
|
199
198
|
const mockFetch = (jest.fn() as any).mockResolvedValueOnce(
|
|
200
199
|
/* eslint-disable camelcase */
|
|
201
|
-
new
|
|
200
|
+
new Response(
|
|
202
201
|
JSON.stringify({
|
|
203
202
|
client_id: "some id",
|
|
204
203
|
client_secret: "some secret",
|
|
205
204
|
redirect_uris: ["https://example.com"],
|
|
206
205
|
}),
|
|
207
|
-
)
|
|
206
|
+
),
|
|
208
207
|
/* eslint-enable camelcase */
|
|
209
208
|
);
|
|
210
209
|
global.fetch = mockFetch;
|
|
@@ -21,24 +21,22 @@
|
|
|
21
21
|
|
|
22
22
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
23
23
|
import { mockStorageUtility } from "@inrupt/solid-client-authn-core";
|
|
24
|
-
import { Response as NodeResponse } from "@inrupt/universal-fetch";
|
|
25
|
-
import type * as UniversalFetch from "@inrupt/universal-fetch";
|
|
26
24
|
import IssuerConfigFetcher from "./IssuerConfigFetcher";
|
|
27
25
|
|
|
28
|
-
jest.mock("@inrupt/universal-fetch", () => {
|
|
29
|
-
const fetchModule = jest.requireActual(
|
|
30
|
-
"@inrupt/universal-fetch",
|
|
31
|
-
) as typeof UniversalFetch;
|
|
32
|
-
return {
|
|
33
|
-
...fetchModule,
|
|
34
|
-
fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(),
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
|
|
38
26
|
/**
|
|
39
27
|
* Test for IssuerConfigFetcher
|
|
40
28
|
*/
|
|
41
29
|
describe("IssuerConfigFetcher", () => {
|
|
30
|
+
let mockFetch: jest.SpiedFunction<typeof fetch>;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
mockFetch = jest.spyOn(globalThis, "fetch");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
jest.restoreAllMocks();
|
|
38
|
+
});
|
|
39
|
+
|
|
42
40
|
const defaultMocks = {
|
|
43
41
|
storageUtility: mockStorageUtility({}),
|
|
44
42
|
};
|
|
@@ -55,11 +53,9 @@ describe("IssuerConfigFetcher", () => {
|
|
|
55
53
|
const configFetcher = getIssuerConfigFetcher({
|
|
56
54
|
storageUtility: mockStorageUtility({}),
|
|
57
55
|
});
|
|
58
|
-
|
|
59
|
-
"@inrupt/universal-fetch",
|
|
60
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
56
|
+
|
|
61
57
|
mockFetch.mockResolvedValueOnce(
|
|
62
|
-
new
|
|
58
|
+
new Response(
|
|
63
59
|
JSON.stringify({
|
|
64
60
|
issuer: "https://example.com",
|
|
65
61
|
// eslint-disable-next-line camelcase
|
|
@@ -83,10 +79,7 @@ describe("IssuerConfigFetcher", () => {
|
|
|
83
79
|
});
|
|
84
80
|
|
|
85
81
|
it("should throw an error if the fetched config could not be converted to JSON", async () => {
|
|
86
|
-
|
|
87
|
-
"@inrupt/universal-fetch",
|
|
88
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
89
|
-
mockFetch.mockResolvedValueOnce(new NodeResponse("Not JSON."));
|
|
82
|
+
mockFetch.mockResolvedValueOnce(new Response("Not JSON."));
|
|
90
83
|
const configFetcher = new IssuerConfigFetcher(mockStorageUtility({}));
|
|
91
84
|
|
|
92
85
|
await expect(configFetcher.fetchConfig("https://some.url")).rejects.toThrow(
|
|
@@ -95,11 +88,8 @@ describe("IssuerConfigFetcher", () => {
|
|
|
95
88
|
});
|
|
96
89
|
|
|
97
90
|
it("should return a config including the support for solid-oidc if present in the discovery profile", async () => {
|
|
98
|
-
const { fetch: mockFetch } = jest.requireMock(
|
|
99
|
-
"@inrupt/universal-fetch",
|
|
100
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
101
91
|
mockFetch.mockResolvedValueOnce(
|
|
102
|
-
new
|
|
92
|
+
new Response(
|
|
103
93
|
JSON.stringify({
|
|
104
94
|
issuer: "https://example.com",
|
|
105
95
|
// eslint-disable-next-line camelcase
|
|
@@ -120,11 +110,8 @@ describe("IssuerConfigFetcher", () => {
|
|
|
120
110
|
});
|
|
121
111
|
|
|
122
112
|
it("should return a default value for the supported scopes if not advertized by the OpenID provider", async () => {
|
|
123
|
-
const { fetch: mockFetch } = jest.requireMock(
|
|
124
|
-
"@inrupt/universal-fetch",
|
|
125
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
126
113
|
mockFetch.mockResolvedValueOnce(
|
|
127
|
-
new
|
|
114
|
+
new Response(
|
|
128
115
|
JSON.stringify({
|
|
129
116
|
issuer: "https://example.com",
|
|
130
117
|
// eslint-disable-next-line camelcase
|
|
@@ -143,12 +130,10 @@ describe("IssuerConfigFetcher", () => {
|
|
|
143
130
|
|
|
144
131
|
it("should append the .well-known/openid-configuration path at the end of the issuer URL", async () => {
|
|
145
132
|
// The response value is irrelevant to this test.
|
|
146
|
-
|
|
147
|
-
"@inrupt/universal-fetch",
|
|
148
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
133
|
+
|
|
149
134
|
mockFetch.mockImplementation(
|
|
150
135
|
async () =>
|
|
151
|
-
new
|
|
136
|
+
new Response(
|
|
152
137
|
JSON.stringify({
|
|
153
138
|
issuer: "https://example.com",
|
|
154
139
|
// eslint-disable-next-line camelcase
|
|
@@ -33,7 +33,6 @@ import type {
|
|
|
33
33
|
IStorageUtility,
|
|
34
34
|
} from "@inrupt/solid-client-authn-core";
|
|
35
35
|
import { ConfigurationError } from "@inrupt/solid-client-authn-core";
|
|
36
|
-
import { fetch as uniFetch } from "@inrupt/universal-fetch";
|
|
37
36
|
|
|
38
37
|
export const WELL_KNOWN_OPENID_CONFIG = ".well-known/openid-configuration";
|
|
39
38
|
|
|
@@ -172,10 +171,7 @@ export default class IssuerConfigFetcher implements IIssuerConfigFetcher {
|
|
|
172
171
|
// includes the full issuer path. See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig.
|
|
173
172
|
issuer.endsWith("/") ? issuer : `${issuer}/`,
|
|
174
173
|
).href;
|
|
175
|
-
const issuerConfigRequestBody = await
|
|
176
|
-
globalThis,
|
|
177
|
-
openIdConfigUrl,
|
|
178
|
-
);
|
|
174
|
+
const issuerConfigRequestBody = await fetch(openIdConfigUrl);
|
|
179
175
|
// Check the validity of the fetched config
|
|
180
176
|
try {
|
|
181
177
|
issuerConfig = processConfig(await issuerConfigRequestBody.json());
|
|
@@ -35,8 +35,6 @@ import {
|
|
|
35
35
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
36
36
|
import { getBearerToken } from "@inrupt/oidc-client-ext";
|
|
37
37
|
import type * as OidcClientExt from "@inrupt/oidc-client-ext";
|
|
38
|
-
import { fetch, Response, Headers } from "@inrupt/universal-fetch";
|
|
39
|
-
import type * as UniversalFetch from "@inrupt/universal-fetch";
|
|
40
38
|
import type { JWK } from "jose";
|
|
41
39
|
import { importJWK } from "jose";
|
|
42
40
|
import type { KeyObject } from "crypto";
|
|
@@ -48,15 +46,7 @@ import {
|
|
|
48
46
|
mockTokenRefresher,
|
|
49
47
|
} from "../refresh/__mocks__/TokenRefresher";
|
|
50
48
|
|
|
51
|
-
jest.
|
|
52
|
-
const fetchModule = jest.requireActual(
|
|
53
|
-
"@inrupt/universal-fetch",
|
|
54
|
-
) as typeof UniversalFetch;
|
|
55
|
-
return {
|
|
56
|
-
...fetchModule,
|
|
57
|
-
fetch: jest.fn<typeof fetch>(),
|
|
58
|
-
};
|
|
59
|
-
});
|
|
49
|
+
const mockedFetch = jest.spyOn(globalThis, "fetch");
|
|
60
50
|
|
|
61
51
|
const mockJwk = (): JWK => {
|
|
62
52
|
return {
|
|
@@ -202,9 +192,6 @@ function mockClientRegistrar(client: IClient): IClientRegistrar {
|
|
|
202
192
|
}
|
|
203
193
|
|
|
204
194
|
const mockFetch = (response: Response) => {
|
|
205
|
-
const { fetch: mockedFetch } = jest.requireMock(
|
|
206
|
-
"@inrupt/universal-fetch",
|
|
207
|
-
) as jest.Mocked<typeof UniversalFetch>;
|
|
208
195
|
mockedFetch.mockResolvedValueOnce(response);
|
|
209
196
|
return mockedFetch;
|
|
210
197
|
};
|
|
@@ -416,7 +403,6 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
416
403
|
|
|
417
404
|
it("returns an authenticated bearer fetch if requested", async () => {
|
|
418
405
|
mockOidcClient();
|
|
419
|
-
const mockedFetch = jest.mocked<typeof fetch>(fetch);
|
|
420
406
|
mockedFetch.mockResolvedValueOnce(
|
|
421
407
|
new Response("", {
|
|
422
408
|
status: 200,
|
|
@@ -427,9 +413,8 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
427
413
|
storageUtility: mockDefaultStorageUtility({ dpop: false }),
|
|
428
414
|
});
|
|
429
415
|
|
|
430
|
-
const redirectInfo =
|
|
431
|
-
mockRedirectUrl()
|
|
432
|
-
);
|
|
416
|
+
const redirectInfo =
|
|
417
|
+
await authCodeRedirectHandler.handle(mockRedirectUrl());
|
|
433
418
|
|
|
434
419
|
// This will call the oidc-client-ext module, which is mocked at
|
|
435
420
|
// the top of this file. The purpose of this test is to check that, if
|
|
@@ -444,7 +429,6 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
444
429
|
|
|
445
430
|
it("returns an authenticated DPoP fetch if requested", async () => {
|
|
446
431
|
mockOidcClient();
|
|
447
|
-
const mockedFetch = jest.mocked<typeof fetch>(fetch);
|
|
448
432
|
mockedFetch.mockResolvedValueOnce(
|
|
449
433
|
new Response("", {
|
|
450
434
|
status: 200,
|
|
@@ -454,9 +438,8 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
454
438
|
const authCodeRedirectHandler = getAuthCodeRedirectHandler({
|
|
455
439
|
storageUtility: mockDefaultStorageUtility({ dpop: true }),
|
|
456
440
|
});
|
|
457
|
-
const redirectInfo =
|
|
458
|
-
mockRedirectUrl()
|
|
459
|
-
);
|
|
441
|
+
const redirectInfo =
|
|
442
|
+
await authCodeRedirectHandler.handle(mockRedirectUrl());
|
|
460
443
|
await redirectInfo.fetch("https://some.other.url");
|
|
461
444
|
|
|
462
445
|
const header = new Headers(mockedFetch.mock.calls[0][1]?.headers);
|
|
@@ -525,9 +508,8 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
525
508
|
storageUtility: mockDefaultStorageUtility(),
|
|
526
509
|
});
|
|
527
510
|
|
|
528
|
-
const sessionInfo =
|
|
529
|
-
mockRedirectUrl()
|
|
530
|
-
);
|
|
511
|
+
const sessionInfo =
|
|
512
|
+
await authCodeRedirectHandler.handle(mockRedirectUrl());
|
|
531
513
|
|
|
532
514
|
expect(sessionInfo.expirationDate).toBe(
|
|
533
515
|
MOCK_TIMESTAMP + MOCK_EXPIRE_TIME * 1000,
|
|
@@ -552,9 +534,8 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
552
534
|
storageUtility: mockedStorage,
|
|
553
535
|
});
|
|
554
536
|
|
|
555
|
-
const sessionInfo =
|
|
556
|
-
mockRedirectUrl()
|
|
557
|
-
);
|
|
537
|
+
const sessionInfo =
|
|
538
|
+
await authCodeRedirectHandler.handle(mockRedirectUrl());
|
|
558
539
|
|
|
559
540
|
expect(sessionInfo.expirationDate).toBeUndefined();
|
|
560
541
|
});
|
|
@@ -598,7 +579,6 @@ describe("AuthCodeRedirectHandler", () => {
|
|
|
598
579
|
await authCodeRedirectHandler.handle(mockRedirectUrl());
|
|
599
580
|
|
|
600
581
|
expect(mockAuthenticatedFetchBuild).toHaveBeenCalledWith(
|
|
601
|
-
expect.anything(),
|
|
602
582
|
expect.anything(),
|
|
603
583
|
expect.objectContaining({
|
|
604
584
|
refreshOptions: {
|
|
@@ -23,12 +23,6 @@
|
|
|
23
23
|
* @hidden
|
|
24
24
|
* @packageDocumentation
|
|
25
25
|
*/
|
|
26
|
-
// FIXME: The following doesn't work in the browser, it results in all the fetches
|
|
27
|
-
// being unauthenticated. This should be looked into when migrating to universal-fetch.
|
|
28
|
-
// import { fetch } from "cross-fetch";
|
|
29
|
-
|
|
30
|
-
import { fetch as uniFetch } from "@inrupt/universal-fetch";
|
|
31
|
-
|
|
32
26
|
import type {
|
|
33
27
|
IClient,
|
|
34
28
|
IClientRegistrar,
|
|
@@ -49,9 +43,6 @@ import type { CodeExchangeResult } from "@inrupt/oidc-client-ext";
|
|
|
49
43
|
import { getDpopToken, getBearerToken } from "@inrupt/oidc-client-ext";
|
|
50
44
|
import type { EventEmitter } from "events";
|
|
51
45
|
|
|
52
|
-
const globalFetch: typeof uniFetch = (...args) =>
|
|
53
|
-
uniFetch.call(globalThis, ...args);
|
|
54
|
-
|
|
55
46
|
/**
|
|
56
47
|
* @hidden
|
|
57
48
|
*/
|
|
@@ -171,16 +162,12 @@ export class AuthCodeRedirectHandler implements IIncomingRedirectHandler {
|
|
|
171
162
|
};
|
|
172
163
|
}
|
|
173
164
|
|
|
174
|
-
const authFetch = await buildAuthenticatedFetch(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
eventEmitter,
|
|
181
|
-
expiresIn: tokens.expiresIn,
|
|
182
|
-
},
|
|
183
|
-
);
|
|
165
|
+
const authFetch = await buildAuthenticatedFetch(tokens.accessToken, {
|
|
166
|
+
dpopKey: tokens.dpopKey,
|
|
167
|
+
refreshOptions,
|
|
168
|
+
eventEmitter,
|
|
169
|
+
expiresIn: tokens.expiresIn,
|
|
170
|
+
});
|
|
184
171
|
|
|
185
172
|
await this.storageUtility.setForUser(
|
|
186
173
|
storedSessionId,
|
|
@@ -22,19 +22,8 @@
|
|
|
22
22
|
import { jest, it, describe, expect } from "@jest/globals";
|
|
23
23
|
import { EventEmitter } from "events";
|
|
24
24
|
import { EVENTS } from "@inrupt/solid-client-authn-core";
|
|
25
|
-
import type * as UniversalFetch from "@inrupt/universal-fetch";
|
|
26
25
|
import { ErrorOidcHandler } from "./ErrorOidcHandler";
|
|
27
26
|
|
|
28
|
-
jest.mock("@inrupt/universal-fetch", () => {
|
|
29
|
-
const fetchModule = jest.requireActual(
|
|
30
|
-
"@inrupt/universal-fetch",
|
|
31
|
-
) as typeof UniversalFetch;
|
|
32
|
-
return {
|
|
33
|
-
...fetchModule,
|
|
34
|
-
fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(),
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
|
|
38
27
|
describe("ErrorOidcHandler", () => {
|
|
39
28
|
describe("canHandle", () => {
|
|
40
29
|
it("Does not handle IRIs without an error parameter", async () => {
|
|
@@ -19,20 +19,9 @@
|
|
|
19
19
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
20
|
//
|
|
21
21
|
|
|
22
|
-
import {
|
|
23
|
-
import type * as UniversalFetch from "@inrupt/universal-fetch";
|
|
22
|
+
import { it, describe, expect } from "@jest/globals";
|
|
24
23
|
import { FallbackRedirectHandler } from "./FallbackRedirectHandler";
|
|
25
24
|
|
|
26
|
-
jest.mock("@inrupt/universal-fetch", () => {
|
|
27
|
-
const fetchModule = jest.requireActual(
|
|
28
|
-
"@inrupt/universal-fetch",
|
|
29
|
-
) as typeof UniversalFetch;
|
|
30
|
-
return {
|
|
31
|
-
...fetchModule,
|
|
32
|
-
fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(),
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
|
|
36
25
|
describe("FallbackRedirectHandler", () => {
|
|
37
26
|
describe("canHandle", () => {
|
|
38
27
|
it("always accept the given IRI", async () => {
|
package/.prettierignore
DELETED
|
Binary file
|
|
Binary file
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
title: Authorization Code Flow with PKCE
|
|
2
|
-
|
|
3
|
-
note left of RP: AUTHORIZATION
|
|
4
|
-
note over RP: 1.Alice uses the decentphotos app
|
|
5
|
-
note over RP: 2. Alice selets her OP or WebID
|
|
6
|
-
RP->Alice's Pod (RS): 2.1 Retrieve Profile
|
|
7
|
-
Alice's Pod (RS)->RP:
|
|
8
|
-
RP->Alice's OP: 3. Requests OP configuration
|
|
9
|
-
Alice's OP->RP: 4. Returns OP configuration
|
|
10
|
-
RP->Alice's OP: 5. Requests OP JWKS
|
|
11
|
-
Alice's OP->RP: 6. Returns OP JWKS
|
|
12
|
-
note over RP: 7. Generates Private/Public key pair
|
|
13
|
-
note over RP: 8. Generates PKCE nonce
|
|
14
|
-
note over RP: 9. Saves both to local storage
|
|
15
|
-
RP->Alice's OP: 10. Authorization Request
|
|
16
|
-
Alice's OP->Decentphotos WebID: 11. Retrieves WebID
|
|
17
|
-
Decentphotos WebID->Alice's OP:
|
|
18
|
-
note over Alice's OP: 11. Validates redirect protocol with WebID
|
|
19
|
-
note over Alice's OP: 12. Gets Alice's consent
|
|
20
|
-
note over Alice's OP: 13. Generates an id_vc
|
|
21
|
-
Alice's OP->RP: 12. Sends code to redirect protocol
|
|
22
|
-
RP->Alice's OP: 13. Token requst with code and nonce proof
|
|
23
|
-
note over Alice's OP: 14. Validates nonce proof
|
|
24
|
-
Alice's OP->RP: 15. Sends id_vc inside id_token
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
note left of RP: SENDING REQUEST
|
|
28
|
-
note over RP: 1. Creates a pop_token
|
|
29
|
-
RP->Bob's Pod (RS): 2. Request sent
|
|
30
|
-
note over Bob's Pod (RS): 3. Checks pop_token Audience
|
|
31
|
-
note over Bob's Pod (RS): 4. Checks client signature
|
|
32
|
-
Bob's Pod (RS)->Alice's Pod (RS): 5. Retrieves Profile
|
|
33
|
-
Alice's Pod (RS)->Bob's Pod (RS):
|
|
34
|
-
note over Bob's Pod (RS): 6. Checks Issuer
|
|
35
|
-
Bob's Pod (RS)->Alice's OP: 7. Retrieves OP configuration
|
|
36
|
-
Alice's OP->Bob's Pod (RS):
|
|
37
|
-
Bob's Pod (RS)->Alice's OP: 8. Requests JWKS
|
|
38
|
-
Alice's OP->Bob's Pod (RS):
|
|
39
|
-
note over Bob's Pod (RS): 9. Performs Authentication
|
|
40
|
-
note over Bob's Pod (RS): 10. Performs Authorization
|
|
41
|
-
Bob's Pod (RS)->RP: 11. Returns Result
|
|
42
|
-
|
|
43
|
-
note left of RP: REFRESH TOKEN
|
|
44
|
-
Bob's Pod (RS)->RP: 1. 401: token expired
|
|
45
|
-
RP->Alice's OP: 2. Refresh token auth request
|
|
46
|
-
Alice's OP->RP: 3. Return updated token
|
|
Binary file
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
title: Authorization Code Grant
|
|
2
|
-
|
|
3
|
-
note left of Alice's Browser: Authorization
|
|
4
|
-
note over Decentphotos Server: 1. Has a public/private keypair
|
|
5
|
-
note over Decentphotos WebID: 1. Has pub key cert
|
|
6
|
-
note over Alice's Browser: 2. Alice navigates to decentphotos.example
|
|
7
|
-
Alice's Browser->Decentphotos Server: 3. Retrieves webpage with session
|
|
8
|
-
Decentphotos Server->Alice's Browser:
|
|
9
|
-
note over Alice's Browser: 4. Alice selets her OP or WebID
|
|
10
|
-
Alice's Browser->Decentphotos Server: 5. Requests login with OP / WebID
|
|
11
|
-
Decentphotos Server->Alice's Pod (RS): 5.1 Retrieve Profile
|
|
12
|
-
Alice's Pod (RS)->Decentphotos Server:
|
|
13
|
-
Decentphotos Server->Alice's OP: 6. Requests OP configuration
|
|
14
|
-
Alice's OP->Decentphotos Server:
|
|
15
|
-
Decentphotos Server->Alice's OP: 7. Requests OP JWKS
|
|
16
|
-
Alice's OP->Decentphotos Server:
|
|
17
|
-
Decentphotos Server->Alice's Browser: 8. Redirects to Auth endpoint
|
|
18
|
-
Alice's Browser->Alice's OP: 9. Authorization Request
|
|
19
|
-
note over Alice's OP: 10. Gets Alice's consent
|
|
20
|
-
Alice's OP->Alice's Browser: 11. Returns to redirect_url with access_code
|
|
21
|
-
Alice's Browser-> Decentphotos Server: 12. Transfers Access Code
|
|
22
|
-
Decentphotos Server->Alice's OP: 13. Auth request with proof of private key
|
|
23
|
-
Alice's OP->Decentphotos WebID: 14. Retrieves app WebID
|
|
24
|
-
Decentphotos WebID->Alice's OP:
|
|
25
|
-
note over Alice's OP: 15. Validates cert with WebID
|
|
26
|
-
note over Alice's OP: 16. Generates an access_code
|
|
27
|
-
Alice's OP->Decentphotos Server: 17. Returns access_code and refresh_token
|
|
28
|
-
|
|
29
|
-
note left of Alice's Browser: SENDING REQUEST
|
|
30
|
-
Alice's Browser->Decentphotos Server: 1. Sends Request details
|
|
31
|
-
note over Decentphotos Server: 2. Creates a pop_token
|
|
32
|
-
Decentphotos Server->Bob's Pod (RS): 3. Request sent
|
|
33
|
-
note over Bob's Pod (RS): 4. Checks pop_token Audience
|
|
34
|
-
note over Bob's Pod (RS): 5. Checks client signature
|
|
35
|
-
Bob's Pod (RS)->Alice's Pod (RS): 6. Retrieves Profile
|
|
36
|
-
Alice's Pod (RS)->Bob's Pod (RS):
|
|
37
|
-
note over Bob's Pod (RS): 7. Checks Issuer
|
|
38
|
-
Bob's Pod (RS)->Alice's OP: 8. Retrieves OP configuration
|
|
39
|
-
Alice's OP->Bob's Pod (RS):
|
|
40
|
-
Bob's Pod (RS)->Alice's OP: 9. Requests JWKS
|
|
41
|
-
Alice's OP->Bob's Pod (RS):
|
|
42
|
-
note over Bob's Pod (RS): 10. Performs Authentication
|
|
43
|
-
note over Bob's Pod (RS): 11. Performs Authorization
|
|
44
|
-
Bob's Pod (RS)->Decentphotos Server: 12. Returns Result
|
|
45
|
-
Decentphotos Server->Alice's Browser: 13. Returns result
|
|
46
|
-
|
|
47
|
-
note left of Alice's Browser: REFRESH pop_token
|
|
48
|
-
Bob's Pod (RS)->Decentphotos Server: 1. 401: token expired
|
|
49
|
-
Decentphotos Server->Alice's OP: 2. Refresh token auth request
|
|
50
|
-
Alice's OP->Decentphotos Server: 3. Return updated token
|
|
Binary file
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
title: Client Credentials Grant
|
|
2
|
-
|
|
3
|
-
note left of RP: AUTHORIZATION
|
|
4
|
-
note over RP: 1. Alice's server knows a client_secret and OP
|
|
5
|
-
RP->Alice's OP: 2. Requests OP configuration
|
|
6
|
-
Alice's OP->RP: 3. Returns OP configuration
|
|
7
|
-
RP->Alice's OP: 4. Requests OP JWKS
|
|
8
|
-
Alice's OP->RP: 5. Returns OP JWKS
|
|
9
|
-
note over RP: 6. Generates Private/Public key pair
|
|
10
|
-
note over RP: 7. Saves Private/Public key pair to local storage
|
|
11
|
-
RP->Alice's OP: 8. Authorization Request
|
|
12
|
-
Alice's OP->RP WebID: 9. Retrieves WebID
|
|
13
|
-
RP WebID->Alice's OP:
|
|
14
|
-
note over Alice's OP: 10. Validates redirect_url with WebID
|
|
15
|
-
note over Alice's OP: 11. Validate Client Secret
|
|
16
|
-
note over Alice's OP: 12. Generates an access_token
|
|
17
|
-
Alice's OP->RP: 12. Returns to redirect_url
|
|
18
|
-
|
|
19
|
-
note left of RP: SENDING REQUEST
|
|
20
|
-
note over RP: 1. Creates a pop_token
|
|
21
|
-
RP->Bob's Pod (RS): 2. Request sent
|
|
22
|
-
note over Bob's Pod (RS): 3. Checks pop_token Audience
|
|
23
|
-
note over Bob's Pod (RS): 4. Checks client signature
|
|
24
|
-
Bob's Pod (RS)->Alice's Pod (RS): 5. Retrieves Profile
|
|
25
|
-
Alice's Pod (RS)->Bob's Pod (RS):
|
|
26
|
-
note over Bob's Pod (RS): 6. Checks Issuer
|
|
27
|
-
Bob's Pod (RS)->Alice's OP: 7. Retrieves OP configuration
|
|
28
|
-
Alice's OP->Bob's Pod (RS):
|
|
29
|
-
Bob's Pod (RS)->Alice's OP: 8. Requests JWKS
|
|
30
|
-
Alice's OP->Bob's Pod (RS):
|
|
31
|
-
note over Bob's Pod (RS): 9. Performs Authentication
|
|
32
|
-
note over Bob's Pod (RS): 10. Performs Authorization
|
|
33
|
-
Bob's Pod (RS)->RP: 11. Returns Result
|
|
34
|
-
|
|
35
|
-
note left of RP: REFRESH TOKEN
|
|
36
|
-
Bob's Pod (RS)->RP: 1. 401: token expired
|
|
37
|
-
RP->Alice's OP: 2. Refresh token auth request
|
|
38
|
-
Alice's OP->RP: 3. Return updated token
|
|
Binary file
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
title: Legacy Implicit Flow
|
|
2
|
-
|
|
3
|
-
note left of RP: AUTHORIZATION
|
|
4
|
-
note over RP: 1. Alice navigates to decentphotos.example
|
|
5
|
-
note over RP: 2. Alice selets her OP or WebID
|
|
6
|
-
RP->Alice's Pod (RS): 2.1 Retrieve Profile
|
|
7
|
-
Alice's Pod (RS)->RP:
|
|
8
|
-
RP->Alice's OP: 3. Requests OP configuration
|
|
9
|
-
Alice's OP->RP: 4. Returns OP configuration
|
|
10
|
-
RP->Alice's OP: 5. Requests OP JWKS
|
|
11
|
-
Alice's OP->RP: 6. Returns OP JWKS
|
|
12
|
-
note over RP: 7. Generates Private/Public key pair
|
|
13
|
-
note over RP: 8. Saves Private/Public key pair to local storage
|
|
14
|
-
RP->Alice's OP: 9. Authorization Request
|
|
15
|
-
Alice's OP->Decentphotos WebID: 10. Retrieves WebID
|
|
16
|
-
Decentphotos WebID->Alice's OP:
|
|
17
|
-
note over Alice's OP: 11. Validates redirect_url with WebID
|
|
18
|
-
note over Alice's OP: 12. Gets Alice's consent
|
|
19
|
-
note over Alice's OP: 13. Generates an access_token
|
|
20
|
-
Alice's OP->RP: 12. Returns to redirect_url
|
|
21
|
-
|
|
22
|
-
note left of RP: SENDING REQUEST
|
|
23
|
-
note over RP: 1. Creates a pop_token
|
|
24
|
-
RP->Bob's Pod (RS): 2. Request sent
|
|
25
|
-
note over Bob's Pod (RS): 3. Checks pop_token Audience
|
|
26
|
-
note over Bob's Pod (RS): 4. Checks client signature
|
|
27
|
-
Bob's Pod (RS)->Alice's Pod (RS): 5. Retrieves Profile
|
|
28
|
-
Alice's Pod (RS)->Bob's Pod (RS):
|
|
29
|
-
note over Bob's Pod (RS): 6. Checks Issuer
|
|
30
|
-
Bob's Pod (RS)->Alice's OP: 7. Retrieves OP configuration
|
|
31
|
-
Alice's OP->Bob's Pod (RS):
|
|
32
|
-
Bob's Pod (RS)->Alice's OP: 8. Requests JWKS
|
|
33
|
-
Alice's OP->Bob's Pod (RS):
|
|
34
|
-
note over Bob's Pod (RS): 9. Performs Authentication
|
|
35
|
-
note over Bob's Pod (RS): 10. Performs Authorization
|
|
36
|
-
Bob's Pod (RS)->RP: 11. Returns Result
|
|
37
|
-
|
|
38
|
-
note left of RP: SILENT REFRESH
|
|
39
|
-
Bob's Pod (RS)->RP: 1. 401: token expired
|
|
40
|
-
note over RP: 2. Opens iFrame to OP
|
|
41
|
-
RP->Alice's OP: 3. Authorization Request with prompt=none
|
|
42
|
-
Alice's OP->RP: 4. Return updated token
|
|
43
|
-
|
|
Binary file
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
title: Self Issued Flow
|
|
2
|
-
|
|
3
|
-
note left of RP: AUTHENTICATION
|
|
4
|
-
note over RP: 1. Alice uses the Decentphotos App
|
|
5
|
-
note over OP: 2. Alice has a self-signed app installed
|
|
6
|
-
note over OP: It knows Alice's private key
|
|
7
|
-
note over Alice's WebID: 3. issuer: selfissued.me
|
|
8
|
-
note over Alice's WebID: Knows Alice's pub cert
|
|
9
|
-
note over RP: 4. Alice selects her OP or WebID
|
|
10
|
-
RP->Alice's WebID: 4.1 Gets WebID
|
|
11
|
-
Alice's WebID->RP:
|
|
12
|
-
RP->OP: 5. Requests OP configuration
|
|
13
|
-
OP->RP:
|
|
14
|
-
RP->OP: 6. Requests OP JWKS
|
|
15
|
-
OP->RP:
|
|
16
|
-
note over RP: 7. Generates Private/Public key pair
|
|
17
|
-
note over RP: 8. Generates PKCE nonce
|
|
18
|
-
note over RP: 9. Saves both to local storage
|
|
19
|
-
RP->OP: 10. Authorization Request
|
|
20
|
-
OP->Decentphotos WebID: 11. Retrieves WebID
|
|
21
|
-
Decentphotos WebID->OP:
|
|
22
|
-
note over OP: 11. Validates redirect protocol with WebID
|
|
23
|
-
note over OP: 12. Gets Alice's consent
|
|
24
|
-
note over OP: 13. Generates an access_code
|
|
25
|
-
OP->RP: 12. Sends code to redirect protocol
|
|
26
|
-
RP->OP: 13. Token requst with code and nonce proof
|
|
27
|
-
note over OP: 14. Validates nonce proof
|
|
28
|
-
OP->RP: 15. Sends access_token
|
|
29
|
-
|
|
30
|
-
note left of RP: SENDING REQUEST
|
|
31
|
-
note over RP: 1. Creates a pop_token
|
|
32
|
-
RP->Bob's Pod (RS): 2. Request sent
|
|
33
|
-
note over Bob's Pod (RS): 3. Checks pop_token Audience
|
|
34
|
-
note over Bob's Pod (RS): 4. Checks client signature
|
|
35
|
-
Bob's Pod (RS)->Alice's WebID: 5. Retrieves Profile
|
|
36
|
-
Alice's WebID->Bob's Pod (RS):
|
|
37
|
-
note over Bob's Pod (RS): 6. Checks that access_token cert matches WebID
|
|
38
|
-
Bob's Pod (RS)->OP: 7. Retrieves OP configuration
|
|
39
|
-
OP->Bob's Pod (RS):
|
|
40
|
-
Bob's Pod (RS)->OP: 8. Requests JWKS
|
|
41
|
-
OP->Bob's Pod (RS):
|
|
42
|
-
note over Bob's Pod (RS): 9. Performs Authentication
|
|
43
|
-
note over Bob's Pod (RS): 10. Performs Authorization
|
|
44
|
-
Bob's Pod (RS)->RP: 11. Returns Result
|
|
45
|
-
|
|
46
|
-
note left of RP: REFRESH TOKEN
|
|
47
|
-
Bob's Pod (RS)->RP: 1. 401: token expired
|
|
48
|
-
RP->OP: 2. Refresh token auth request
|
|
49
|
-
OP->RP: 3. Return updated token
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
title: Legacy Implicit Flow
|
|
2
|
-
|
|
3
|
-
note left of RP: AUTHORIZATION
|
|
4
|
-
note over RP: 1. Alice navigates to badguys.com
|
|
5
|
-
note over RP: 2. Alice selects her OP or WebID
|
|
6
|
-
RP->Alice's WebId: 2.1 Retrieve Profile
|
|
7
|
-
Alice's WebId->RP:
|
|
8
|
-
RP->Alice's OP: 3. Get OP configuration
|
|
9
|
-
Alice's OP->RP:
|
|
10
|
-
RP->Alice's OP: 4. Get OP JWKS
|
|
11
|
-
Alice's OP->RP:
|
|
12
|
-
note over RP: 5. Generates Private/Public key pair
|
|
13
|
-
note over RP: 6. Saves Private/Public key pair to local storage
|
|
14
|
-
RP->Alice's OP: 7. Authorization Request
|
|
15
|
-
Alice's OP->badguys.com WebId: 8. Retrieves WebID
|
|
16
|
-
badguys.com WebId->Alice's OP:
|
|
17
|
-
note over Alice's OP: 9. Validates redirect_url with WebID
|
|
18
|
-
note over Alice's OP: 10. Gets Alice's consent
|
|
19
|
-
note over Alice's OP: 11. Generates an access_token
|
|
20
|
-
Alice's OP->RP: 12. Returns to redirect_url
|
|
21
|
-
|
|
22
|
-
note left of RP: SENDING REQUEST
|
|
23
|
-
note over RP: 1. Creates a pop_token
|
|
24
|
-
RP->Bob's Pod (RS): 2. Request sent
|
|
25
|
-
note over Bob's Pod (RS): 3. Checks pop_token Audience
|
|
26
|
-
note over Bob's Pod (RS): 4. Checks client signature
|
|
27
|
-
Bob's Pod (RS)->Alice's WebId: 5. Retrieves Subject Profile
|
|
28
|
-
Alice's WebId->Bob's Pod (RS):
|
|
29
|
-
note over Bob's Pod (RS): 6. Checks Issuer
|
|
30
|
-
Bob's Pod (RS)->Alice's OP: 7. Retrieves OP configuration
|
|
31
|
-
Alice's OP->Bob's Pod (RS):
|
|
32
|
-
Bob's Pod (RS)->Alice's OP: 8. Requests JWKS
|
|
33
|
-
Alice's OP->Bob's Pod (RS):
|
|
34
|
-
note over Bob's Pod (RS): 9. Performs Authentication
|
|
35
|
-
note over Bob's Pod (RS): 10. Performs Authorization
|
|
36
|
-
Bob's Pod (RS)->RP: 11. Returns Result
|