@inrupt/solid-client-authn-browser 1.11.8-alpha.1 → 1.11.8-alpha.2
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 +18 -17
- package/dist/Session.d.ts +35 -35
- package/dist/constant.d.ts +2 -2
- package/dist/defaultSession.d.ts +9 -9
- package/dist/dependencies.d.ts +6 -6
- package/dist/iframe.d.ts +3 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.es.js +1693 -0
- package/dist/index.js +1717 -27
- package/dist/login/AggregateLoginHandler.d.ts +4 -4
- package/dist/login/oidc/AggregateOidcHandler.d.ts +4 -4
- package/dist/login/oidc/ClientRegistrar.d.ts +6 -6
- package/dist/login/oidc/IssuerConfigFetcher.d.ts +8 -8
- package/dist/login/oidc/OidcLoginHandler.d.ts +10 -10
- package/dist/login/oidc/Redirector.d.ts +4 -4
- package/dist/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.d.ts +8 -8
- package/dist/login/oidc/oidcHandlers/OidcHandlerCanHandleTest.d.ts +9 -9
- package/dist/login/oidc/redirectHandler/AggregateRedirectHandler.d.ts +4 -4
- package/dist/login/oidc/redirectHandler/AuthCodeRedirectHandler.d.ts +15 -15
- package/dist/login/oidc/redirectHandler/ErrorOidcHandler.d.ts +9 -9
- package/dist/login/oidc/redirectHandler/FallbackRedirectHandler.d.ts +7 -7
- package/dist/login/oidc/refresh/TokenRefresher.d.ts +10 -10
- package/dist/login/webid/WebIdLoginHandler.d.ts +5 -5
- package/dist/logout/GeneralLogoutHandler.d.ts +7 -7
- package/dist/sessionInfo/SessionInfoManager.d.ts +16 -16
- package/dist/solid-client-authn.bundle.js +1720 -2
- package/dist/storage/BrowserStorage.d.ts +7 -7
- package/dist/storage/StorageUtility.d.ts +4 -4
- package/dist/util/UuidGenerator.d.ts +6 -6
- package/dist/util/urlPath.d.ts +1 -1
- package/examples/demoClientApp/package-lock.json +67 -0
- package/examples/demoClientApp/package.json +2 -1
- package/examples/demoClientApp/src/DemoClientApp.js +9 -1
- package/jest.config.js +2 -1
- package/package.json +13 -10
- package/rollup.config.js +57 -0
- package/src/ClientAuthentication.spec.ts +69 -1
- package/src/ClientAuthentication.ts +32 -14
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +2 -9
- package/src/login/oidc/redirectHandler/__mocks__/RedirectHandler.ts +13 -0
- package/src/index.browser.spec.ts +0 -27
- package/src/index.browser.ts +0 -24
- package/webpack.browser.js +0 -19
- package/webpack.common.js +0 -22
- package/webpack.config.js +0 -8
- package/webpack.dev.js +0 -17
- package/webpack.prod.js +0 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IStorage } from "@inrupt/solid-client-authn-core";
|
|
2
|
-
export default class BrowserStorage implements IStorage {
|
|
3
|
-
get storage(): typeof window.localStorage;
|
|
4
|
-
get(key: string): Promise<string | undefined>;
|
|
5
|
-
set(key: string, value: string): Promise<void>;
|
|
6
|
-
delete(key: string): Promise<void>;
|
|
7
|
-
}
|
|
1
|
+
import { IStorage } from "@inrupt/solid-client-authn-core";
|
|
2
|
+
export default class BrowserStorage implements IStorage {
|
|
3
|
+
get storage(): typeof window.localStorage;
|
|
4
|
+
get(key: string): Promise<string | undefined>;
|
|
5
|
+
set(key: string, value: string): Promise<void>;
|
|
6
|
+
delete(key: string): Promise<void>;
|
|
7
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IStorage, StorageUtility } from "@inrupt/solid-client-authn-core";
|
|
2
|
-
export default class StorageUtilityBrowser extends StorageUtility {
|
|
3
|
-
constructor(secureStorage: IStorage, insecureStorage: IStorage);
|
|
4
|
-
}
|
|
1
|
+
import { IStorage, StorageUtility } from "@inrupt/solid-client-authn-core";
|
|
2
|
+
export default class StorageUtilityBrowser extends StorageUtility {
|
|
3
|
+
constructor(secureStorage: IStorage, insecureStorage: IStorage);
|
|
4
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface IUuidGenerator {
|
|
2
|
-
v4(): string;
|
|
3
|
-
}
|
|
4
|
-
export default class UuidGenerator {
|
|
5
|
-
v4(): string;
|
|
6
|
-
}
|
|
1
|
+
export interface IUuidGenerator {
|
|
2
|
+
v4(): string;
|
|
3
|
+
}
|
|
4
|
+
export default class UuidGenerator {
|
|
5
|
+
v4(): string;
|
|
6
|
+
}
|
package/dist/util/urlPath.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function appendToUrlPathname(url: string, append: string): string;
|
|
1
|
+
export declare function appendToUrlPathname(url: string, append: string): string;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
+
"@inrupt/solid-client-authn-browser": "file:../..",
|
|
12
13
|
"react": "^17.0.2",
|
|
13
14
|
"react-dom": "^17.0.2",
|
|
14
15
|
"regenerator-runtime": "^0.13.9"
|
|
@@ -26,6 +27,39 @@
|
|
|
26
27
|
"webpack-dev-server": "^4.7.3"
|
|
27
28
|
}
|
|
28
29
|
},
|
|
30
|
+
"../..": {
|
|
31
|
+
"name": "@inrupt/solid-client-authn-browser",
|
|
32
|
+
"version": "1.11.7",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@inrupt/oidc-client-ext": "^1.11.7",
|
|
36
|
+
"@inrupt/solid-client-authn-core": "^1.11.7",
|
|
37
|
+
"@types/lodash.clonedeep": "^4.5.6",
|
|
38
|
+
"@types/node": "^17.0.2",
|
|
39
|
+
"@types/uuid": "^8.3.0",
|
|
40
|
+
"events": "^3.3.0",
|
|
41
|
+
"jose": "^4.3.7",
|
|
42
|
+
"lodash.clonedeep": "^4.5.0",
|
|
43
|
+
"uuid": "^8.3.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@rollup/plugin-node-resolve": "^13.2.1",
|
|
47
|
+
"@types/jest": "^27.0.3",
|
|
48
|
+
"cross-fetch": "^3.0.6",
|
|
49
|
+
"eslint": "^7.16.0",
|
|
50
|
+
"jest": "^27.5.1",
|
|
51
|
+
"license-checker": "^25.0.1",
|
|
52
|
+
"rollup": "^2.38.4",
|
|
53
|
+
"rollup-plugin-polyfill-node": "^0.9.0",
|
|
54
|
+
"rollup-plugin-typescript2": "^0.31.1",
|
|
55
|
+
"ts-jest": "^27.0.7",
|
|
56
|
+
"ts-loader": "^9.1.1",
|
|
57
|
+
"tsc-watch": "^5.0.2",
|
|
58
|
+
"typedoc": "^0.22.4",
|
|
59
|
+
"typedoc-plugin-markdown": "^3.10.2",
|
|
60
|
+
"typescript": "^4.0.5"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
29
63
|
"node_modules/@babel/code-frame": {
|
|
30
64
|
"version": "7.16.7",
|
|
31
65
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
|
|
@@ -1691,6 +1725,10 @@
|
|
|
1691
1725
|
"node": ">=10.0.0"
|
|
1692
1726
|
}
|
|
1693
1727
|
},
|
|
1728
|
+
"node_modules/@inrupt/solid-client-authn-browser": {
|
|
1729
|
+
"resolved": "../..",
|
|
1730
|
+
"link": true
|
|
1731
|
+
},
|
|
1694
1732
|
"node_modules/@nodelib/fs.scandir": {
|
|
1695
1733
|
"version": "2.1.5",
|
|
1696
1734
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
|
@@ -7797,6 +7835,35 @@
|
|
|
7797
7835
|
"integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==",
|
|
7798
7836
|
"dev": true
|
|
7799
7837
|
},
|
|
7838
|
+
"@inrupt/solid-client-authn-browser": {
|
|
7839
|
+
"version": "file:../..",
|
|
7840
|
+
"requires": {
|
|
7841
|
+
"@inrupt/oidc-client-ext": "^1.11.7",
|
|
7842
|
+
"@inrupt/solid-client-authn-core": "^1.11.7",
|
|
7843
|
+
"@rollup/plugin-node-resolve": "^13.2.1",
|
|
7844
|
+
"@types/jest": "^27.0.3",
|
|
7845
|
+
"@types/lodash.clonedeep": "^4.5.6",
|
|
7846
|
+
"@types/node": "^17.0.2",
|
|
7847
|
+
"@types/uuid": "^8.3.0",
|
|
7848
|
+
"cross-fetch": "^3.0.6",
|
|
7849
|
+
"eslint": "^7.16.0",
|
|
7850
|
+
"events": "^3.3.0",
|
|
7851
|
+
"jest": "^27.5.1",
|
|
7852
|
+
"jose": "^4.3.7",
|
|
7853
|
+
"license-checker": "^25.0.1",
|
|
7854
|
+
"lodash.clonedeep": "^4.5.0",
|
|
7855
|
+
"rollup": "^2.38.4",
|
|
7856
|
+
"rollup-plugin-polyfill-node": "^0.9.0",
|
|
7857
|
+
"rollup-plugin-typescript2": "^0.31.1",
|
|
7858
|
+
"ts-jest": "^27.0.7",
|
|
7859
|
+
"ts-loader": "^9.1.1",
|
|
7860
|
+
"tsc-watch": "^5.0.2",
|
|
7861
|
+
"typedoc": "^0.22.4",
|
|
7862
|
+
"typedoc-plugin-markdown": "^3.10.2",
|
|
7863
|
+
"typescript": "^4.0.5",
|
|
7864
|
+
"uuid": "^8.3.1"
|
|
7865
|
+
}
|
|
7866
|
+
},
|
|
7800
7867
|
"@nodelib/fs.scandir": {
|
|
7801
7868
|
"version": "2.1.5",
|
|
7802
7869
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
|
@@ -8,7 +8,7 @@ import "regenerator-runtime/runtime";
|
|
|
8
8
|
import {
|
|
9
9
|
Session,
|
|
10
10
|
getClientAuthenticationWithDependencies,
|
|
11
|
-
} from "
|
|
11
|
+
} from "@inrupt/solid-client-authn-browser";
|
|
12
12
|
|
|
13
13
|
const clientApplicationName = "S-C-A Browser Demo Client App";
|
|
14
14
|
let snackBarTimeout = undefined;
|
|
@@ -298,6 +298,14 @@ class DemoClientApp extends Component {
|
|
|
298
298
|
|
|
299
299
|
this.setState({ fetchLoading: true });
|
|
300
300
|
|
|
301
|
+
if (this.state.fetchRoute.startsWith("/")) {
|
|
302
|
+
this.setState({
|
|
303
|
+
fetchBody: "Error: please specify a full URL",
|
|
304
|
+
fetchLoading: false,
|
|
305
|
+
});
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
|
|
301
309
|
try {
|
|
302
310
|
const session = getSession();
|
|
303
311
|
const response = await (
|
package/jest.config.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
...require("../../jest.config"),
|
|
3
3
|
// Allows running tests from packages/browser/
|
|
4
|
-
testEnvironment: "<rootDir>/../../tests/environment/customEnvironment.js",
|
|
4
|
+
// testEnvironment: "<rootDir>/../../tests/environment/customEnvironment.js",
|
|
5
|
+
testEnvironment: "<rootDir>/../../tests/environment/browserEnvironment.js",
|
|
5
6
|
|
|
6
7
|
// Enable injectGlobals here to support jest-mock-console
|
|
7
8
|
// https://github.com/bpedersen/jest-mock-console/issues/32
|
package/package.json
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inrupt/solid-client-authn-browser",
|
|
3
|
-
"version": "1.11.8-alpha.
|
|
3
|
+
"version": "1.11.8-alpha.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"types": "dist/index",
|
|
6
6
|
"browser": "dist/solid-client-authn.bundle.js",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.es.js",
|
|
8
9
|
"bundle": "dist/solid-client-authn.bundle.js",
|
|
9
10
|
"repository": {
|
|
10
11
|
"url": "https://github.com/inrupt/solid-client-authn"
|
|
11
12
|
},
|
|
12
13
|
"scripts": {
|
|
13
14
|
"prepublishOnly": "npm run build",
|
|
14
|
-
"clean": "
|
|
15
|
-
"
|
|
16
|
-
"clean-browser": "rimraf ./browserDist",
|
|
17
|
-
"build": "npm run build-module && npm run build-browser",
|
|
18
|
-
"build-module": "npm run clean-module && tsc -p tsconfig.json",
|
|
19
|
-
"build-browser": "npm run clean-browser && webpack --config webpack.browser.js",
|
|
15
|
+
"clean": "rimraf ./dist",
|
|
16
|
+
"build": "rollup --config rollup.config.js",
|
|
20
17
|
"lint:fix": "npm run lint:eslint -- --fix && npm run lint:prettier -- --write",
|
|
21
18
|
"lint:check": "npm run lint:eslint && npm run lint:prettier -- --check",
|
|
22
19
|
"lint:eslint": "eslint --config .eslintrc.js \"src/\"",
|
|
@@ -28,8 +25,8 @@
|
|
|
28
25
|
"build-docs-preview-site": "npm run build-api-docs; cd docs/api; make html"
|
|
29
26
|
},
|
|
30
27
|
"dependencies": {
|
|
31
|
-
"@inrupt/oidc-client-ext": "^1.11.8-alpha.
|
|
32
|
-
"@inrupt/solid-client-authn-core": "^1.11.8-alpha.
|
|
28
|
+
"@inrupt/oidc-client-ext": "^1.11.8-alpha.2",
|
|
29
|
+
"@inrupt/solid-client-authn-core": "^1.11.8-alpha.2",
|
|
33
30
|
"@types/lodash.clonedeep": "^4.5.6",
|
|
34
31
|
"@types/node": "^17.0.2",
|
|
35
32
|
"@types/uuid": "^8.3.0",
|
|
@@ -41,5 +38,11 @@
|
|
|
41
38
|
"publishConfig": {
|
|
42
39
|
"access": "public"
|
|
43
40
|
},
|
|
44
|
-
"
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@rollup/plugin-node-resolve": "^13.2.1",
|
|
43
|
+
"jest-location-mock": "^1.0.9",
|
|
44
|
+
"rollup-plugin-polyfill-node": "^0.9.0",
|
|
45
|
+
"rollup-plugin-sourcemaps": "^0.6.3"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "189b55888fa242a04f54da33dca36f0aca3b7969"
|
|
45
48
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import pkg from "./package.json";
|
|
2
|
+
import typescript from "rollup-plugin-typescript2";
|
|
3
|
+
import nodeResolve from "@rollup/plugin-node-resolve";
|
|
4
|
+
import nodePolyfills from "rollup-plugin-polyfill-node";
|
|
5
|
+
import sourcemaps from "rollup-plugin-sourcemaps";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
input: "./src/index.ts",
|
|
9
|
+
output: [
|
|
10
|
+
{
|
|
11
|
+
file: pkg.main,
|
|
12
|
+
format: "cjs",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
file: pkg.module,
|
|
16
|
+
format: "esm",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
file: pkg.bundle,
|
|
20
|
+
format: "umd",
|
|
21
|
+
name: "solidClientAuthentication",
|
|
22
|
+
globals: {
|
|
23
|
+
// FIXME: inline oidc-client:
|
|
24
|
+
"@inrupt/oidc-client": "oidcClient",
|
|
25
|
+
"@inrupt/solid-client-authn-core": "solidClientAuthnCore",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
plugins: [
|
|
30
|
+
nodePolyfills({
|
|
31
|
+
include: ["events"],
|
|
32
|
+
}),
|
|
33
|
+
sourcemaps(),
|
|
34
|
+
nodeResolve({
|
|
35
|
+
browser: true,
|
|
36
|
+
preferBuiltins: true,
|
|
37
|
+
resolveOnly: [
|
|
38
|
+
"uuid",
|
|
39
|
+
"@inrupt/solid-client-authn-core",
|
|
40
|
+
"@inrupt/oidc-client-ext",
|
|
41
|
+
],
|
|
42
|
+
}),
|
|
43
|
+
typescript({
|
|
44
|
+
// Use our own version of TypeScript, rather than the one bundled with the plugin:
|
|
45
|
+
typescript: require("typescript"),
|
|
46
|
+
tsconfigOverride: {
|
|
47
|
+
compilerOptions: {
|
|
48
|
+
module: "esnext",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
],
|
|
53
|
+
external: ["@inrupt/solid-client", "@inrupt/solid-client-authn-core"],
|
|
54
|
+
// external: ['crypto'],
|
|
55
|
+
// The following option is useful because symlinks are used in monorepos
|
|
56
|
+
preserveSymlinks: true,
|
|
57
|
+
};
|
|
@@ -19,17 +19,19 @@
|
|
|
19
19
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { jest, it, describe, expect } from "@jest/globals";
|
|
22
|
+
import { jest, it, describe, expect, beforeEach } from "@jest/globals";
|
|
23
23
|
import {
|
|
24
24
|
mockStorageUtility,
|
|
25
25
|
StorageUtility,
|
|
26
26
|
USER_SESSION_PREFIX,
|
|
27
27
|
mockStorage,
|
|
28
|
+
EVENTS,
|
|
28
29
|
} from "@inrupt/solid-client-authn-core";
|
|
29
30
|
import * as SolidClientAuthnCore from "@inrupt/solid-client-authn-core";
|
|
30
31
|
import { EventEmitter } from "events";
|
|
31
32
|
import { LoginHandlerMock } from "./login/__mocks__/LoginHandler";
|
|
32
33
|
import {
|
|
34
|
+
RedirectFailureHandlerMock,
|
|
33
35
|
RedirectHandlerMock,
|
|
34
36
|
RedirectHandlerResponse,
|
|
35
37
|
} from "./login/oidc/redirectHandler/__mocks__/RedirectHandler";
|
|
@@ -97,8 +99,43 @@ describe("ClientAuthentication", () => {
|
|
|
97
99
|
);
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
jest.clearAllMocks();
|
|
104
|
+
Object.defineProperty(window, "location", {
|
|
105
|
+
writable: true,
|
|
106
|
+
value: { assign: jest.fn() },
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
100
110
|
describe("login", () => {
|
|
101
111
|
const mockEmitter = new EventEmitter();
|
|
112
|
+
// TODO: add tests for events & errors
|
|
113
|
+
|
|
114
|
+
it("calls login, and uses the window.location.href for the redirect if no redirectUrl is set", async () => {
|
|
115
|
+
// Set a current window location which will be the expected URL to be
|
|
116
|
+
// redirected back to, since we don't pass redirectUrl:
|
|
117
|
+
window.location.href = "https://coolapp.test/some/redirect";
|
|
118
|
+
|
|
119
|
+
const clientAuthn = getClientAuthentication();
|
|
120
|
+
await clientAuthn.login(
|
|
121
|
+
{
|
|
122
|
+
sessionId: "mySession",
|
|
123
|
+
tokenType: "DPoP",
|
|
124
|
+
clientId: "coolApp",
|
|
125
|
+
oidcIssuer: "https://idp.com",
|
|
126
|
+
},
|
|
127
|
+
mockEmitter
|
|
128
|
+
);
|
|
129
|
+
expect(defaultMocks.loginHandler.handle).toHaveBeenCalledWith({
|
|
130
|
+
sessionId: "mySession",
|
|
131
|
+
clientId: "coolApp",
|
|
132
|
+
redirectUrl: "https://coolapp.test/some/redirect",
|
|
133
|
+
oidcIssuer: "https://idp.com",
|
|
134
|
+
clientName: "coolApp",
|
|
135
|
+
eventEmitter: mockEmitter,
|
|
136
|
+
tokenType: "DPoP",
|
|
137
|
+
});
|
|
138
|
+
});
|
|
102
139
|
|
|
103
140
|
it("calls login, and defaults to a DPoP token", async () => {
|
|
104
141
|
const clientAuthn = getClientAuthentication();
|
|
@@ -200,6 +237,7 @@ describe("ClientAuthentication", () => {
|
|
|
200
237
|
|
|
201
238
|
describe("logout", () => {
|
|
202
239
|
const mockEmitter = new EventEmitter();
|
|
240
|
+
// TODO: add tests for events & errors
|
|
203
241
|
|
|
204
242
|
it("reverts back to un-authenticated fetch on logout", async () => {
|
|
205
243
|
window.fetch = jest.fn();
|
|
@@ -267,6 +305,7 @@ describe("ClientAuthentication", () => {
|
|
|
267
305
|
|
|
268
306
|
describe("handleIncomingRedirect", () => {
|
|
269
307
|
const mockEmitter = new EventEmitter();
|
|
308
|
+
mockEmitter.emit = jest.fn();
|
|
270
309
|
|
|
271
310
|
it("calls handle redirect", async () => {
|
|
272
311
|
// eslint-disable-next-line no-restricted-globals
|
|
@@ -302,6 +341,7 @@ describe("ClientAuthentication", () => {
|
|
|
302
341
|
|
|
303
342
|
// Calling the redirect handler should have updated the fetch.
|
|
304
343
|
expect(clientAuthn.fetch).not.toBe(unauthFetch);
|
|
344
|
+
expect(mockEmitter.emit).not.toHaveBeenCalled();
|
|
305
345
|
});
|
|
306
346
|
|
|
307
347
|
it("clears the current IRI from OAuth query parameters in the auth code flow", async () => {
|
|
@@ -317,6 +357,32 @@ describe("ClientAuthentication", () => {
|
|
|
317
357
|
"",
|
|
318
358
|
"https://coolapp.com/redirect"
|
|
319
359
|
);
|
|
360
|
+
expect(mockEmitter.emit).not.toHaveBeenCalled();
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("clears the current IRI from OAuth query parameters even if auth flow fails", async () => {
|
|
364
|
+
// eslint-disable-next-line no-restricted-globals
|
|
365
|
+
history.replaceState = jest.fn();
|
|
366
|
+
const clientAuthn = getClientAuthentication({
|
|
367
|
+
...defaultMocks,
|
|
368
|
+
redirectHandler: RedirectFailureHandlerMock,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const url =
|
|
372
|
+
"https://coolapp.com/redirect?state=someState&code=someAuthCode";
|
|
373
|
+
await clientAuthn.handleIncomingRedirect(url, mockEmitter);
|
|
374
|
+
// eslint-disable-next-line no-restricted-globals
|
|
375
|
+
expect(history.replaceState).toHaveBeenCalledWith(
|
|
376
|
+
null,
|
|
377
|
+
"",
|
|
378
|
+
"https://coolapp.com/redirect"
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
expect(mockEmitter.emit).toHaveBeenCalledWith(
|
|
382
|
+
EVENTS.ERROR,
|
|
383
|
+
"redirect",
|
|
384
|
+
new Error("Something went wrong")
|
|
385
|
+
);
|
|
320
386
|
});
|
|
321
387
|
|
|
322
388
|
it("clears the current IRI from OAuth query parameters in the implicit flow", async () => {
|
|
@@ -332,6 +398,7 @@ describe("ClientAuthentication", () => {
|
|
|
332
398
|
"",
|
|
333
399
|
"https://coolapp.com/redirect"
|
|
334
400
|
);
|
|
401
|
+
expect(mockEmitter.emit).not.toHaveBeenCalled();
|
|
335
402
|
});
|
|
336
403
|
|
|
337
404
|
it("preserves non-OAuth query strings", async () => {
|
|
@@ -347,6 +414,7 @@ describe("ClientAuthentication", () => {
|
|
|
347
414
|
"",
|
|
348
415
|
"https://coolapp.com/redirect?someQuery=someValue"
|
|
349
416
|
);
|
|
417
|
+
expect(mockEmitter.emit).not.toHaveBeenCalled();
|
|
350
418
|
});
|
|
351
419
|
});
|
|
352
420
|
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
IIssuerConfigFetcher,
|
|
34
34
|
ISessionInternalInfo,
|
|
35
35
|
ILoginOptions,
|
|
36
|
+
EVENTS,
|
|
36
37
|
} from "@inrupt/solid-client-authn-core";
|
|
37
38
|
import { removeOidcQueryParam } from "@inrupt/oidc-client-ext";
|
|
38
39
|
import { EventEmitter } from "events";
|
|
@@ -129,13 +130,37 @@ export default class ClientAuthentication {
|
|
|
129
130
|
url: string,
|
|
130
131
|
eventEmitter: EventEmitter
|
|
131
132
|
): Promise<ISessionInfo | undefined> => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
try {
|
|
134
|
+
const redirectInfo = await this.redirectHandler.handle(url, eventEmitter);
|
|
135
|
+
// The `FallbackRedirectHandler` directly returns the global `fetch` for
|
|
136
|
+
// his value, so we should ensure it's bound to `window` rather than to
|
|
137
|
+
// ClientAuthentication, to avoid the following error:
|
|
138
|
+
// > 'fetch' called on an object that does not implement interface Window.
|
|
139
|
+
this.fetch = redirectInfo.fetch.bind(window);
|
|
140
|
+
|
|
141
|
+
// Strip the oauth params:
|
|
142
|
+
this.cleanUrlAfterRedirect(url);
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
isLoggedIn: redirectInfo.isLoggedIn,
|
|
146
|
+
webId: redirectInfo.webId,
|
|
147
|
+
sessionId: redirectInfo.sessionId,
|
|
148
|
+
expirationDate: redirectInfo.expirationDate,
|
|
149
|
+
};
|
|
150
|
+
} catch (err) {
|
|
151
|
+
// Strip the oauth params:
|
|
152
|
+
this.cleanUrlAfterRedirect(url);
|
|
153
|
+
|
|
154
|
+
// FIXME: EVENTS.ERROR should be errorCode, errorDescription
|
|
155
|
+
//
|
|
156
|
+
// I'm not sure if "redirect" is a good error code, and in theory `err`
|
|
157
|
+
// maybe an Error object and not a string; Maybe we want to just hardcode
|
|
158
|
+
// a description instead?
|
|
159
|
+
eventEmitter.emit(EVENTS.ERROR, "redirect", err);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
138
162
|
|
|
163
|
+
private cleanUrlAfterRedirect(url: string): void {
|
|
139
164
|
const cleanedUpUrl = new URL(url);
|
|
140
165
|
cleanedUpUrl.searchParams.delete("state");
|
|
141
166
|
// For auth code flow
|
|
@@ -153,12 +178,5 @@ export default class ClientAuthentication {
|
|
|
153
178
|
// authentication library will be called again with what are now invalid
|
|
154
179
|
// query parameters!).
|
|
155
180
|
window.history.replaceState(null, "", cleanedUpUrl.toString());
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
isLoggedIn: redirectInfo.isLoggedIn,
|
|
159
|
-
webId: redirectInfo.webId,
|
|
160
|
-
sessionId: redirectInfo.sessionId,
|
|
161
|
-
expirationDate: redirectInfo.expirationDate,
|
|
162
|
-
};
|
|
163
|
-
};
|
|
181
|
+
}
|
|
164
182
|
}
|
|
@@ -19,15 +19,8 @@
|
|
|
19
19
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
it,
|
|
25
|
-
describe,
|
|
26
|
-
expect,
|
|
27
|
-
beforeEach,
|
|
28
|
-
afterEach,
|
|
29
|
-
} from "@jest/globals";
|
|
30
|
-
import mockConsole, { RestoreConsole } from "jest-mock-console";
|
|
22
|
+
import { jest, it, describe, expect, afterEach } from "@jest/globals";
|
|
23
|
+
import mockConsole from "jest-mock-console";
|
|
31
24
|
|
|
32
25
|
/**
|
|
33
26
|
* Test for AuthorizationCodeWithPkceOidcHandler
|
|
@@ -45,3 +45,16 @@ export const RedirectHandlerMock: jest.Mocked<IRedirectHandler> = {
|
|
|
45
45
|
),
|
|
46
46
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
47
|
} as any;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @hidden
|
|
51
|
+
*/
|
|
52
|
+
export const RedirectFailureHandlerMock: jest.Mocked<IRedirectHandler> = {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
|
+
canHandle: jest.fn((url: string) => Promise.resolve(true)),
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
56
|
+
handle: jest.fn((url: string) =>
|
|
57
|
+
Promise.reject(new Error("Something went wrong"))
|
|
58
|
+
),
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
} as any;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 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
|
-
import { it, expect } from "@jest/globals";
|
|
23
|
-
import * as solidClientAuthentication from "./index.browser";
|
|
24
|
-
|
|
25
|
-
it("exports the public API from the entrypoint", () => {
|
|
26
|
-
expect(solidClientAuthentication).toBeDefined();
|
|
27
|
-
});
|
package/src/index.browser.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 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
|
-
import * as solidClientAuthentication from "./index";
|
|
23
|
-
|
|
24
|
-
module.exports = solidClientAuthentication;
|
package/webpack.browser.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const { merge } = require("webpack-merge");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const commonConfig = require("./webpack.common.js");
|
|
5
|
-
|
|
6
|
-
module.exports = () => {
|
|
7
|
-
const envConfig = require(`./webpack.prod.js`);
|
|
8
|
-
|
|
9
|
-
const browserConfig = {
|
|
10
|
-
output: {
|
|
11
|
-
libraryTarget: "var",
|
|
12
|
-
library: "solidClientAuthentication",
|
|
13
|
-
filename: "solid-client-authn.bundle.js",
|
|
14
|
-
path: path.resolve(__dirname, "dist"),
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return merge(commonConfig, envConfig, browserConfig);
|
|
19
|
-
};
|
package/webpack.common.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
entry: "./src/index.browser.ts",
|
|
3
|
-
module: {
|
|
4
|
-
rules: [
|
|
5
|
-
{
|
|
6
|
-
test: /\.tsx?$/,
|
|
7
|
-
use: [
|
|
8
|
-
{
|
|
9
|
-
loader: "ts-loader",
|
|
10
|
-
options: {
|
|
11
|
-
configFile: "tsconfig.json",
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
exclude: /node_modules/,
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
resolve: {
|
|
20
|
-
extensions: [".tsx", ".ts", ".js"],
|
|
21
|
-
},
|
|
22
|
-
};
|
package/webpack.config.js
DELETED
package/webpack.dev.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const path = require("path");
|
|
2
|
-
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
mode: "development",
|
|
6
|
-
devtool: "inline-source-map",
|
|
7
|
-
devServer: {
|
|
8
|
-
contentBase: path.join(__dirname, "browserDist"),
|
|
9
|
-
port: 9000,
|
|
10
|
-
},
|
|
11
|
-
plugins: [
|
|
12
|
-
new HtmlWebpackPlugin({
|
|
13
|
-
title: "Solid Authenticator Test Page",
|
|
14
|
-
template: "./src/index.html",
|
|
15
|
-
}),
|
|
16
|
-
],
|
|
17
|
-
};
|
package/webpack.prod.js
DELETED