diff --git a/adapters/oidc/js/.gitignore b/adapters/oidc/js/.gitignore new file mode 100644 index 0000000000..6b7940261b --- /dev/null +++ b/adapters/oidc/js/.gitignore @@ -0,0 +1,2 @@ +node +node_modules diff --git a/adapters/oidc/js/package-lock.json b/adapters/oidc/js/package-lock.json new file mode 100644 index 0000000000..e0ac963a3e --- /dev/null +++ b/adapters/oidc/js/package-lock.json @@ -0,0 +1,1237 @@ +{ + "name": "keycloak-js-adapter", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "keycloak-js-adapter", + "dependencies": { + "base64-js": "^1.5.1", + "es6-promise": "^4.2.8", + "js-sha256": "^0.9.0" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^21.0.1", + "@rollup/plugin-inject": "^4.0.3", + "@rollup/plugin-node-resolve": "^13.1.1", + "@rollup/plugin-typescript": "^8.3.0", + "@types/node": "^17.0.5", + "rollup": "^2.62.0", + "rollup-plugin-terser": "^7.0.2", + "typescript": "^4.5.4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.15.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz", + "integrity": "sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "commondir": "^1.0.1", + "estree-walker": "^2.0.1", + "glob": "^7.1.6", + "is-reference": "^1.2.1", + "magic-string": "^0.25.7", + "resolve": "^1.17.0" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^2.38.3" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/plugin-inject": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-4.0.3.tgz", + "integrity": "sha512-lzMXmj0LZjd67MI+M8H9dk/oCxR0TYqYAdZ6ZOejWQLSUtud+FUPu4NCMAO8KyWWAalFo8ean7yFHCMvCNsCZw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "estree-walker": "^2.0.1", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-inject/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", + "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^2.42.0" + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz", + "integrity": "sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "resolve": "^1.17.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0", + "tslib": "*", + "typescript": ">=3.7.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.5.tgz", + "integrity": "sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.62.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.62.0.tgz", + "integrity": "sha512-cJEQq2gwB0GWMD3rYImefQTSjrPYaC6s4J9pYqnstVLJ1CHa/aZNVkD4Epuvg4iLeMA4KRiq7UM7awKK6j7jcw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "acorn": "^8.5.0" + }, + "peerDependenciesMeta": { + "acorn": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true, + "peer": true + }, + "node_modules/typescript": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.15.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@rollup/plugin-commonjs": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz", + "integrity": "sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "commondir": "^1.0.1", + "estree-walker": "^2.0.1", + "glob": "^7.1.6", + "is-reference": "^1.2.1", + "magic-string": "^0.25.7", + "resolve": "^1.17.0" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@rollup/plugin-inject": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-4.0.3.tgz", + "integrity": "sha512-lzMXmj0LZjd67MI+M8H9dk/oCxR0TYqYAdZ6ZOejWQLSUtud+FUPu4NCMAO8KyWWAalFo8ean7yFHCMvCNsCZw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "estree-walker": "^2.0.1", + "magic-string": "^0.25.7" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@rollup/plugin-node-resolve": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", + "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/plugin-typescript": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz", + "integrity": "sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "resolve": "^1.17.0" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.5.tgz", + "integrity": "sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==", + "dev": true + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "2.62.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.62.0.tgz", + "integrity": "sha512-cJEQq2gwB0GWMD3rYImefQTSjrPYaC6s4J9pYqnstVLJ1CHa/aZNVkD4Epuvg4iLeMA4KRiq7UM7awKK6j7jcw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true, + "peer": true + }, + "typescript": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/adapters/oidc/js/package.json b/adapters/oidc/js/package.json new file mode 100644 index 0000000000..b58febff3a --- /dev/null +++ b/adapters/oidc/js/package.json @@ -0,0 +1,22 @@ +{ + "name": "keycloak-js-adapter", + "private": true, + "scripts": { + "build": "rollup --config --configPlugin typescript" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^21.0.1", + "@rollup/plugin-inject": "^4.0.3", + "@rollup/plugin-node-resolve": "^13.1.1", + "@rollup/plugin-typescript": "^8.3.0", + "@types/node": "^17.0.5", + "rollup": "^2.62.0", + "rollup-plugin-terser": "^7.0.2", + "typescript": "^4.5.4" + }, + "dependencies": { + "base64-js": "^1.5.1", + "es6-promise": "^4.2.8", + "js-sha256": "^0.9.0" + } +} diff --git a/adapters/oidc/js/pom.xml b/adapters/oidc/js/pom.xml index 6e360df4e7..c9cd3245cb 100755 --- a/adapters/oidc/js/pom.xml +++ b/adapters/oidc/js/pom.xml @@ -16,75 +16,50 @@ ~ limitations under the License. --> - + keycloak-parent org.keycloak 17.0.0-SNAPSHOT - ../../../pom.xml + ../../../pom.xml 4.0.0 keycloak-js-adapter Keycloak JS Integration - - - - - - - com.samaxes.maven - minify-maven-plugin - - CLOSURE - ECMASCRIPT5 - true - - - - min-js - compile - - utf-8 - ${basedir}/src/main/resources - . - - keycloak.js - - - ${project.build.directory}/classes - . - keycloak.js - - - minify - - - - min-authz-js - compile - - utf-8 - ${basedir}/src/main/resources - . - - keycloak-authz.js - - - ${project.build.directory}/classes - . - keycloak-authz.js - - - minify - - - - + + + com.github.eirslett + frontend-maven-plugin + + + install node and npm + + install-node-and-npm + + + + npm install + + npm + + + + npm run build + + npm + + + run build + + + + + ${node.version} + + - diff --git a/adapters/oidc/js/rollup.config.ts b/adapters/oidc/js/rollup.config.ts new file mode 100644 index 0000000000..6734c89a09 --- /dev/null +++ b/adapters/oidc/js/rollup.config.ts @@ -0,0 +1,81 @@ +import commonjs from "@rollup/plugin-commonjs"; +import inject from "@rollup/plugin-inject"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import path from "node:path"; +import type { OutputOptions, RollupOptions } from "rollup"; +import { defineConfig } from "rollup"; +import { terser } from "rollup-plugin-terser"; + +interface DefineOptionsArgs { + file: string; + name: string; + amdId: string; +} + +function defineOptions({ + file, + name, + amdId, +}: DefineOptionsArgs): RollupOptions[] { + const sourceDir = "src/main/js"; + const targetDir = "target/classes"; + const commonOptions: RollupOptions = { + input: path.join(sourceDir, `${file}.js`), + plugins: [commonjs(), nodeResolve()], + }; + + const umdOutput: OutputOptions = { + format: "umd", + name, + amd: { id: amdId }, + }; + + return [ + // Modern ES module variant, with externalized dependencies. + { + ...commonOptions, + output: [ + { + file: path.join(targetDir, `${file}.mjs`), + }, + ], + external: ["base64-js", "js-sha256"], + }, + // Legacy Universal Module Definition, or “UMD”, with inlined dependencies. + { + ...commonOptions, + output: [ + { + ...umdOutput, + file: path.join(targetDir, `${file}.js`), + }, + { + ...umdOutput, + file: path.join(targetDir, `${file}.min.js`), + sourcemap: true, + sourcemapExcludeSources: true, + plugins: [terser()], + }, + ], + plugins: [ + ...commonOptions.plugins, + inject({ + Promise: ["es6-promise/dist/es6-promise.min.js", "Promise"], + }), + ], + }, + ]; +} + +export default defineConfig([ + ...defineOptions({ + file: "keycloak", + name: "Keycloak", + amdId: "keycloak", + }), + ...defineOptions({ + file: "keycloak-authz", + name: "KeycloakAuthorization", + amdId: "keycloak-authorization", + }), +]); diff --git a/adapters/oidc/js/src/main/js/keycloak-authz.js b/adapters/oidc/js/src/main/js/keycloak-authz.js new file mode 100644 index 0000000000..9d83e4bc12 --- /dev/null +++ b/adapters/oidc/js/src/main/js/keycloak-authz.js @@ -0,0 +1,221 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +var KeycloakAuthorization = function (keycloak, options) { + var _instance = this; + this.rpt = null; + + var resolve = function () {}; + var reject = function () {}; + + // detects if browser supports promises + if (typeof Promise !== "undefined" && Promise.toString().indexOf("[native code]") !== -1) { + this.ready = new Promise(function (res, rej) { + resolve = res; + reject = rej; + }); + } + + this.init = function () { + var request = new XMLHttpRequest(); + + request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/.well-known/uma2-configuration'); + request.onreadystatechange = function () { + if (request.readyState == 4) { + if (request.status == 200) { + _instance.config = JSON.parse(request.responseText); + resolve(); + } else { + console.error('Could not obtain configuration from server.'); + reject(); + } + } + } + + request.send(null); + }; + + /** + * This method enables client applications to better integrate with resource servers protected by a Keycloak + * policy enforcer using UMA protocol. + * + * The authorization request must be provided with a ticket. + */ + this.authorize = function (authorizationRequest) { + this.then = function (onGrant, onDeny, onError) { + if (authorizationRequest && authorizationRequest.ticket) { + var request = new XMLHttpRequest(); + + request.open('POST', _instance.config.token_endpoint, true); + request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); + + request.onreadystatechange = function () { + if (request.readyState == 4) { + var status = request.status; + + if (status >= 200 && status < 300) { + var rpt = JSON.parse(request.responseText).access_token; + _instance.rpt = rpt; + onGrant(rpt); + } else if (status == 403) { + if (onDeny) { + onDeny(); + } else { + console.error('Authorization request was denied by the server.'); + } + } else { + if (onError) { + onError(); + } else { + console.error('Could not obtain authorization data from server.'); + } + } + } + }; + + var params = "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&client_id=" + keycloak.clientId + "&ticket=" + authorizationRequest.ticket; + + if (authorizationRequest.submitRequest != undefined) { + params += "&submit_request=" + authorizationRequest.submitRequest; + } + + var metadata = authorizationRequest.metadata; + + if (metadata) { + if (metadata.responseIncludeResourceName) { + params += "&response_include_resource_name=" + metadata.responseIncludeResourceName; + } + if (metadata.responsePermissionsLimit) { + params += "&response_permissions_limit=" + metadata.responsePermissionsLimit; + } + } + + if (_instance.rpt && (authorizationRequest.incrementalAuthorization == undefined || authorizationRequest.incrementalAuthorization)) { + params += "&rpt=" + _instance.rpt; + } + + request.send(params); + } + }; + + return this; + }; + + /** + * Obtains all entitlements from a Keycloak Server based on a given resourceServerId. + */ + this.entitlement = function (resourceServerId, authorizationRequest) { + this.then = function (onGrant, onDeny, onError) { + var request = new XMLHttpRequest(); + + request.open('POST', _instance.config.token_endpoint, true); + request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); + + request.onreadystatechange = function () { + if (request.readyState == 4) { + var status = request.status; + + if (status >= 200 && status < 300) { + var rpt = JSON.parse(request.responseText).access_token; + _instance.rpt = rpt; + onGrant(rpt); + } else if (status == 403) { + if (onDeny) { + onDeny(); + } else { + console.error('Authorization request was denied by the server.'); + } + } else { + if (onError) { + onError(); + } else { + console.error('Could not obtain authorization data from server.'); + } + } + } + }; + + if (!authorizationRequest) { + authorizationRequest = {}; + } + + var params = "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&client_id=" + keycloak.clientId; + + if (authorizationRequest.claimToken) { + params += "&claim_token=" + authorizationRequest.claimToken; + + if (authorizationRequest.claimTokenFormat) { + params += "&claim_token_format=" + authorizationRequest.claimTokenFormat; + } + } + + params += "&audience=" + resourceServerId; + + var permissions = authorizationRequest.permissions; + + if (!permissions) { + permissions = []; + } + + for (var i = 0; i < permissions.length; i++) { + var resource = permissions[i]; + var permission = resource.id; + + if (resource.scopes && resource.scopes.length > 0) { + permission += "#"; + for (j = 0; j < resource.scopes.length; j++) { + var scope = resource.scopes[j]; + if (permission.indexOf('#') != permission.length - 1) { + permission += ","; + } + permission += scope; + } + } + + params += "&permission=" + permission; + } + + var metadata = authorizationRequest.metadata; + + if (metadata) { + if (metadata.responseIncludeResourceName) { + params += "&response_include_resource_name=" + metadata.responseIncludeResourceName; + } + if (metadata.responsePermissionsLimit) { + params += "&response_permissions_limit=" + metadata.responsePermissionsLimit; + } + } + + if (_instance.rpt) { + params += "&rpt=" + _instance.rpt; + } + + request.send(params); + }; + + return this; + }; + + this.init(this); + + return this; +}; + +export default KeycloakAuthorization; diff --git a/adapters/oidc/js/src/main/js/keycloak.js b/adapters/oidc/js/src/main/js/keycloak.js new file mode 100755 index 0000000000..db95534bec --- /dev/null +++ b/adapters/oidc/js/src/main/js/keycloak.js @@ -0,0 +1,1721 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import base64 from 'base64-js'; +import { sha256 } from 'js-sha256'; + +if (typeof Promise === 'undefined') { + throw Error('Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill.'); +} + +var loggedPromiseDeprecation = false; + +function logPromiseDeprecation() { + if (!loggedPromiseDeprecation) { + loggedPromiseDeprecation = true; + console.warn('[KEYCLOAK] Usage of legacy style promise methods such as `.error()` and `.success()` has been deprecated and support will be removed in future versions. Use standard style promise methods such as `.then() and `.catch()` instead.'); + } +} + +function Keycloak (config) { + if (!(this instanceof Keycloak)) { + return new Keycloak(config); + } + + var kc = this; + var adapter; + var refreshQueue = []; + var callbackStorage; + + var loginIframe = { + enable: true, + callbackList: [], + interval: 5 + }; + + var scripts = document.getElementsByTagName('script'); + for (var i = 0; i < scripts.length; i++) { + if ((scripts[i].src.indexOf('keycloak.js') !== -1 || scripts[i].src.indexOf('keycloak.min.js') !== -1) && scripts[i].src.indexOf('version=') !== -1) { + kc.iframeVersion = scripts[i].src.substring(scripts[i].src.indexOf('version=') + 8).split('&')[0]; + } + } + + var useNonce = true; + var logInfo = createLogger(console.info); + var logWarn = createLogger(console.warn); + + kc.init = function (initOptions) { + kc.authenticated = false; + + callbackStorage = createCallbackStorage(); + var adapters = ['default', 'cordova', 'cordova-native']; + + if (initOptions && adapters.indexOf(initOptions.adapter) > -1) { + adapter = loadAdapter(initOptions.adapter); + } else if (initOptions && typeof initOptions.adapter === "object") { + adapter = initOptions.adapter; + } else { + if (window.Cordova || window.cordova) { + adapter = loadAdapter('cordova'); + } else { + adapter = loadAdapter(); + } + } + + if (initOptions) { + if (typeof initOptions.useNonce !== 'undefined') { + useNonce = initOptions.useNonce; + } + + if (typeof initOptions.checkLoginIframe !== 'undefined') { + loginIframe.enable = initOptions.checkLoginIframe; + } + + if (initOptions.checkLoginIframeInterval) { + loginIframe.interval = initOptions.checkLoginIframeInterval; + } + + if (initOptions.onLoad === 'login-required') { + kc.loginRequired = true; + } + + if (initOptions.responseMode) { + if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') { + kc.responseMode = initOptions.responseMode; + } else { + throw 'Invalid value for responseMode'; + } + } + + if (initOptions.flow) { + switch (initOptions.flow) { + case 'standard': + kc.responseType = 'code'; + break; + case 'implicit': + kc.responseType = 'id_token token'; + break; + case 'hybrid': + kc.responseType = 'code id_token token'; + break; + default: + throw 'Invalid value for flow'; + } + kc.flow = initOptions.flow; + } + + if (initOptions.timeSkew != null) { + kc.timeSkew = initOptions.timeSkew; + } + + if(initOptions.redirectUri) { + kc.redirectUri = initOptions.redirectUri; + } + + if (initOptions.silentCheckSsoRedirectUri) { + kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri; + } + + if (typeof initOptions.silentCheckSsoFallback === 'boolean') { + kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback; + } else { + kc.silentCheckSsoFallback = true; + } + + if (initOptions.pkceMethod) { + if (initOptions.pkceMethod !== "S256") { + throw 'Invalid value for pkceMethod'; + } + kc.pkceMethod = initOptions.pkceMethod; + } + + if (typeof initOptions.enableLogging === 'boolean') { + kc.enableLogging = initOptions.enableLogging; + } else { + kc.enableLogging = false; + } + + if (typeof initOptions.scope === 'string') { + kc.scope = initOptions.scope; + } + + if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) { + kc.messageReceiveTimeout = initOptions.messageReceiveTimeout; + } else { + kc.messageReceiveTimeout = 10000; + } + } + + if (!kc.responseMode) { + kc.responseMode = 'fragment'; + } + if (!kc.responseType) { + kc.responseType = 'code'; + kc.flow = 'standard'; + } + + var promise = createPromise(); + + var initPromise = createPromise(); + initPromise.promise.then(function() { + kc.onReady && kc.onReady(kc.authenticated); + promise.setSuccess(kc.authenticated); + }).catch(function(error) { + promise.setError(error); + }); + + var configPromise = loadConfig(config); + + function onLoad() { + var doLogin = function(prompt) { + if (!prompt) { + options.prompt = 'none'; + } + + kc.login(options).then(function () { + initPromise.setSuccess(); + }).catch(function (error) { + initPromise.setError(error); + }); + } + + var checkSsoSilently = function() { + var ifrm = document.createElement("iframe"); + var src = kc.createLoginUrl({prompt: 'none', redirectUri: kc.silentCheckSsoRedirectUri}); + ifrm.setAttribute("src", src); + ifrm.setAttribute("title", "keycloak-silent-check-sso"); + ifrm.style.display = "none"; + document.body.appendChild(ifrm); + + var messageCallback = function(event) { + if (event.origin !== window.location.origin || ifrm.contentWindow !== event.source) { + return; + } + + var oauth = parseCallback(event.data); + processCallback(oauth, initPromise); + + document.body.removeChild(ifrm); + window.removeEventListener("message", messageCallback); + }; + + window.addEventListener("message", messageCallback); + }; + + var options = {}; + switch (initOptions.onLoad) { + case 'check-sso': + if (loginIframe.enable) { + setupCheckLoginIframe().then(function() { + checkLoginIframe().then(function (unchanged) { + if (!unchanged) { + kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false); + } else { + initPromise.setSuccess(); + } + }).catch(function (error) { + initPromise.setError(error); + }); + }); + } else { + kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false); + } + break; + case 'login-required': + doLogin(true); + break; + default: + throw 'Invalid value for onLoad'; + } + } + + function processInit() { + var callback = parseCallback(window.location.href); + + if (callback) { + window.history.replaceState(window.history.state, null, callback.newUrl); + } + + if (callback && callback.valid) { + return setupCheckLoginIframe().then(function() { + processCallback(callback, initPromise); + }).catch(function (error) { + initPromise.setError(error); + }); + } else if (initOptions) { + if (initOptions.token && initOptions.refreshToken) { + setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken); + + if (loginIframe.enable) { + setupCheckLoginIframe().then(function() { + checkLoginIframe().then(function (unchanged) { + if (unchanged) { + kc.onAuthSuccess && kc.onAuthSuccess(); + initPromise.setSuccess(); + scheduleCheckIframe(); + } else { + initPromise.setSuccess(); + } + }).catch(function (error) { + initPromise.setError(error); + }); + }); + } else { + kc.updateToken(-1).then(function() { + kc.onAuthSuccess && kc.onAuthSuccess(); + initPromise.setSuccess(); + }).catch(function(error) { + kc.onAuthError && kc.onAuthError(); + if (initOptions.onLoad) { + onLoad(); + } else { + initPromise.setError(error); + } + }); + } + } else if (initOptions.onLoad) { + onLoad(); + } else { + initPromise.setSuccess(); + } + } else { + initPromise.setSuccess(); + } + } + + function domReady() { + var promise = createPromise(); + + var checkReadyState = function () { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + document.removeEventListener('readystatechange', checkReadyState); + promise.setSuccess(); + } + } + document.addEventListener('readystatechange', checkReadyState); + + checkReadyState(); // just in case the event was already fired and we missed it (in case the init is done later than at the load time, i.e. it's done from code) + + return promise.promise; + } + + configPromise.then(function () { + domReady() + .then(check3pCookiesSupported) + .then(processInit) + .catch(function (error) { + promise.setError(error); + }); + }); + configPromise.catch(function (error) { + promise.setError(error); + }); + + return promise.promise; + } + + kc.login = function (options) { + return adapter.login(options); + } + + function generateRandomData(len) { + // use web crypto APIs if possible + var array = null; + var crypto = window.crypto || window.msCrypto; + if (crypto && crypto.getRandomValues && window.Uint8Array) { + array = new Uint8Array(len); + crypto.getRandomValues(array); + return array; + } + + // fallback to Math random + array = new Array(len); + for (var j = 0; j < array.length; j++) { + array[j] = Math.floor(256 * Math.random()); + } + return array; + } + + function generateCodeVerifier(len) { + return generateRandomString(len, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'); + } + + function generateRandomString(len, alphabet){ + var randomData = generateRandomData(len); + var chars = new Array(len); + for (var i = 0; i < len; i++) { + chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length); + } + return String.fromCharCode.apply(null, chars); + } + + function generatePkceChallenge(pkceMethod, codeVerifier) { + switch (pkceMethod) { + // The use of the "plain" method is considered insecure and therefore not supported. + case "S256": + // hash codeVerifier, then encode as url-safe base64 without padding + var hashBytes = new Uint8Array(sha256.arrayBuffer(codeVerifier)); + var encodedHash = base64.fromByteArray(hashBytes) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/\=/g, ''); + return encodedHash; + default: + throw 'Invalid value for pkceMethod'; + } + } + + kc.createLoginUrl = function(options) { + var state = createUUID(); + var nonce = createUUID(); + + var redirectUri = adapter.redirectUri(options); + + var callbackState = { + state: state, + nonce: nonce, + redirectUri: encodeURIComponent(redirectUri) + }; + + if (options && options.prompt) { + callbackState.prompt = options.prompt; + } + + var baseUrl; + if (options && options.action == 'register') { + baseUrl = kc.endpoints.register(); + } else { + baseUrl = kc.endpoints.authorize(); + } + + var scope = options && options.scope || kc.scope; + if (!scope) { + // if scope is not set, default to "openid" + scope = "openid"; + } else if (scope.indexOf("openid") === -1) { + // if openid scope is missing, prefix the given scopes with it + scope = "openid " + scope; + } + + var url = baseUrl + + '?client_id=' + encodeURIComponent(kc.clientId) + + '&redirect_uri=' + encodeURIComponent(redirectUri) + + '&state=' + encodeURIComponent(state) + + '&response_mode=' + encodeURIComponent(kc.responseMode) + + '&response_type=' + encodeURIComponent(kc.responseType) + + '&scope=' + encodeURIComponent(scope); + if (useNonce) { + url = url + '&nonce=' + encodeURIComponent(nonce); + } + + if (options && options.prompt) { + url += '&prompt=' + encodeURIComponent(options.prompt); + } + + if (options && options.maxAge) { + url += '&max_age=' + encodeURIComponent(options.maxAge); + } + + if (options && options.loginHint) { + url += '&login_hint=' + encodeURIComponent(options.loginHint); + } + + if (options && options.idpHint) { + url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint); + } + + if (options && options.action && options.action != 'register') { + url += '&kc_action=' + encodeURIComponent(options.action); + } + + if (options && options.locale) { + url += '&ui_locales=' + encodeURIComponent(options.locale); + } + + if (kc.pkceMethod) { + var codeVerifier = generateCodeVerifier(96); + callbackState.pkceCodeVerifier = codeVerifier; + var pkceChallenge = generatePkceChallenge(kc.pkceMethod, codeVerifier); + url += '&code_challenge=' + pkceChallenge; + url += '&code_challenge_method=' + kc.pkceMethod; + } + + callbackStorage.add(callbackState); + + return url; + } + + kc.logout = function(options) { + return adapter.logout(options); + } + + kc.createLogoutUrl = function(options) { + var url = kc.endpoints.logout() + + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options, false)); + + return url; + } + + kc.register = function (options) { + return adapter.register(options); + } + + kc.createRegisterUrl = function(options) { + if (!options) { + options = {}; + } + options.action = 'register'; + return kc.createLoginUrl(options); + } + + kc.createAccountUrl = function(options) { + var realm = getRealmUrl(); + var url = undefined; + if (typeof realm !== 'undefined') { + url = realm + + '/account' + + '?referrer=' + encodeURIComponent(kc.clientId) + + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options)); + } + return url; + } + + kc.accountManagement = function() { + return adapter.accountManagement(); + } + + kc.hasRealmRole = function (role) { + var access = kc.realmAccess; + return !!access && access.roles.indexOf(role) >= 0; + } + + kc.hasResourceRole = function(role, resource) { + if (!kc.resourceAccess) { + return false; + } + + var access = kc.resourceAccess[resource || kc.clientId]; + return !!access && access.roles.indexOf(role) >= 0; + } + + kc.loadUserProfile = function() { + var url = getRealmUrl() + '/account'; + var req = new XMLHttpRequest(); + req.open('GET', url, true); + req.setRequestHeader('Accept', 'application/json'); + req.setRequestHeader('Authorization', 'bearer ' + kc.token); + + var promise = createPromise(); + + req.onreadystatechange = function () { + if (req.readyState == 4) { + if (req.status == 200) { + kc.profile = JSON.parse(req.responseText); + promise.setSuccess(kc.profile); + } else { + promise.setError(); + } + } + } + + req.send(); + + return promise.promise; + } + + kc.loadUserInfo = function() { + var url = kc.endpoints.userinfo(); + var req = new XMLHttpRequest(); + req.open('GET', url, true); + req.setRequestHeader('Accept', 'application/json'); + req.setRequestHeader('Authorization', 'bearer ' + kc.token); + + var promise = createPromise(); + + req.onreadystatechange = function () { + if (req.readyState == 4) { + if (req.status == 200) { + kc.userInfo = JSON.parse(req.responseText); + promise.setSuccess(kc.userInfo); + } else { + promise.setError(); + } + } + } + + req.send(); + + return promise.promise; + } + + kc.isTokenExpired = function(minValidity) { + if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != 'implicit' )) { + throw 'Not authenticated'; + } + + if (kc.timeSkew == null) { + logInfo('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set'); + return true; + } + + var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew; + if (minValidity) { + if (isNaN(minValidity)) { + throw 'Invalid minValidity'; + } + expiresIn -= minValidity; + } + return expiresIn < 0; + } + + kc.updateToken = function(minValidity) { + var promise = createPromise(); + + if (!kc.refreshToken) { + promise.setError(); + return promise.promise; + } + + minValidity = minValidity || 5; + + var exec = function() { + var refreshToken = false; + if (minValidity == -1) { + refreshToken = true; + logInfo('[KEYCLOAK] Refreshing token: forced refresh'); + } else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) { + refreshToken = true; + logInfo('[KEYCLOAK] Refreshing token: token expired'); + } + + if (!refreshToken) { + promise.setSuccess(false); + } else { + var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken; + var url = kc.endpoints.token(); + + refreshQueue.push(promise); + + if (refreshQueue.length == 1) { + var req = new XMLHttpRequest(); + req.open('POST', url, true); + req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + req.withCredentials = true; + + params += '&client_id=' + encodeURIComponent(kc.clientId); + + var timeLocal = new Date().getTime(); + + req.onreadystatechange = function () { + if (req.readyState == 4) { + if (req.status == 200) { + logInfo('[KEYCLOAK] Token refreshed'); + + timeLocal = (timeLocal + new Date().getTime()) / 2; + + var tokenResponse = JSON.parse(req.responseText); + + setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal); + + kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess(); + for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) { + p.setSuccess(true); + } + } else { + logWarn('[KEYCLOAK] Failed to refresh token'); + + if (req.status == 400) { + kc.clearToken(); + } + + kc.onAuthRefreshError && kc.onAuthRefreshError(); + for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) { + p.setError(true); + } + } + } + }; + + req.send(params); + } + } + } + + if (loginIframe.enable) { + var iframePromise = checkLoginIframe(); + iframePromise.then(function() { + exec(); + }).catch(function(error) { + promise.setError(error); + }); + } else { + exec(); + } + + return promise.promise; + } + + kc.clearToken = function() { + if (kc.token) { + setToken(null, null, null); + kc.onAuthLogout && kc.onAuthLogout(); + if (kc.loginRequired) { + kc.login(); + } + } + } + + function getRealmUrl() { + if (typeof kc.authServerUrl !== 'undefined') { + if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') { + return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm); + } else { + return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm); + } + } else { + return undefined; + } + } + + function getOrigin() { + if (!window.location.origin) { + return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); + } else { + return window.location.origin; + } + } + + function processCallback(oauth, promise) { + var code = oauth.code; + var error = oauth.error; + var prompt = oauth.prompt; + + var timeLocal = new Date().getTime(); + + if (oauth['kc_action_status']) { + kc.onActionUpdate && kc.onActionUpdate(oauth['kc_action_status']); + } + + if (error) { + if (prompt != 'none') { + var errorData = { error: error, error_description: oauth.error_description }; + kc.onAuthError && kc.onAuthError(errorData); + promise && promise.setError(errorData); + } else { + promise && promise.setSuccess(); + } + return; + } else if ((kc.flow != 'standard') && (oauth.access_token || oauth.id_token)) { + authSuccess(oauth.access_token, null, oauth.id_token, true); + } + + if ((kc.flow != 'implicit') && code) { + var params = 'code=' + code + '&grant_type=authorization_code'; + var url = kc.endpoints.token(); + + var req = new XMLHttpRequest(); + req.open('POST', url, true); + req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + + params += '&client_id=' + encodeURIComponent(kc.clientId); + params += '&redirect_uri=' + oauth.redirectUri; + + if (oauth.pkceCodeVerifier) { + params += '&code_verifier=' + oauth.pkceCodeVerifier; + } + + req.withCredentials = true; + + req.onreadystatechange = function() { + if (req.readyState == 4) { + if (req.status == 200) { + + var tokenResponse = JSON.parse(req.responseText); + authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard'); + scheduleCheckIframe(); + } else { + kc.onAuthError && kc.onAuthError(); + promise && promise.setError(); + } + } + }; + + req.send(params); + } + + function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) { + timeLocal = (timeLocal + new Date().getTime()) / 2; + + setToken(accessToken, refreshToken, idToken, timeLocal); + + if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) || + (kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) || + (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) { + + logInfo('[KEYCLOAK] Invalid nonce, clearing token'); + kc.clearToken(); + promise && promise.setError(); + } else { + if (fulfillPromise) { + kc.onAuthSuccess && kc.onAuthSuccess(); + promise && promise.setSuccess(); + } + } + } + + } + + function loadConfig(url) { + var promise = createPromise(); + var configUrl; + + if (!config) { + configUrl = 'keycloak.json'; + } else if (typeof config === 'string') { + configUrl = config; + } + + function setupOidcEndoints(oidcConfiguration) { + if (! oidcConfiguration) { + kc.endpoints = { + authorize: function() { + return getRealmUrl() + '/protocol/openid-connect/auth'; + }, + token: function() { + return getRealmUrl() + '/protocol/openid-connect/token'; + }, + logout: function() { + return getRealmUrl() + '/protocol/openid-connect/logout'; + }, + checkSessionIframe: function() { + var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html'; + if (kc.iframeVersion) { + src = src + '?version=' + kc.iframeVersion; + } + return src; + }, + thirdPartyCookiesIframe: function() { + var src = getRealmUrl() + '/protocol/openid-connect/3p-cookies/step1.html'; + if (kc.iframeVersion) { + src = src + '?version=' + kc.iframeVersion; + } + return src; + }, + register: function() { + return getRealmUrl() + '/protocol/openid-connect/registrations'; + }, + userinfo: function() { + return getRealmUrl() + '/protocol/openid-connect/userinfo'; + } + }; + } else { + kc.endpoints = { + authorize: function() { + return oidcConfiguration.authorization_endpoint; + }, + token: function() { + return oidcConfiguration.token_endpoint; + }, + logout: function() { + if (!oidcConfiguration.end_session_endpoint) { + throw "Not supported by the OIDC server"; + } + return oidcConfiguration.end_session_endpoint; + }, + checkSessionIframe: function() { + if (!oidcConfiguration.check_session_iframe) { + throw "Not supported by the OIDC server"; + } + return oidcConfiguration.check_session_iframe; + }, + register: function() { + throw 'Redirection to "Register user" page not supported in standard OIDC mode'; + }, + userinfo: function() { + if (!oidcConfiguration.userinfo_endpoint) { + throw "Not supported by the OIDC server"; + } + return oidcConfiguration.userinfo_endpoint; + } + } + } + } + + if (configUrl) { + var req = new XMLHttpRequest(); + req.open('GET', configUrl, true); + req.setRequestHeader('Accept', 'application/json'); + + req.onreadystatechange = function () { + if (req.readyState == 4) { + if (req.status == 200 || fileLoaded(req)) { + var config = JSON.parse(req.responseText); + + kc.authServerUrl = config['auth-server-url']; + kc.realm = config['realm']; + kc.clientId = config['resource']; + setupOidcEndoints(null); + promise.setSuccess(); + } else { + promise.setError(); + } + } + }; + + req.send(); + } else { + if (!config.clientId) { + throw 'clientId missing'; + } + + kc.clientId = config.clientId; + + var oidcProvider = config['oidcProvider']; + if (!oidcProvider) { + if (!config['url']) { + var scripts = document.getElementsByTagName('script'); + for (var i = 0; i < scripts.length; i++) { + if (scripts[i].src.match(/.*keycloak\.js/)) { + config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js')); + break; + } + } + } + if (!config.realm) { + throw 'realm missing'; + } + + kc.authServerUrl = config.url; + kc.realm = config.realm; + setupOidcEndoints(null); + promise.setSuccess(); + } else { + if (typeof oidcProvider === 'string') { + var oidcProviderConfigUrl; + if (oidcProvider.charAt(oidcProvider.length - 1) == '/') { + oidcProviderConfigUrl = oidcProvider + '.well-known/openid-configuration'; + } else { + oidcProviderConfigUrl = oidcProvider + '/.well-known/openid-configuration'; + } + var req = new XMLHttpRequest(); + req.open('GET', oidcProviderConfigUrl, true); + req.setRequestHeader('Accept', 'application/json'); + + req.onreadystatechange = function () { + if (req.readyState == 4) { + if (req.status == 200 || fileLoaded(req)) { + var oidcProviderConfig = JSON.parse(req.responseText); + setupOidcEndoints(oidcProviderConfig); + promise.setSuccess(); + } else { + promise.setError(); + } + } + }; + + req.send(); + } else { + setupOidcEndoints(oidcProvider); + promise.setSuccess(); + } + } + } + + return promise.promise; + } + + function fileLoaded(xhr) { + return xhr.status == 0 && xhr.responseText && xhr.responseURL.startsWith('file:'); + } + + function setToken(token, refreshToken, idToken, timeLocal) { + if (kc.tokenTimeoutHandle) { + clearTimeout(kc.tokenTimeoutHandle); + kc.tokenTimeoutHandle = null; + } + + if (refreshToken) { + kc.refreshToken = refreshToken; + kc.refreshTokenParsed = decodeToken(refreshToken); + } else { + delete kc.refreshToken; + delete kc.refreshTokenParsed; + } + + if (idToken) { + kc.idToken = idToken; + kc.idTokenParsed = decodeToken(idToken); + } else { + delete kc.idToken; + delete kc.idTokenParsed; + } + + if (token) { + kc.token = token; + kc.tokenParsed = decodeToken(token); + kc.sessionId = kc.tokenParsed.session_state; + kc.authenticated = true; + kc.subject = kc.tokenParsed.sub; + kc.realmAccess = kc.tokenParsed.realm_access; + kc.resourceAccess = kc.tokenParsed.resource_access; + + if (timeLocal) { + kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat; + } + + if (kc.timeSkew != null) { + logInfo('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds'); + + if (kc.onTokenExpired) { + var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000; + logInfo('[KEYCLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s'); + if (expiresIn <= 0) { + kc.onTokenExpired(); + } else { + kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn); + } + } + } + } else { + delete kc.token; + delete kc.tokenParsed; + delete kc.subject; + delete kc.realmAccess; + delete kc.resourceAccess; + + kc.authenticated = false; + } + } + + function decodeToken(str) { + str = str.split('.')[1]; + + str = str.replace(/-/g, '+'); + str = str.replace(/_/g, '/'); + switch (str.length % 4) { + case 0: + break; + case 2: + str += '=='; + break; + case 3: + str += '='; + break; + default: + throw 'Invalid token'; + } + + str = decodeURIComponent(escape(atob(str))); + + str = JSON.parse(str); + return str; + } + + function createUUID() { + var hexDigits = '0123456789abcdef'; + var s = generateRandomString(36, hexDigits).split(""); + s[14] = '4'; + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); + s[8] = s[13] = s[18] = s[23] = '-'; + var uuid = s.join(''); + return uuid; + } + + function parseCallback(url) { + var oauth = parseCallbackUrl(url); + if (!oauth) { + return; + } + + var oauthState = callbackStorage.get(oauth.state); + + if (oauthState) { + oauth.valid = true; + oauth.redirectUri = oauthState.redirectUri; + oauth.storedNonce = oauthState.nonce; + oauth.prompt = oauthState.prompt; + oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier; + } + + return oauth; + } + + function parseCallbackUrl(url) { + var supportedParams; + switch (kc.flow) { + case 'standard': + supportedParams = ['code', 'state', 'session_state', 'kc_action_status']; + break; + case 'implicit': + supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status']; + break; + case 'hybrid': + supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status']; + break; + } + + supportedParams.push('error'); + supportedParams.push('error_description'); + supportedParams.push('error_uri'); + + var queryIndex = url.indexOf('?'); + var fragmentIndex = url.indexOf('#'); + + var newUrl; + var parsed; + + if (kc.responseMode === 'query' && queryIndex !== -1) { + newUrl = url.substring(0, queryIndex); + parsed = parseCallbackParams(url.substring(queryIndex + 1, fragmentIndex !== -1 ? fragmentIndex : url.length), supportedParams); + if (parsed.paramsString !== '') { + newUrl += '?' + parsed.paramsString; + } + if (fragmentIndex !== -1) { + newUrl += url.substring(fragmentIndex); + } + } else if (kc.responseMode === 'fragment' && fragmentIndex !== -1) { + newUrl = url.substring(0, fragmentIndex); + parsed = parseCallbackParams(url.substring(fragmentIndex + 1), supportedParams); + if (parsed.paramsString !== '') { + newUrl += '#' + parsed.paramsString; + } + } + + if (parsed && parsed.oauthParams) { + if (kc.flow === 'standard' || kc.flow === 'hybrid') { + if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) { + parsed.oauthParams.newUrl = newUrl; + return parsed.oauthParams; + } + } else if (kc.flow === 'implicit') { + if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) { + parsed.oauthParams.newUrl = newUrl; + return parsed.oauthParams; + } + } + } + } + + function parseCallbackParams(paramsString, supportedParams) { + var p = paramsString.split('&'); + var result = { + paramsString: '', + oauthParams: {} + } + for (var i = 0; i < p.length; i++) { + var split = p[i].indexOf("="); + var key = p[i].slice(0, split); + if (supportedParams.indexOf(key) !== -1) { + result.oauthParams[key] = p[i].slice(split + 1); + } else { + if (result.paramsString !== '') { + result.paramsString += '&'; + } + result.paramsString += p[i]; + } + } + return result; + } + + function createPromise() { + // Need to create a native Promise which also preserves the + // interface of the custom promise type previously used by the API + var p = { + setSuccess: function(result) { + p.resolve(result); + }, + + setError: function(result) { + p.reject(result); + } + }; + p.promise = new Promise(function(resolve, reject) { + p.resolve = resolve; + p.reject = reject; + }); + + p.promise.success = function(callback) { + logPromiseDeprecation(); + + this.then(function handleSuccess(value) { + callback(value); + }); + + return this; + } + + p.promise.error = function(callback) { + logPromiseDeprecation(); + + this.catch(function handleError(error) { + callback(error); + }); + + return this; + } + + return p; + } + + // Function to extend existing native Promise with timeout + function applyTimeoutToPromise(promise, timeout, errorMessage) { + var timeoutHandle = null; + var timeoutPromise = new Promise(function (resolve, reject) { + timeoutHandle = setTimeout(function () { + reject({ "error": errorMessage || "Promise is not settled within timeout of " + timeout + "ms" }); + }, timeout); + }); + + return Promise.race([promise, timeoutPromise]).finally(function () { + clearTimeout(timeoutHandle); + }); + } + + function setupCheckLoginIframe() { + var promise = createPromise(); + + if (!loginIframe.enable) { + promise.setSuccess(); + return promise.promise; + } + + if (loginIframe.iframe) { + promise.setSuccess(); + return promise.promise; + } + + var iframe = document.createElement('iframe'); + loginIframe.iframe = iframe; + + iframe.onload = function() { + var authUrl = kc.endpoints.authorize(); + if (authUrl.charAt(0) === '/') { + loginIframe.iframeOrigin = getOrigin(); + } else { + loginIframe.iframeOrigin = authUrl.substring(0, authUrl.indexOf('/', 8)); + } + promise.setSuccess(); + } + + var src = kc.endpoints.checkSessionIframe(); + iframe.setAttribute('src', src ); + iframe.setAttribute('title', 'keycloak-session-iframe' ); + iframe.style.display = 'none'; + document.body.appendChild(iframe); + + var messageCallback = function(event) { + if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) { + return; + } + + if (!(event.data == 'unchanged' || event.data == 'changed' || event.data == 'error')) { + return; + } + + + if (event.data != 'unchanged') { + kc.clearToken(); + } + + var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length); + + for (var i = callbacks.length - 1; i >= 0; --i) { + var promise = callbacks[i]; + if (event.data == 'error') { + promise.setError(); + } else { + promise.setSuccess(event.data == 'unchanged'); + } + } + }; + + window.addEventListener('message', messageCallback, false); + + return promise.promise; + } + + function scheduleCheckIframe() { + if (loginIframe.enable) { + if (kc.token) { + setTimeout(function() { + checkLoginIframe().then(function(unchanged) { + if (unchanged) { + scheduleCheckIframe(); + } + }); + }, loginIframe.interval * 1000); + } + } + } + + function checkLoginIframe() { + var promise = createPromise(); + + if (loginIframe.iframe && loginIframe.iframeOrigin ) { + var msg = kc.clientId + ' ' + (kc.sessionId ? kc.sessionId : ''); + loginIframe.callbackList.push(promise); + var origin = loginIframe.iframeOrigin; + if (loginIframe.callbackList.length == 1) { + loginIframe.iframe.contentWindow.postMessage(msg, origin); + } + } else { + promise.setSuccess(); + } + + return promise.promise; + } + + function check3pCookiesSupported() { + var promise = createPromise(); + + if (loginIframe.enable || kc.silentCheckSsoRedirectUri) { + var iframe = document.createElement('iframe'); + iframe.setAttribute('src', kc.endpoints.thirdPartyCookiesIframe()); + iframe.setAttribute('title', 'keycloak-3p-check-iframe' ); + iframe.style.display = 'none'; + document.body.appendChild(iframe); + + var messageCallback = function(event) { + if (iframe.contentWindow !== event.source) { + return; + } + + if (event.data !== "supported" && event.data !== "unsupported") { + return; + } else if (event.data === "unsupported") { + loginIframe.enable = false; + if (kc.silentCheckSsoFallback) { + kc.silentCheckSsoRedirectUri = false; + } + logWarn("[KEYCLOAK] 3rd party cookies aren't supported by this browser. checkLoginIframe and " + + "silent check-sso are not available.") + } + + document.body.removeChild(iframe); + window.removeEventListener("message", messageCallback); + promise.setSuccess(); + }; + + window.addEventListener('message', messageCallback, false); + } else { + promise.setSuccess(); + } + + return applyTimeoutToPromise(promise.promise, kc.messageReceiveTimeout, "Timeout when waiting for 3rd party check iframe message."); + } + + function loadAdapter(type) { + if (!type || type == 'default') { + return { + login: function(options) { + window.location.replace(kc.createLoginUrl(options)); + return createPromise().promise; + }, + + logout: function(options) { + window.location.replace(kc.createLogoutUrl(options)); + return createPromise().promise; + }, + + register: function(options) { + window.location.replace(kc.createRegisterUrl(options)); + return createPromise().promise; + }, + + accountManagement : function() { + var accountUrl = kc.createAccountUrl(); + if (typeof accountUrl !== 'undefined') { + window.location.href = accountUrl; + } else { + throw "Not supported by the OIDC server"; + } + return createPromise().promise; + }, + + redirectUri: function(options, encodeHash) { + if (arguments.length == 1) { + encodeHash = true; + } + + if (options && options.redirectUri) { + return options.redirectUri; + } else if (kc.redirectUri) { + return kc.redirectUri; + } else { + return location.href; + } + } + }; + } + + if (type == 'cordova') { + loginIframe.enable = false; + var cordovaOpenWindowWrapper = function(loginUrl, target, options) { + if (window.cordova && window.cordova.InAppBrowser) { + // Use inappbrowser for IOS and Android if available + return window.cordova.InAppBrowser.open(loginUrl, target, options); + } else { + return window.open(loginUrl, target, options); + } + }; + + var shallowCloneCordovaOptions = function (userOptions) { + if (userOptions && userOptions.cordovaOptions) { + return Object.keys(userOptions.cordovaOptions).reduce(function (options, optionName) { + options[optionName] = userOptions.cordovaOptions[optionName]; + return options; + }, {}); + } else { + return {}; + } + }; + + var formatCordovaOptions = function (cordovaOptions) { + return Object.keys(cordovaOptions).reduce(function (options, optionName) { + options.push(optionName+"="+cordovaOptions[optionName]); + return options; + }, []).join(","); + }; + + var createCordovaOptions = function (userOptions) { + var cordovaOptions = shallowCloneCordovaOptions(userOptions); + cordovaOptions.location = 'no'; + if (userOptions && userOptions.prompt == 'none') { + cordovaOptions.hidden = 'yes'; + } + return formatCordovaOptions(cordovaOptions); + }; + + return { + login: function(options) { + var promise = createPromise(); + + var cordovaOptions = createCordovaOptions(options); + var loginUrl = kc.createLoginUrl(options); + var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', cordovaOptions); + var completed = false; + + var closed = false; + var closeBrowser = function() { + closed = true; + ref.close(); + }; + + ref.addEventListener('loadstart', function(event) { + if (event.url.indexOf('http://localhost') == 0) { + var callback = parseCallback(event.url); + processCallback(callback, promise); + closeBrowser(); + completed = true; + } + }); + + ref.addEventListener('loaderror', function(event) { + if (!completed) { + if (event.url.indexOf('http://localhost') == 0) { + var callback = parseCallback(event.url); + processCallback(callback, promise); + closeBrowser(); + completed = true; + } else { + promise.setError(); + closeBrowser(); + } + } + }); + + ref.addEventListener('exit', function(event) { + if (!closed) { + promise.setError({ + reason: "closed_by_user" + }); + } + }); + + return promise.promise; + }, + + logout: function(options) { + var promise = createPromise(); + + var logoutUrl = kc.createLogoutUrl(options); + var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes,clearcache=yes'); + + var error; + + ref.addEventListener('loadstart', function(event) { + if (event.url.indexOf('http://localhost') == 0) { + ref.close(); + } + }); + + ref.addEventListener('loaderror', function(event) { + if (event.url.indexOf('http://localhost') == 0) { + ref.close(); + } else { + error = true; + ref.close(); + } + }); + + ref.addEventListener('exit', function(event) { + if (error) { + promise.setError(); + } else { + kc.clearToken(); + promise.setSuccess(); + } + }); + + return promise.promise; + }, + + register : function(options) { + var promise = createPromise(); + var registerUrl = kc.createRegisterUrl(); + var cordovaOptions = createCordovaOptions(options); + var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions); + ref.addEventListener('loadstart', function(event) { + if (event.url.indexOf('http://localhost') == 0) { + ref.close(); + var oauth = parseCallback(event.url); + processCallback(oauth, promise); + } + }); + return promise.promise; + }, + + accountManagement : function() { + var accountUrl = kc.createAccountUrl(); + if (typeof accountUrl !== 'undefined') { + var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no'); + ref.addEventListener('loadstart', function(event) { + if (event.url.indexOf('http://localhost') == 0) { + ref.close(); + } + }); + } else { + throw "Not supported by the OIDC server"; + } + }, + + redirectUri: function(options) { + return 'http://localhost'; + } + } + } + + if (type == 'cordova-native') { + loginIframe.enable = false; + + return { + login: function(options) { + var promise = createPromise(); + var loginUrl = kc.createLoginUrl(options); + + universalLinks.subscribe('keycloak', function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + var oauth = parseCallback(event.url); + processCallback(oauth, promise); + }); + + window.cordova.plugins.browsertab.openUrl(loginUrl); + return promise.promise; + }, + + logout: function(options) { + var promise = createPromise(); + var logoutUrl = kc.createLogoutUrl(options); + + universalLinks.subscribe('keycloak', function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + kc.clearToken(); + promise.setSuccess(); + }); + + window.cordova.plugins.browsertab.openUrl(logoutUrl); + return promise.promise; + }, + + register : function(options) { + var promise = createPromise(); + var registerUrl = kc.createRegisterUrl(options); + universalLinks.subscribe('keycloak' , function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + var oauth = parseCallback(event.url); + processCallback(oauth, promise); + }); + window.cordova.plugins.browsertab.openUrl(registerUrl); + return promise.promise; + + }, + + accountManagement : function() { + var accountUrl = kc.createAccountUrl(); + if (typeof accountUrl !== 'undefined') { + window.cordova.plugins.browsertab.openUrl(accountUrl); + } else { + throw "Not supported by the OIDC server"; + } + }, + + redirectUri: function(options) { + if (options && options.redirectUri) { + return options.redirectUri; + } else if (kc.redirectUri) { + return kc.redirectUri; + } else { + return "http://localhost"; + } + } + } + } + + throw 'invalid adapter type: ' + type; + } + + var LocalStorage = function() { + if (!(this instanceof LocalStorage)) { + return new LocalStorage(); + } + + localStorage.setItem('kc-test', 'test'); + localStorage.removeItem('kc-test'); + + var cs = this; + + function clearExpired() { + var time = new Date().getTime(); + for (var i = 0; i < localStorage.length; i++) { + var key = localStorage.key(i); + if (key && key.indexOf('kc-callback-') == 0) { + var value = localStorage.getItem(key); + if (value) { + try { + var expires = JSON.parse(value).expires; + if (!expires || expires < time) { + localStorage.removeItem(key); + } + } catch (err) { + localStorage.removeItem(key); + } + } + } + } + } + + cs.get = function(state) { + if (!state) { + return; + } + + var key = 'kc-callback-' + state; + var value = localStorage.getItem(key); + if (value) { + localStorage.removeItem(key); + value = JSON.parse(value); + } + + clearExpired(); + return value; + }; + + cs.add = function(state) { + clearExpired(); + + var key = 'kc-callback-' + state.state; + state.expires = new Date().getTime() + (60 * 60 * 1000); + localStorage.setItem(key, JSON.stringify(state)); + }; + }; + + var CookieStorage = function() { + if (!(this instanceof CookieStorage)) { + return new CookieStorage(); + } + + var cs = this; + + cs.get = function(state) { + if (!state) { + return; + } + + var value = getCookie('kc-callback-' + state); + setCookie('kc-callback-' + state, '', cookieExpiration(-100)); + if (value) { + return JSON.parse(value); + } + }; + + cs.add = function(state) { + setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60)); + }; + + cs.removeItem = function(key) { + setCookie(key, '', cookieExpiration(-100)); + }; + + var cookieExpiration = function (minutes) { + var exp = new Date(); + exp.setTime(exp.getTime() + (minutes*60*1000)); + return exp; + }; + + var getCookie = function (key) { + var name = key + '='; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == ' ') { + c = c.substring(1); + } + if (c.indexOf(name) == 0) { + return c.substring(name.length, c.length); + } + } + return ''; + }; + + var setCookie = function (key, value, expirationDate) { + var cookie = key + '=' + value + '; ' + + 'expires=' + expirationDate.toUTCString() + '; '; + document.cookie = cookie; + } + }; + + function createCallbackStorage() { + try { + return new LocalStorage(); + } catch (err) { + } + + return new CookieStorage(); + } + + function createLogger(fn) { + return function() { + if (kc.enableLogging) { + fn.apply(console, Array.prototype.slice.call(arguments)); + } + }; + } +} + +export default Keycloak; diff --git a/adapters/oidc/js/src/main/resources/keycloak-authz.js b/adapters/oidc/js/src/main/resources/keycloak-authz.js deleted file mode 100644 index df60747641..0000000000 --- a/adapters/oidc/js/src/main/resources/keycloak-authz.js +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -(function( window, undefined ) { - - var KeycloakAuthorization = function (keycloak, options) { - var _instance = this; - this.rpt = null; - - var resolve = function () {}; - var reject = function () {}; - - // detects if browser supports promises - if (typeof Promise !== "undefined" && Promise.toString().indexOf("[native code]") !== -1) { - this.ready = new Promise(function (res, rej) { - resolve = res; - reject = rej; - }); - } - - this.init = function () { - var request = new XMLHttpRequest(); - - request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/.well-known/uma2-configuration'); - request.onreadystatechange = function () { - if (request.readyState == 4) { - if (request.status == 200) { - _instance.config = JSON.parse(request.responseText); - resolve(); - } else { - console.error('Could not obtain configuration from server.'); - reject(); - } - } - } - - request.send(null); - }; - - /** - * This method enables client applications to better integrate with resource servers protected by a Keycloak - * policy enforcer using UMA protocol. - * - * The authorization request must be provided with a ticket. - */ - this.authorize = function (authorizationRequest) { - this.then = function (onGrant, onDeny, onError) { - if (authorizationRequest && authorizationRequest.ticket) { - var request = new XMLHttpRequest(); - - request.open('POST', _instance.config.token_endpoint, true); - request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); - - request.onreadystatechange = function () { - if (request.readyState == 4) { - var status = request.status; - - if (status >= 200 && status < 300) { - var rpt = JSON.parse(request.responseText).access_token; - _instance.rpt = rpt; - onGrant(rpt); - } else if (status == 403) { - if (onDeny) { - onDeny(); - } else { - console.error('Authorization request was denied by the server.'); - } - } else { - if (onError) { - onError(); - } else { - console.error('Could not obtain authorization data from server.'); - } - } - } - }; - - var params = "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&client_id=" + keycloak.clientId + "&ticket=" + authorizationRequest.ticket; - - if (authorizationRequest.submitRequest != undefined) { - params += "&submit_request=" + authorizationRequest.submitRequest; - } - - var metadata = authorizationRequest.metadata; - - if (metadata) { - if (metadata.responseIncludeResourceName) { - params += "&response_include_resource_name=" + metadata.responseIncludeResourceName; - } - if (metadata.responsePermissionsLimit) { - params += "&response_permissions_limit=" + metadata.responsePermissionsLimit; - } - } - - if (_instance.rpt && (authorizationRequest.incrementalAuthorization == undefined || authorizationRequest.incrementalAuthorization)) { - params += "&rpt=" + _instance.rpt; - } - - request.send(params); - } - }; - - return this; - }; - - /** - * Obtains all entitlements from a Keycloak Server based on a given resourceServerId. - */ - this.entitlement = function (resourceServerId, authorizationRequest) { - this.then = function (onGrant, onDeny, onError) { - var request = new XMLHttpRequest(); - - request.open('POST', _instance.config.token_endpoint, true); - request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); - - request.onreadystatechange = function () { - if (request.readyState == 4) { - var status = request.status; - - if (status >= 200 && status < 300) { - var rpt = JSON.parse(request.responseText).access_token; - _instance.rpt = rpt; - onGrant(rpt); - } else if (status == 403) { - if (onDeny) { - onDeny(); - } else { - console.error('Authorization request was denied by the server.'); - } - } else { - if (onError) { - onError(); - } else { - console.error('Could not obtain authorization data from server.'); - } - } - } - }; - - if (!authorizationRequest) { - authorizationRequest = {}; - } - - var params = "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&client_id=" + keycloak.clientId; - - if (authorizationRequest.claimToken) { - params += "&claim_token=" + authorizationRequest.claimToken; - - if (authorizationRequest.claimTokenFormat) { - params += "&claim_token_format=" + authorizationRequest.claimTokenFormat; - } - } - - params += "&audience=" + resourceServerId; - - var permissions = authorizationRequest.permissions; - - if (!permissions) { - permissions = []; - } - - for (i = 0; i < permissions.length; i++) { - var resource = permissions[i]; - var permission = resource.id; - - if (resource.scopes && resource.scopes.length > 0) { - permission += "#"; - for (j = 0; j < resource.scopes.length; j++) { - var scope = resource.scopes[j]; - if (permission.indexOf('#') != permission.length - 1) { - permission += ","; - } - permission += scope; - } - } - - params += "&permission=" + permission; - } - - var metadata = authorizationRequest.metadata; - - if (metadata) { - if (metadata.responseIncludeResourceName) { - params += "&response_include_resource_name=" + metadata.responseIncludeResourceName; - } - if (metadata.responsePermissionsLimit) { - params += "&response_permissions_limit=" + metadata.responsePermissionsLimit; - } - } - - if (_instance.rpt) { - params += "&rpt=" + _instance.rpt; - } - - request.send(params); - }; - - return this; - }; - - this.init(this); - - return this; - }; - - if ( typeof module === "object" && module && typeof module.exports === "object" ) { - module.exports = KeycloakAuthorization; - } else { - window.KeycloakAuthorization = KeycloakAuthorization; - - if ( typeof define === "function" && define.amd ) { - define( "keycloak-authorization", [], function () { return KeycloakAuthorization; } ); - } - } -})( window ); \ No newline at end of file diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js deleted file mode 100755 index 936a3c3c36..0000000000 --- a/adapters/oidc/js/src/main/resources/keycloak.js +++ /dev/null @@ -1,1766 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function(root, factory) { - if ( typeof exports === 'object' ) { - if ( typeof module === 'object' ) { - module.exports = factory( require("js-sha256"), require("base64-js") ); - } else { - exports["keycloak"] = factory( require("js-sha256"), require("base64-js") ); - } - } else { - /** - * [js-sha256]{@link https://github.com/emn178/js-sha256} - * - * @version 0.9.0 - * @author Chen, Yi-Cyuan [emn178@gmail.com] - * @copyright Chen, Yi-Cyuan 2014-2017 - * @license MIT - */ - !function () { "use strict"; function t(t, i) { i ? (d[0] = d[16] = d[1] = d[2] = d[3] = d[4] = d[5] = d[6] = d[7] = d[8] = d[9] = d[10] = d[11] = d[12] = d[13] = d[14] = d[15] = 0, this.blocks = d) : this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], t ? (this.h0 = 3238371032, this.h1 = 914150663, this.h2 = 812702999, this.h3 = 4144912697, this.h4 = 4290775857, this.h5 = 1750603025, this.h6 = 1694076839, this.h7 = 3204075428) : (this.h0 = 1779033703, this.h1 = 3144134277, this.h2 = 1013904242, this.h3 = 2773480762, this.h4 = 1359893119, this.h5 = 2600822924, this.h6 = 528734635, this.h7 = 1541459225), this.block = this.start = this.bytes = this.hBytes = 0, this.finalized = this.hashed = !1, this.first = !0, this.is224 = t } function i(i, r, s) { var e, n = typeof i; if ("string" === n) { var o, a = [], u = i.length, c = 0; for (e = 0; e < u; ++e)(o = i.charCodeAt(e)) < 128 ? a[c++] = o : o < 2048 ? (a[c++] = 192 | o >> 6, a[c++] = 128 | 63 & o) : o < 55296 || o >= 57344 ? (a[c++] = 224 | o >> 12, a[c++] = 128 | o >> 6 & 63, a[c++] = 128 | 63 & o) : (o = 65536 + ((1023 & o) << 10 | 1023 & i.charCodeAt(++e)), a[c++] = 240 | o >> 18, a[c++] = 128 | o >> 12 & 63, a[c++] = 128 | o >> 6 & 63, a[c++] = 128 | 63 & o); i = a } else { if ("object" !== n) throw new Error(h); if (null === i) throw new Error(h); if (f && i.constructor === ArrayBuffer) i = new Uint8Array(i); else if (!(Array.isArray(i) || f && ArrayBuffer.isView(i))) throw new Error(h) } i.length > 64 && (i = new t(r, !0).update(i).array()); var y = [], p = []; for (e = 0; e < 64; ++e) { var l = i[e] || 0; y[e] = 92 ^ l, p[e] = 54 ^ l } t.call(this, r, s), this.update(p), this.oKeyPad = y, this.inner = !0, this.sharedMemory = s } var h = "input is invalid type", r = "object" == typeof window, s = r ? window : {}; s.JS_SHA256_NO_WINDOW && (r = !1); var e = !r && "object" == typeof self, n = !s.JS_SHA256_NO_NODE_JS && "object" == typeof process && process.versions && process.versions.node; n ? s = global : e && (s = self); var o = !s.JS_SHA256_NO_COMMON_JS && "object" == typeof module && module.exports, a = "function" == typeof define && define.amd, f = !s.JS_SHA256_NO_ARRAY_BUFFER && "undefined" != typeof ArrayBuffer, u = "0123456789abcdef".split(""), c = [-2147483648, 8388608, 32768, 128], y = [24, 16, 8, 0], p = [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298], l = ["hex", "array", "digest", "arrayBuffer"], d = []; !s.JS_SHA256_NO_NODE_JS && Array.isArray || (Array.isArray = function (t) { return "[object Array]" === Object.prototype.toString.call(t) }), !f || !s.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW && ArrayBuffer.isView || (ArrayBuffer.isView = function (t) { return "object" == typeof t && t.buffer && t.buffer.constructor === ArrayBuffer }); var A = function (i, h) { return function (r) { return new t(h, !0).update(r)[i]() } }, w = function (i) { var h = A("hex", i); n && (h = b(h, i)), h.create = function () { return new t(i) }, h.update = function (t) { return h.create().update(t) }; for (var r = 0; r < l.length; ++r) { var s = l[r]; h[s] = A(s, i) } return h }, b = function (t, i) { var r = eval("require('crypto')"), s = eval("require('buffer').Buffer"), e = i ? "sha224" : "sha256", n = function (i) { if ("string" == typeof i) return r.createHash(e).update(i, "utf8").digest("hex"); if (null === i || void 0 === i) throw new Error(h); return i.constructor === ArrayBuffer && (i = new Uint8Array(i)), Array.isArray(i) || ArrayBuffer.isView(i) || i.constructor === s ? r.createHash(e).update(new s(i)).digest("hex") : t(i) }; return n }, v = function (t, h) { return function (r, s) { return new i(r, h, !0).update(s)[t]() } }, _ = function (t) { var h = v("hex", t); h.create = function (h) { return new i(h, t) }, h.update = function (t, i) { return h.create(t).update(i) }; for (var r = 0; r < l.length; ++r) { var s = l[r]; h[s] = v(s, t) } return h }; t.prototype.update = function (t) { if (!this.finalized) { var i, r = typeof t; if ("string" !== r) { if ("object" !== r) throw new Error(h); if (null === t) throw new Error(h); if (f && t.constructor === ArrayBuffer) t = new Uint8Array(t); else if (!(Array.isArray(t) || f && ArrayBuffer.isView(t))) throw new Error(h); i = !0 } for (var s, e, n = 0, o = t.length, a = this.blocks; n < o;) { if (this.hashed && (this.hashed = !1, a[0] = this.block, a[16] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = a[9] = a[10] = a[11] = a[12] = a[13] = a[14] = a[15] = 0), i) for (e = this.start; n < o && e < 64; ++n)a[e >> 2] |= t[n] << y[3 & e++]; else for (e = this.start; n < o && e < 64; ++n)(s = t.charCodeAt(n)) < 128 ? a[e >> 2] |= s << y[3 & e++] : s < 2048 ? (a[e >> 2] |= (192 | s >> 6) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]) : s < 55296 || s >= 57344 ? (a[e >> 2] |= (224 | s >> 12) << y[3 & e++], a[e >> 2] |= (128 | s >> 6 & 63) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++n)), a[e >> 2] |= (240 | s >> 18) << y[3 & e++], a[e >> 2] |= (128 | s >> 12 & 63) << y[3 & e++], a[e >> 2] |= (128 | s >> 6 & 63) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]); this.lastByteIndex = e, this.bytes += e - this.start, e >= 64 ? (this.block = a[16], this.start = e - 64, this.hash(), this.hashed = !0) : this.start = e } return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0, this.bytes = this.bytes % 4294967296), this } }, t.prototype.finalize = function () { if (!this.finalized) { this.finalized = !0; var t = this.blocks, i = this.lastByteIndex; t[16] = this.block, t[i >> 2] |= c[3 & i], this.block = t[16], i >= 56 && (this.hashed || this.hash(), t[0] = this.block, t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0), t[14] = this.hBytes << 3 | this.bytes >>> 29, t[15] = this.bytes << 3, this.hash() } }, t.prototype.hash = function () { var t, i, h, r, s, e, n, o, a, f = this.h0, u = this.h1, c = this.h2, y = this.h3, l = this.h4, d = this.h5, A = this.h6, w = this.h7, b = this.blocks; for (t = 16; t < 64; ++t)i = ((s = b[t - 15]) >>> 7 | s << 25) ^ (s >>> 18 | s << 14) ^ s >>> 3, h = ((s = b[t - 2]) >>> 17 | s << 15) ^ (s >>> 19 | s << 13) ^ s >>> 10, b[t] = b[t - 16] + i + b[t - 7] + h << 0; for (a = u & c, t = 0; t < 64; t += 4)this.first ? (this.is224 ? (e = 300032, w = (s = b[0] - 1413257819) - 150054599 << 0, y = s + 24177077 << 0) : (e = 704751109, w = (s = b[0] - 210244248) - 1521486534 << 0, y = s + 143694565 << 0), this.first = !1) : (i = (f >>> 2 | f << 30) ^ (f >>> 13 | f << 19) ^ (f >>> 22 | f << 10), r = (e = f & u) ^ f & c ^ a, w = y + (s = w + (h = (l >>> 6 | l << 26) ^ (l >>> 11 | l << 21) ^ (l >>> 25 | l << 7)) + (l & d ^ ~l & A) + p[t] + b[t]) << 0, y = s + (i + r) << 0), i = (y >>> 2 | y << 30) ^ (y >>> 13 | y << 19) ^ (y >>> 22 | y << 10), r = (n = y & f) ^ y & u ^ e, A = c + (s = A + (h = (w >>> 6 | w << 26) ^ (w >>> 11 | w << 21) ^ (w >>> 25 | w << 7)) + (w & l ^ ~w & d) + p[t + 1] + b[t + 1]) << 0, i = ((c = s + (i + r) << 0) >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10), r = (o = c & y) ^ c & f ^ n, d = u + (s = d + (h = (A >>> 6 | A << 26) ^ (A >>> 11 | A << 21) ^ (A >>> 25 | A << 7)) + (A & w ^ ~A & l) + p[t + 2] + b[t + 2]) << 0, i = ((u = s + (i + r) << 0) >>> 2 | u << 30) ^ (u >>> 13 | u << 19) ^ (u >>> 22 | u << 10), r = (a = u & c) ^ u & y ^ o, l = f + (s = l + (h = (d >>> 6 | d << 26) ^ (d >>> 11 | d << 21) ^ (d >>> 25 | d << 7)) + (d & A ^ ~d & w) + p[t + 3] + b[t + 3]) << 0, f = s + (i + r) << 0; this.h0 = this.h0 + f << 0, this.h1 = this.h1 + u << 0, this.h2 = this.h2 + c << 0, this.h3 = this.h3 + y << 0, this.h4 = this.h4 + l << 0, this.h5 = this.h5 + d << 0, this.h6 = this.h6 + A << 0, this.h7 = this.h7 + w << 0 }, t.prototype.hex = function () { this.finalize(); var t = this.h0, i = this.h1, h = this.h2, r = this.h3, s = this.h4, e = this.h5, n = this.h6, o = this.h7, a = u[t >> 28 & 15] + u[t >> 24 & 15] + u[t >> 20 & 15] + u[t >> 16 & 15] + u[t >> 12 & 15] + u[t >> 8 & 15] + u[t >> 4 & 15] + u[15 & t] + u[i >> 28 & 15] + u[i >> 24 & 15] + u[i >> 20 & 15] + u[i >> 16 & 15] + u[i >> 12 & 15] + u[i >> 8 & 15] + u[i >> 4 & 15] + u[15 & i] + u[h >> 28 & 15] + u[h >> 24 & 15] + u[h >> 20 & 15] + u[h >> 16 & 15] + u[h >> 12 & 15] + u[h >> 8 & 15] + u[h >> 4 & 15] + u[15 & h] + u[r >> 28 & 15] + u[r >> 24 & 15] + u[r >> 20 & 15] + u[r >> 16 & 15] + u[r >> 12 & 15] + u[r >> 8 & 15] + u[r >> 4 & 15] + u[15 & r] + u[s >> 28 & 15] + u[s >> 24 & 15] + u[s >> 20 & 15] + u[s >> 16 & 15] + u[s >> 12 & 15] + u[s >> 8 & 15] + u[s >> 4 & 15] + u[15 & s] + u[e >> 28 & 15] + u[e >> 24 & 15] + u[e >> 20 & 15] + u[e >> 16 & 15] + u[e >> 12 & 15] + u[e >> 8 & 15] + u[e >> 4 & 15] + u[15 & e] + u[n >> 28 & 15] + u[n >> 24 & 15] + u[n >> 20 & 15] + u[n >> 16 & 15] + u[n >> 12 & 15] + u[n >> 8 & 15] + u[n >> 4 & 15] + u[15 & n]; return this.is224 || (a += u[o >> 28 & 15] + u[o >> 24 & 15] + u[o >> 20 & 15] + u[o >> 16 & 15] + u[o >> 12 & 15] + u[o >> 8 & 15] + u[o >> 4 & 15] + u[15 & o]), a }, t.prototype.toString = t.prototype.hex, t.prototype.digest = function () { this.finalize(); var t = this.h0, i = this.h1, h = this.h2, r = this.h3, s = this.h4, e = this.h5, n = this.h6, o = this.h7, a = [t >> 24 & 255, t >> 16 & 255, t >> 8 & 255, 255 & t, i >> 24 & 255, i >> 16 & 255, i >> 8 & 255, 255 & i, h >> 24 & 255, h >> 16 & 255, h >> 8 & 255, 255 & h, r >> 24 & 255, r >> 16 & 255, r >> 8 & 255, 255 & r, s >> 24 & 255, s >> 16 & 255, s >> 8 & 255, 255 & s, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e, n >> 24 & 255, n >> 16 & 255, n >> 8 & 255, 255 & n]; return this.is224 || a.push(o >> 24 & 255, o >> 16 & 255, o >> 8 & 255, 255 & o), a }, t.prototype.array = t.prototype.digest, t.prototype.arrayBuffer = function () { this.finalize(); var t = new ArrayBuffer(this.is224 ? 28 : 32), i = new DataView(t); return i.setUint32(0, this.h0), i.setUint32(4, this.h1), i.setUint32(8, this.h2), i.setUint32(12, this.h3), i.setUint32(16, this.h4), i.setUint32(20, this.h5), i.setUint32(24, this.h6), this.is224 || i.setUint32(28, this.h7), t }, i.prototype = new t, i.prototype.finalize = function () { if (t.prototype.finalize.call(this), this.inner) { this.inner = !1; var i = this.array(); t.call(this, this.is224, this.sharedMemory), this.update(this.oKeyPad), this.update(i), t.prototype.finalize.call(this) } }; var B = w(); B.sha256 = B, B.sha224 = w(!0), B.sha256.hmac = _(), B.sha224.hmac = _(!0), o ? module.exports = B : (s.sha256 = B.sha256, s.sha224 = B.sha224, a && define(function () { return B })) }(); - - /** - * [base64-js]{@link https://github.com/beatgammit/base64-js} - * - * @version v1.3.0 - * @author Kirill, Fomichev - * @copyright Kirill, Fomichev 2014 - * @license MIT - */ - (function (r) { if (typeof exports === "object" && typeof module !== "undefined") { module.exports = r() } else if (typeof define === "function" && define.amd) { define([], r) } else { var e; if (typeof window !== "undefined") { e = window } else if (typeof global !== "undefined") { e = global } else if (typeof self !== "undefined") { e = self } else { e = this } e.base64js = r() } })(function () { var r, e, n; return function () { function r(e, n, t) { function o(f, i) { if (!n[f]) { if (!e[f]) { var u = "function" == typeof require && require; if (!i && u) return u(f, !0); if (a) return a(f, !0); var v = new Error("Cannot find module '" + f + "'"); throw v.code = "MODULE_NOT_FOUND", v } var d = n[f] = { exports: {} }; e[f][0].call(d.exports, function (r) { var n = e[f][1][r]; return o(n || r) }, d, d.exports, r, e, n, t) } return n[f].exports } for (var a = "function" == typeof require && require, f = 0; f < t.length; f++)o(t[f]); return o } return r }()({ "/": [function (r, e, n) { "use strict"; n.byteLength = d; n.toByteArray = h; n.fromByteArray = p; var t = []; var o = []; var a = typeof Uint8Array !== "undefined" ? Uint8Array : Array; var f = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; for (var i = 0, u = f.length; i < u; ++i) { t[i] = f[i]; o[f.charCodeAt(i)] = i } o["-".charCodeAt(0)] = 62; o["_".charCodeAt(0)] = 63; function v(r) { var e = r.length; if (e % 4 > 0) { throw new Error("Invalid string. Length must be a multiple of 4") } var n = r.indexOf("="); if (n === -1) n = e; var t = n === e ? 0 : 4 - n % 4; return [n, t] } function d(r) { var e = v(r); var n = e[0]; var t = e[1]; return (n + t) * 3 / 4 - t } function c(r, e, n) { return (e + n) * 3 / 4 - n } function h(r) { var e; var n = v(r); var t = n[0]; var f = n[1]; var i = new a(c(r, t, f)); var u = 0; var d = f > 0 ? t - 4 : t; for (var h = 0; h < d; h += 4) { e = o[r.charCodeAt(h)] << 18 | o[r.charCodeAt(h + 1)] << 12 | o[r.charCodeAt(h + 2)] << 6 | o[r.charCodeAt(h + 3)]; i[u++] = e >> 16 & 255; i[u++] = e >> 8 & 255; i[u++] = e & 255 } if (f === 2) { e = o[r.charCodeAt(h)] << 2 | o[r.charCodeAt(h + 1)] >> 4; i[u++] = e & 255 } if (f === 1) { e = o[r.charCodeAt(h)] << 10 | o[r.charCodeAt(h + 1)] << 4 | o[r.charCodeAt(h + 2)] >> 2; i[u++] = e >> 8 & 255; i[u++] = e & 255 } return i } function s(r) { return t[r >> 18 & 63] + t[r >> 12 & 63] + t[r >> 6 & 63] + t[r & 63] } function l(r, e, n) { var t; var o = []; for (var a = e; a < n; a += 3) { t = (r[a] << 16 & 16711680) + (r[a + 1] << 8 & 65280) + (r[a + 2] & 255); o.push(s(t)) } return o.join("") } function p(r) { var e; var n = r.length; var o = n % 3; var a = []; var f = 16383; for (var i = 0, u = n - o; i < u; i += f) { a.push(l(r, i, i + f > u ? u : i + f)) } if (o === 1) { e = r[n - 1]; a.push(t[e >> 2] + t[e << 4 & 63] + "==") } else if (o === 2) { e = (r[n - 2] << 8) + r[n - 1]; a.push(t[e >> 10] + t[e >> 4 & 63] + t[e << 2 & 63] + "=") } return a.join("") } }, {}] }, {}, [])("/") }); - - /** - * [promise-polyfill]{@link https://github.com/taylorhakes/promise-polyfill} - * - * @version v8.1.3 - * @author Hakes, Taylor - * @copyright Hakes, Taylor 2014 - * @license MIT - */ - !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(e){return!(!e||"undefined"==typeof e.length)}function t(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],c(e,this)}function r(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(r){return void f(n.promise,r)}i(n.promise,o)}else(1===e._state?i:f)(n.promise,e._value)})):e._deferreds.push(n)}function i(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof o)return e._state=3,e._value=n,void u(e);if("function"==typeof t)return void c(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,u(e)}catch(r){f(e,r)}}function f(e,n){e._state=2,e._value=n,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;t>n;n++)r(e,e._deferreds[n]);e._deferreds=null}function c(e,n){var t=!1;try{e(function(e){t||(t=!0,i(n,e))},function(e){t||(t=!0,f(n,e))})}catch(o){if(t)return;t=!0,f(n,o)}}var a=setTimeout;o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var o=new this.constructor(t);return r(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,n,o)),o},o.prototype["finally"]=e,o.all=function(e){return new o(function(t,o){function r(e,n){try{if(n&&("object"==typeof n||"function"==typeof n)){var u=n.then;if("function"==typeof u)return void u.call(n,function(n){r(e,n)},o)}i[e]=n,0==--f&&t(i)}catch(c){o(c)}}if(!n(e))return o(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(t,r){if(!n(e))return r(new TypeError("Promise.race accepts an array"));for(var i=0,f=e.length;f>i;i++)o.resolve(e[i]).then(t,r)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=o}); - - var Keycloak = factory( root["sha256"], root["base64js"] ); - root["Keycloak"] = Keycloak; - - if ( typeof define === "function" && define.amd ) { - define( "keycloak", [], function () { return Keycloak; } ); - } - } -})(window, function (sha256_imported, base64js_imported) { - if (typeof Promise === 'undefined') { - throw Error('Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill.'); - } - - var loggedPromiseDeprecation = false; - - function logPromiseDeprecation() { - if (!loggedPromiseDeprecation) { - loggedPromiseDeprecation = true; - console.warn('[KEYCLOAK] Usage of legacy style promise methods such as `.error()` and `.success()` has been deprecated and support will be removed in future versions. Use standard style promise methods such as `.then() and `.catch()` instead.'); - } - } - - function Keycloak (config) { - if (!(this instanceof Keycloak)) { - return new Keycloak(config); - } - - var kc = this; - var adapter; - var refreshQueue = []; - var callbackStorage; - - var loginIframe = { - enable: true, - callbackList: [], - interval: 5 - }; - - var scripts = document.getElementsByTagName('script'); - for (var i = 0; i < scripts.length; i++) { - if ((scripts[i].src.indexOf('keycloak.js') !== -1 || scripts[i].src.indexOf('keycloak.min.js') !== -1) && scripts[i].src.indexOf('version=') !== -1) { - kc.iframeVersion = scripts[i].src.substring(scripts[i].src.indexOf('version=') + 8).split('&')[0]; - } - } - - var useNonce = true; - var logInfo = createLogger(console.info); - var logWarn = createLogger(console.warn); - - kc.init = function (initOptions) { - kc.authenticated = false; - - callbackStorage = createCallbackStorage(); - var adapters = ['default', 'cordova', 'cordova-native']; - - if (initOptions && adapters.indexOf(initOptions.adapter) > -1) { - adapter = loadAdapter(initOptions.adapter); - } else if (initOptions && typeof initOptions.adapter === "object") { - adapter = initOptions.adapter; - } else { - if (window.Cordova || window.cordova) { - adapter = loadAdapter('cordova'); - } else { - adapter = loadAdapter(); - } - } - - if (initOptions) { - if (typeof initOptions.useNonce !== 'undefined') { - useNonce = initOptions.useNonce; - } - - if (typeof initOptions.checkLoginIframe !== 'undefined') { - loginIframe.enable = initOptions.checkLoginIframe; - } - - if (initOptions.checkLoginIframeInterval) { - loginIframe.interval = initOptions.checkLoginIframeInterval; - } - - if (initOptions.onLoad === 'login-required') { - kc.loginRequired = true; - } - - if (initOptions.responseMode) { - if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') { - kc.responseMode = initOptions.responseMode; - } else { - throw 'Invalid value for responseMode'; - } - } - - if (initOptions.flow) { - switch (initOptions.flow) { - case 'standard': - kc.responseType = 'code'; - break; - case 'implicit': - kc.responseType = 'id_token token'; - break; - case 'hybrid': - kc.responseType = 'code id_token token'; - break; - default: - throw 'Invalid value for flow'; - } - kc.flow = initOptions.flow; - } - - if (initOptions.timeSkew != null) { - kc.timeSkew = initOptions.timeSkew; - } - - if(initOptions.redirectUri) { - kc.redirectUri = initOptions.redirectUri; - } - - if (initOptions.silentCheckSsoRedirectUri) { - kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri; - } - - if (typeof initOptions.silentCheckSsoFallback === 'boolean') { - kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback; - } else { - kc.silentCheckSsoFallback = true; - } - - if (initOptions.pkceMethod) { - if (initOptions.pkceMethod !== "S256") { - throw 'Invalid value for pkceMethod'; - } - kc.pkceMethod = initOptions.pkceMethod; - } - - if (typeof initOptions.enableLogging === 'boolean') { - kc.enableLogging = initOptions.enableLogging; - } else { - kc.enableLogging = false; - } - - if (typeof initOptions.scope === 'string') { - kc.scope = initOptions.scope; - } - - if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) { - kc.messageReceiveTimeout = initOptions.messageReceiveTimeout; - } else { - kc.messageReceiveTimeout = 10000; - } - } - - if (!kc.responseMode) { - kc.responseMode = 'fragment'; - } - if (!kc.responseType) { - kc.responseType = 'code'; - kc.flow = 'standard'; - } - - var promise = createPromise(); - - var initPromise = createPromise(); - initPromise.promise.then(function() { - kc.onReady && kc.onReady(kc.authenticated); - promise.setSuccess(kc.authenticated); - }).catch(function(error) { - promise.setError(error); - }); - - var configPromise = loadConfig(config); - - function onLoad() { - var doLogin = function(prompt) { - if (!prompt) { - options.prompt = 'none'; - } - - kc.login(options).then(function () { - initPromise.setSuccess(); - }).catch(function (error) { - initPromise.setError(error); - }); - } - - var checkSsoSilently = function() { - var ifrm = document.createElement("iframe"); - var src = kc.createLoginUrl({prompt: 'none', redirectUri: kc.silentCheckSsoRedirectUri}); - ifrm.setAttribute("src", src); - ifrm.setAttribute("title", "keycloak-silent-check-sso"); - ifrm.style.display = "none"; - document.body.appendChild(ifrm); - - var messageCallback = function(event) { - if (event.origin !== window.location.origin || ifrm.contentWindow !== event.source) { - return; - } - - var oauth = parseCallback(event.data); - processCallback(oauth, initPromise); - - document.body.removeChild(ifrm); - window.removeEventListener("message", messageCallback); - }; - - window.addEventListener("message", messageCallback); - }; - - var options = {}; - switch (initOptions.onLoad) { - case 'check-sso': - if (loginIframe.enable) { - setupCheckLoginIframe().then(function() { - checkLoginIframe().then(function (unchanged) { - if (!unchanged) { - kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false); - } else { - initPromise.setSuccess(); - } - }).catch(function (error) { - initPromise.setError(error); - }); - }); - } else { - kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false); - } - break; - case 'login-required': - doLogin(true); - break; - default: - throw 'Invalid value for onLoad'; - } - } - - function processInit() { - var callback = parseCallback(window.location.href); - - if (callback) { - window.history.replaceState(window.history.state, null, callback.newUrl); - } - - if (callback && callback.valid) { - return setupCheckLoginIframe().then(function() { - processCallback(callback, initPromise); - }).catch(function (error) { - initPromise.setError(error); - }); - } else if (initOptions) { - if (initOptions.token && initOptions.refreshToken) { - setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken); - - if (loginIframe.enable) { - setupCheckLoginIframe().then(function() { - checkLoginIframe().then(function (unchanged) { - if (unchanged) { - kc.onAuthSuccess && kc.onAuthSuccess(); - initPromise.setSuccess(); - scheduleCheckIframe(); - } else { - initPromise.setSuccess(); - } - }).catch(function (error) { - initPromise.setError(error); - }); - }); - } else { - kc.updateToken(-1).then(function() { - kc.onAuthSuccess && kc.onAuthSuccess(); - initPromise.setSuccess(); - }).catch(function(error) { - kc.onAuthError && kc.onAuthError(); - if (initOptions.onLoad) { - onLoad(); - } else { - initPromise.setError(error); - } - }); - } - } else if (initOptions.onLoad) { - onLoad(); - } else { - initPromise.setSuccess(); - } - } else { - initPromise.setSuccess(); - } - } - - function domReady() { - var promise = createPromise(); - - var checkReadyState = function () { - if (document.readyState === 'interactive' || document.readyState === 'complete') { - document.removeEventListener('readystatechange', checkReadyState); - promise.setSuccess(); - } - } - document.addEventListener('readystatechange', checkReadyState); - - checkReadyState(); // just in case the event was already fired and we missed it (in case the init is done later than at the load time, i.e. it's done from code) - - return promise.promise; - } - - configPromise.then(function () { - domReady() - .then(check3pCookiesSupported) - .then(processInit) - .catch(function (error) { - promise.setError(error); - }); - }); - configPromise.catch(function (error) { - promise.setError(error); - }); - - return promise.promise; - } - - kc.login = function (options) { - return adapter.login(options); - } - - function generateRandomData(len) { - // use web crypto APIs if possible - var array = null; - var crypto = window.crypto || window.msCrypto; - if (crypto && crypto.getRandomValues && window.Uint8Array) { - array = new Uint8Array(len); - crypto.getRandomValues(array); - return array; - } - - // fallback to Math random - array = new Array(len); - for (var j = 0; j < array.length; j++) { - array[j] = Math.floor(256 * Math.random()); - } - return array; - } - - function generateCodeVerifier(len) { - return generateRandomString(len, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'); - } - - function generateRandomString(len, alphabet){ - var randomData = generateRandomData(len); - var chars = new Array(len); - for (var i = 0; i < len; i++) { - chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length); - } - return String.fromCharCode.apply(null, chars); - } - - function generatePkceChallenge(pkceMethod, codeVerifier) { - switch (pkceMethod) { - // The use of the "plain" method is considered insecure and therefore not supported. - case "S256": - // hash codeVerifier, then encode as url-safe base64 without padding - var hashBytes = new Uint8Array(sha256_imported.arrayBuffer(codeVerifier)); - var encodedHash = base64js_imported.fromByteArray(hashBytes) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/\=/g, ''); - return encodedHash; - default: - throw 'Invalid value for pkceMethod'; - } - } - - kc.createLoginUrl = function(options) { - var state = createUUID(); - var nonce = createUUID(); - - var redirectUri = adapter.redirectUri(options); - - var callbackState = { - state: state, - nonce: nonce, - redirectUri: encodeURIComponent(redirectUri) - }; - - if (options && options.prompt) { - callbackState.prompt = options.prompt; - } - - var baseUrl; - if (options && options.action == 'register') { - baseUrl = kc.endpoints.register(); - } else { - baseUrl = kc.endpoints.authorize(); - } - - var scope = options && options.scope || kc.scope; - if (!scope) { - // if scope is not set, default to "openid" - scope = "openid"; - } else if (scope.indexOf("openid") === -1) { - // if openid scope is missing, prefix the given scopes with it - scope = "openid " + scope; - } - - var url = baseUrl - + '?client_id=' + encodeURIComponent(kc.clientId) - + '&redirect_uri=' + encodeURIComponent(redirectUri) - + '&state=' + encodeURIComponent(state) - + '&response_mode=' + encodeURIComponent(kc.responseMode) - + '&response_type=' + encodeURIComponent(kc.responseType) - + '&scope=' + encodeURIComponent(scope); - if (useNonce) { - url = url + '&nonce=' + encodeURIComponent(nonce); - } - - if (options && options.prompt) { - url += '&prompt=' + encodeURIComponent(options.prompt); - } - - if (options && options.maxAge) { - url += '&max_age=' + encodeURIComponent(options.maxAge); - } - - if (options && options.loginHint) { - url += '&login_hint=' + encodeURIComponent(options.loginHint); - } - - if (options && options.idpHint) { - url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint); - } - - if (options && options.action && options.action != 'register') { - url += '&kc_action=' + encodeURIComponent(options.action); - } - - if (options && options.locale) { - url += '&ui_locales=' + encodeURIComponent(options.locale); - } - - if (kc.pkceMethod) { - var codeVerifier = generateCodeVerifier(96); - callbackState.pkceCodeVerifier = codeVerifier; - var pkceChallenge = generatePkceChallenge(kc.pkceMethod, codeVerifier); - url += '&code_challenge=' + pkceChallenge; - url += '&code_challenge_method=' + kc.pkceMethod; - } - - callbackStorage.add(callbackState); - - return url; - } - - kc.logout = function(options) { - return adapter.logout(options); - } - - kc.createLogoutUrl = function(options) { - var url = kc.endpoints.logout() - + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options, false)); - - return url; - } - - kc.register = function (options) { - return adapter.register(options); - } - - kc.createRegisterUrl = function(options) { - if (!options) { - options = {}; - } - options.action = 'register'; - return kc.createLoginUrl(options); - } - - kc.createAccountUrl = function(options) { - var realm = getRealmUrl(); - var url = undefined; - if (typeof realm !== 'undefined') { - url = realm - + '/account' - + '?referrer=' + encodeURIComponent(kc.clientId) - + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options)); - } - return url; - } - - kc.accountManagement = function() { - return adapter.accountManagement(); - } - - kc.hasRealmRole = function (role) { - var access = kc.realmAccess; - return !!access && access.roles.indexOf(role) >= 0; - } - - kc.hasResourceRole = function(role, resource) { - if (!kc.resourceAccess) { - return false; - } - - var access = kc.resourceAccess[resource || kc.clientId]; - return !!access && access.roles.indexOf(role) >= 0; - } - - kc.loadUserProfile = function() { - var url = getRealmUrl() + '/account'; - var req = new XMLHttpRequest(); - req.open('GET', url, true); - req.setRequestHeader('Accept', 'application/json'); - req.setRequestHeader('Authorization', 'bearer ' + kc.token); - - var promise = createPromise(); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200) { - kc.profile = JSON.parse(req.responseText); - promise.setSuccess(kc.profile); - } else { - promise.setError(); - } - } - } - - req.send(); - - return promise.promise; - } - - kc.loadUserInfo = function() { - var url = kc.endpoints.userinfo(); - var req = new XMLHttpRequest(); - req.open('GET', url, true); - req.setRequestHeader('Accept', 'application/json'); - req.setRequestHeader('Authorization', 'bearer ' + kc.token); - - var promise = createPromise(); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200) { - kc.userInfo = JSON.parse(req.responseText); - promise.setSuccess(kc.userInfo); - } else { - promise.setError(); - } - } - } - - req.send(); - - return promise.promise; - } - - kc.isTokenExpired = function(minValidity) { - if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != 'implicit' )) { - throw 'Not authenticated'; - } - - if (kc.timeSkew == null) { - logInfo('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set'); - return true; - } - - var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew; - if (minValidity) { - if (isNaN(minValidity)) { - throw 'Invalid minValidity'; - } - expiresIn -= minValidity; - } - return expiresIn < 0; - } - - kc.updateToken = function(minValidity) { - var promise = createPromise(); - - if (!kc.refreshToken) { - promise.setError(); - return promise.promise; - } - - minValidity = minValidity || 5; - - var exec = function() { - var refreshToken = false; - if (minValidity == -1) { - refreshToken = true; - logInfo('[KEYCLOAK] Refreshing token: forced refresh'); - } else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) { - refreshToken = true; - logInfo('[KEYCLOAK] Refreshing token: token expired'); - } - - if (!refreshToken) { - promise.setSuccess(false); - } else { - var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken; - var url = kc.endpoints.token(); - - refreshQueue.push(promise); - - if (refreshQueue.length == 1) { - var req = new XMLHttpRequest(); - req.open('POST', url, true); - req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - req.withCredentials = true; - - params += '&client_id=' + encodeURIComponent(kc.clientId); - - var timeLocal = new Date().getTime(); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200) { - logInfo('[KEYCLOAK] Token refreshed'); - - timeLocal = (timeLocal + new Date().getTime()) / 2; - - var tokenResponse = JSON.parse(req.responseText); - - setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal); - - kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess(); - for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) { - p.setSuccess(true); - } - } else { - logWarn('[KEYCLOAK] Failed to refresh token'); - - if (req.status == 400) { - kc.clearToken(); - } - - kc.onAuthRefreshError && kc.onAuthRefreshError(); - for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) { - p.setError(true); - } - } - } - }; - - req.send(params); - } - } - } - - if (loginIframe.enable) { - var iframePromise = checkLoginIframe(); - iframePromise.then(function() { - exec(); - }).catch(function(error) { - promise.setError(error); - }); - } else { - exec(); - } - - return promise.promise; - } - - kc.clearToken = function() { - if (kc.token) { - setToken(null, null, null); - kc.onAuthLogout && kc.onAuthLogout(); - if (kc.loginRequired) { - kc.login(); - } - } - } - - function getRealmUrl() { - if (typeof kc.authServerUrl !== 'undefined') { - if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') { - return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm); - } else { - return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm); - } - } else { - return undefined; - } - } - - function getOrigin() { - if (!window.location.origin) { - return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); - } else { - return window.location.origin; - } - } - - function processCallback(oauth, promise) { - var code = oauth.code; - var error = oauth.error; - var prompt = oauth.prompt; - - var timeLocal = new Date().getTime(); - - if (oauth['kc_action_status']) { - kc.onActionUpdate && kc.onActionUpdate(oauth['kc_action_status']); - } - - if (error) { - if (prompt != 'none') { - var errorData = { error: error, error_description: oauth.error_description }; - kc.onAuthError && kc.onAuthError(errorData); - promise && promise.setError(errorData); - } else { - promise && promise.setSuccess(); - } - return; - } else if ((kc.flow != 'standard') && (oauth.access_token || oauth.id_token)) { - authSuccess(oauth.access_token, null, oauth.id_token, true); - } - - if ((kc.flow != 'implicit') && code) { - var params = 'code=' + code + '&grant_type=authorization_code'; - var url = kc.endpoints.token(); - - var req = new XMLHttpRequest(); - req.open('POST', url, true); - req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - - params += '&client_id=' + encodeURIComponent(kc.clientId); - params += '&redirect_uri=' + oauth.redirectUri; - - if (oauth.pkceCodeVerifier) { - params += '&code_verifier=' + oauth.pkceCodeVerifier; - } - - req.withCredentials = true; - - req.onreadystatechange = function() { - if (req.readyState == 4) { - if (req.status == 200) { - - var tokenResponse = JSON.parse(req.responseText); - authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard'); - scheduleCheckIframe(); - } else { - kc.onAuthError && kc.onAuthError(); - promise && promise.setError(); - } - } - }; - - req.send(params); - } - - function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) { - timeLocal = (timeLocal + new Date().getTime()) / 2; - - setToken(accessToken, refreshToken, idToken, timeLocal); - - if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) || - (kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) || - (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) { - - logInfo('[KEYCLOAK] Invalid nonce, clearing token'); - kc.clearToken(); - promise && promise.setError(); - } else { - if (fulfillPromise) { - kc.onAuthSuccess && kc.onAuthSuccess(); - promise && promise.setSuccess(); - } - } - } - - } - - function loadConfig(url) { - var promise = createPromise(); - var configUrl; - - if (!config) { - configUrl = 'keycloak.json'; - } else if (typeof config === 'string') { - configUrl = config; - } - - function setupOidcEndoints(oidcConfiguration) { - if (! oidcConfiguration) { - kc.endpoints = { - authorize: function() { - return getRealmUrl() + '/protocol/openid-connect/auth'; - }, - token: function() { - return getRealmUrl() + '/protocol/openid-connect/token'; - }, - logout: function() { - return getRealmUrl() + '/protocol/openid-connect/logout'; - }, - checkSessionIframe: function() { - var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html'; - if (kc.iframeVersion) { - src = src + '?version=' + kc.iframeVersion; - } - return src; - }, - thirdPartyCookiesIframe: function() { - var src = getRealmUrl() + '/protocol/openid-connect/3p-cookies/step1.html'; - if (kc.iframeVersion) { - src = src + '?version=' + kc.iframeVersion; - } - return src; - }, - register: function() { - return getRealmUrl() + '/protocol/openid-connect/registrations'; - }, - userinfo: function() { - return getRealmUrl() + '/protocol/openid-connect/userinfo'; - } - }; - } else { - kc.endpoints = { - authorize: function() { - return oidcConfiguration.authorization_endpoint; - }, - token: function() { - return oidcConfiguration.token_endpoint; - }, - logout: function() { - if (!oidcConfiguration.end_session_endpoint) { - throw "Not supported by the OIDC server"; - } - return oidcConfiguration.end_session_endpoint; - }, - checkSessionIframe: function() { - if (!oidcConfiguration.check_session_iframe) { - throw "Not supported by the OIDC server"; - } - return oidcConfiguration.check_session_iframe; - }, - register: function() { - throw 'Redirection to "Register user" page not supported in standard OIDC mode'; - }, - userinfo: function() { - if (!oidcConfiguration.userinfo_endpoint) { - throw "Not supported by the OIDC server"; - } - return oidcConfiguration.userinfo_endpoint; - } - } - } - } - - if (configUrl) { - var req = new XMLHttpRequest(); - req.open('GET', configUrl, true); - req.setRequestHeader('Accept', 'application/json'); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200 || fileLoaded(req)) { - var config = JSON.parse(req.responseText); - - kc.authServerUrl = config['auth-server-url']; - kc.realm = config['realm']; - kc.clientId = config['resource']; - setupOidcEndoints(null); - promise.setSuccess(); - } else { - promise.setError(); - } - } - }; - - req.send(); - } else { - if (!config.clientId) { - throw 'clientId missing'; - } - - kc.clientId = config.clientId; - - var oidcProvider = config['oidcProvider']; - if (!oidcProvider) { - if (!config['url']) { - var scripts = document.getElementsByTagName('script'); - for (var i = 0; i < scripts.length; i++) { - if (scripts[i].src.match(/.*keycloak\.js/)) { - config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js')); - break; - } - } - } - if (!config.realm) { - throw 'realm missing'; - } - - kc.authServerUrl = config.url; - kc.realm = config.realm; - setupOidcEndoints(null); - promise.setSuccess(); - } else { - if (typeof oidcProvider === 'string') { - var oidcProviderConfigUrl; - if (oidcProvider.charAt(oidcProvider.length - 1) == '/') { - oidcProviderConfigUrl = oidcProvider + '.well-known/openid-configuration'; - } else { - oidcProviderConfigUrl = oidcProvider + '/.well-known/openid-configuration'; - } - var req = new XMLHttpRequest(); - req.open('GET', oidcProviderConfigUrl, true); - req.setRequestHeader('Accept', 'application/json'); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200 || fileLoaded(req)) { - var oidcProviderConfig = JSON.parse(req.responseText); - setupOidcEndoints(oidcProviderConfig); - promise.setSuccess(); - } else { - promise.setError(); - } - } - }; - - req.send(); - } else { - setupOidcEndoints(oidcProvider); - promise.setSuccess(); - } - } - } - - return promise.promise; - } - - function fileLoaded(xhr) { - return xhr.status == 0 && xhr.responseText && xhr.responseURL.startsWith('file:'); - } - - function setToken(token, refreshToken, idToken, timeLocal) { - if (kc.tokenTimeoutHandle) { - clearTimeout(kc.tokenTimeoutHandle); - kc.tokenTimeoutHandle = null; - } - - if (refreshToken) { - kc.refreshToken = refreshToken; - kc.refreshTokenParsed = decodeToken(refreshToken); - } else { - delete kc.refreshToken; - delete kc.refreshTokenParsed; - } - - if (idToken) { - kc.idToken = idToken; - kc.idTokenParsed = decodeToken(idToken); - } else { - delete kc.idToken; - delete kc.idTokenParsed; - } - - if (token) { - kc.token = token; - kc.tokenParsed = decodeToken(token); - kc.sessionId = kc.tokenParsed.session_state; - kc.authenticated = true; - kc.subject = kc.tokenParsed.sub; - kc.realmAccess = kc.tokenParsed.realm_access; - kc.resourceAccess = kc.tokenParsed.resource_access; - - if (timeLocal) { - kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat; - } - - if (kc.timeSkew != null) { - logInfo('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds'); - - if (kc.onTokenExpired) { - var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000; - logInfo('[KEYCLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s'); - if (expiresIn <= 0) { - kc.onTokenExpired(); - } else { - kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn); - } - } - } - } else { - delete kc.token; - delete kc.tokenParsed; - delete kc.subject; - delete kc.realmAccess; - delete kc.resourceAccess; - - kc.authenticated = false; - } - } - - function decodeToken(str) { - str = str.split('.')[1]; - - str = str.replace(/-/g, '+'); - str = str.replace(/_/g, '/'); - switch (str.length % 4) { - case 0: - break; - case 2: - str += '=='; - break; - case 3: - str += '='; - break; - default: - throw 'Invalid token'; - } - - str = decodeURIComponent(escape(atob(str))); - - str = JSON.parse(str); - return str; - } - - function createUUID() { - var hexDigits = '0123456789abcdef'; - var s = generateRandomString(36, hexDigits).split(""); - s[14] = '4'; - s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); - s[8] = s[13] = s[18] = s[23] = '-'; - var uuid = s.join(''); - return uuid; - } - - function parseCallback(url) { - var oauth = parseCallbackUrl(url); - if (!oauth) { - return; - } - - var oauthState = callbackStorage.get(oauth.state); - - if (oauthState) { - oauth.valid = true; - oauth.redirectUri = oauthState.redirectUri; - oauth.storedNonce = oauthState.nonce; - oauth.prompt = oauthState.prompt; - oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier; - } - - return oauth; - } - - function parseCallbackUrl(url) { - var supportedParams; - switch (kc.flow) { - case 'standard': - supportedParams = ['code', 'state', 'session_state', 'kc_action_status']; - break; - case 'implicit': - supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status']; - break; - case 'hybrid': - supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status']; - break; - } - - supportedParams.push('error'); - supportedParams.push('error_description'); - supportedParams.push('error_uri'); - - var queryIndex = url.indexOf('?'); - var fragmentIndex = url.indexOf('#'); - - var newUrl; - var parsed; - - if (kc.responseMode === 'query' && queryIndex !== -1) { - newUrl = url.substring(0, queryIndex); - parsed = parseCallbackParams(url.substring(queryIndex + 1, fragmentIndex !== -1 ? fragmentIndex : url.length), supportedParams); - if (parsed.paramsString !== '') { - newUrl += '?' + parsed.paramsString; - } - if (fragmentIndex !== -1) { - newUrl += url.substring(fragmentIndex); - } - } else if (kc.responseMode === 'fragment' && fragmentIndex !== -1) { - newUrl = url.substring(0, fragmentIndex); - parsed = parseCallbackParams(url.substring(fragmentIndex + 1), supportedParams); - if (parsed.paramsString !== '') { - newUrl += '#' + parsed.paramsString; - } - } - - if (parsed && parsed.oauthParams) { - if (kc.flow === 'standard' || kc.flow === 'hybrid') { - if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) { - parsed.oauthParams.newUrl = newUrl; - return parsed.oauthParams; - } - } else if (kc.flow === 'implicit') { - if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) { - parsed.oauthParams.newUrl = newUrl; - return parsed.oauthParams; - } - } - } - } - - function parseCallbackParams(paramsString, supportedParams) { - var p = paramsString.split('&'); - var result = { - paramsString: '', - oauthParams: {} - } - for (var i = 0; i < p.length; i++) { - var split = p[i].indexOf("="); - var key = p[i].slice(0, split); - if (supportedParams.indexOf(key) !== -1) { - result.oauthParams[key] = p[i].slice(split + 1); - } else { - if (result.paramsString !== '') { - result.paramsString += '&'; - } - result.paramsString += p[i]; - } - } - return result; - } - - function createPromise() { - // Need to create a native Promise which also preserves the - // interface of the custom promise type previously used by the API - var p = { - setSuccess: function(result) { - p.resolve(result); - }, - - setError: function(result) { - p.reject(result); - } - }; - p.promise = new Promise(function(resolve, reject) { - p.resolve = resolve; - p.reject = reject; - }); - - p.promise.success = function(callback) { - logPromiseDeprecation(); - - this.then(function handleSuccess(value) { - callback(value); - }); - - return this; - } - - p.promise.error = function(callback) { - logPromiseDeprecation(); - - this.catch(function handleError(error) { - callback(error); - }); - - return this; - } - - return p; - } - - // Function to extend existing native Promise with timeout - function applyTimeoutToPromise(promise, timeout, errorMessage) { - var timeoutHandle = null; - var timeoutPromise = new Promise(function (resolve, reject) { - timeoutHandle = setTimeout(function () { - reject({ "error": errorMessage || "Promise is not settled within timeout of " + timeout + "ms" }); - }, timeout); - }); - - return Promise.race([promise, timeoutPromise]).finally(function () { - clearTimeout(timeoutHandle); - }); - } - - function setupCheckLoginIframe() { - var promise = createPromise(); - - if (!loginIframe.enable) { - promise.setSuccess(); - return promise.promise; - } - - if (loginIframe.iframe) { - promise.setSuccess(); - return promise.promise; - } - - var iframe = document.createElement('iframe'); - loginIframe.iframe = iframe; - - iframe.onload = function() { - var authUrl = kc.endpoints.authorize(); - if (authUrl.charAt(0) === '/') { - loginIframe.iframeOrigin = getOrigin(); - } else { - loginIframe.iframeOrigin = authUrl.substring(0, authUrl.indexOf('/', 8)); - } - promise.setSuccess(); - } - - var src = kc.endpoints.checkSessionIframe(); - iframe.setAttribute('src', src ); - iframe.setAttribute('title', 'keycloak-session-iframe' ); - iframe.style.display = 'none'; - document.body.appendChild(iframe); - - var messageCallback = function(event) { - if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) { - return; - } - - if (!(event.data == 'unchanged' || event.data == 'changed' || event.data == 'error')) { - return; - } - - - if (event.data != 'unchanged') { - kc.clearToken(); - } - - var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length); - - for (var i = callbacks.length - 1; i >= 0; --i) { - var promise = callbacks[i]; - if (event.data == 'error') { - promise.setError(); - } else { - promise.setSuccess(event.data == 'unchanged'); - } - } - }; - - window.addEventListener('message', messageCallback, false); - - return promise.promise; - } - - function scheduleCheckIframe() { - if (loginIframe.enable) { - if (kc.token) { - setTimeout(function() { - checkLoginIframe().then(function(unchanged) { - if (unchanged) { - scheduleCheckIframe(); - } - }); - }, loginIframe.interval * 1000); - } - } - } - - function checkLoginIframe() { - var promise = createPromise(); - - if (loginIframe.iframe && loginIframe.iframeOrigin ) { - var msg = kc.clientId + ' ' + (kc.sessionId ? kc.sessionId : ''); - loginIframe.callbackList.push(promise); - var origin = loginIframe.iframeOrigin; - if (loginIframe.callbackList.length == 1) { - loginIframe.iframe.contentWindow.postMessage(msg, origin); - } - } else { - promise.setSuccess(); - } - - return promise.promise; - } - - function check3pCookiesSupported() { - var promise = createPromise(); - - if (loginIframe.enable || kc.silentCheckSsoRedirectUri) { - var iframe = document.createElement('iframe'); - iframe.setAttribute('src', kc.endpoints.thirdPartyCookiesIframe()); - iframe.setAttribute('title', 'keycloak-3p-check-iframe' ); - iframe.style.display = 'none'; - document.body.appendChild(iframe); - - var messageCallback = function(event) { - if (iframe.contentWindow !== event.source) { - return; - } - - if (event.data !== "supported" && event.data !== "unsupported") { - return; - } else if (event.data === "unsupported") { - loginIframe.enable = false; - if (kc.silentCheckSsoFallback) { - kc.silentCheckSsoRedirectUri = false; - } - logWarn("[KEYCLOAK] 3rd party cookies aren't supported by this browser. checkLoginIframe and " + - "silent check-sso are not available.") - } - - document.body.removeChild(iframe); - window.removeEventListener("message", messageCallback); - promise.setSuccess(); - }; - - window.addEventListener('message', messageCallback, false); - } else { - promise.setSuccess(); - } - - return applyTimeoutToPromise(promise.promise, kc.messageReceiveTimeout, "Timeout when waiting for 3rd party check iframe message."); - } - - function loadAdapter(type) { - if (!type || type == 'default') { - return { - login: function(options) { - window.location.replace(kc.createLoginUrl(options)); - return createPromise().promise; - }, - - logout: function(options) { - window.location.replace(kc.createLogoutUrl(options)); - return createPromise().promise; - }, - - register: function(options) { - window.location.replace(kc.createRegisterUrl(options)); - return createPromise().promise; - }, - - accountManagement : function() { - var accountUrl = kc.createAccountUrl(); - if (typeof accountUrl !== 'undefined') { - window.location.href = accountUrl; - } else { - throw "Not supported by the OIDC server"; - } - return createPromise().promise; - }, - - redirectUri: function(options, encodeHash) { - if (arguments.length == 1) { - encodeHash = true; - } - - if (options && options.redirectUri) { - return options.redirectUri; - } else if (kc.redirectUri) { - return kc.redirectUri; - } else { - return location.href; - } - } - }; - } - - if (type == 'cordova') { - loginIframe.enable = false; - var cordovaOpenWindowWrapper = function(loginUrl, target, options) { - if (window.cordova && window.cordova.InAppBrowser) { - // Use inappbrowser for IOS and Android if available - return window.cordova.InAppBrowser.open(loginUrl, target, options); - } else { - return window.open(loginUrl, target, options); - } - }; - - var shallowCloneCordovaOptions = function (userOptions) { - if (userOptions && userOptions.cordovaOptions) { - return Object.keys(userOptions.cordovaOptions).reduce(function (options, optionName) { - options[optionName] = userOptions.cordovaOptions[optionName]; - return options; - }, {}); - } else { - return {}; - } - }; - - var formatCordovaOptions = function (cordovaOptions) { - return Object.keys(cordovaOptions).reduce(function (options, optionName) { - options.push(optionName+"="+cordovaOptions[optionName]); - return options; - }, []).join(","); - }; - - var createCordovaOptions = function (userOptions) { - var cordovaOptions = shallowCloneCordovaOptions(userOptions); - cordovaOptions.location = 'no'; - if (userOptions && userOptions.prompt == 'none') { - cordovaOptions.hidden = 'yes'; - } - return formatCordovaOptions(cordovaOptions); - }; - - return { - login: function(options) { - var promise = createPromise(); - - var cordovaOptions = createCordovaOptions(options); - var loginUrl = kc.createLoginUrl(options); - var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', cordovaOptions); - var completed = false; - - var closed = false; - var closeBrowser = function() { - closed = true; - ref.close(); - }; - - ref.addEventListener('loadstart', function(event) { - if (event.url.indexOf('http://localhost') == 0) { - var callback = parseCallback(event.url); - processCallback(callback, promise); - closeBrowser(); - completed = true; - } - }); - - ref.addEventListener('loaderror', function(event) { - if (!completed) { - if (event.url.indexOf('http://localhost') == 0) { - var callback = parseCallback(event.url); - processCallback(callback, promise); - closeBrowser(); - completed = true; - } else { - promise.setError(); - closeBrowser(); - } - } - }); - - ref.addEventListener('exit', function(event) { - if (!closed) { - promise.setError({ - reason: "closed_by_user" - }); - } - }); - - return promise.promise; - }, - - logout: function(options) { - var promise = createPromise(); - - var logoutUrl = kc.createLogoutUrl(options); - var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes,clearcache=yes'); - - var error; - - ref.addEventListener('loadstart', function(event) { - if (event.url.indexOf('http://localhost') == 0) { - ref.close(); - } - }); - - ref.addEventListener('loaderror', function(event) { - if (event.url.indexOf('http://localhost') == 0) { - ref.close(); - } else { - error = true; - ref.close(); - } - }); - - ref.addEventListener('exit', function(event) { - if (error) { - promise.setError(); - } else { - kc.clearToken(); - promise.setSuccess(); - } - }); - - return promise.promise; - }, - - register : function(options) { - var promise = createPromise(); - var registerUrl = kc.createRegisterUrl(); - var cordovaOptions = createCordovaOptions(options); - var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions); - ref.addEventListener('loadstart', function(event) { - if (event.url.indexOf('http://localhost') == 0) { - ref.close(); - var oauth = parseCallback(event.url); - processCallback(oauth, promise); - } - }); - return promise.promise; - }, - - accountManagement : function() { - var accountUrl = kc.createAccountUrl(); - if (typeof accountUrl !== 'undefined') { - var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no'); - ref.addEventListener('loadstart', function(event) { - if (event.url.indexOf('http://localhost') == 0) { - ref.close(); - } - }); - } else { - throw "Not supported by the OIDC server"; - } - }, - - redirectUri: function(options) { - return 'http://localhost'; - } - } - } - - if (type == 'cordova-native') { - loginIframe.enable = false; - - return { - login: function(options) { - var promise = createPromise(); - var loginUrl = kc.createLoginUrl(options); - - universalLinks.subscribe('keycloak', function(event) { - universalLinks.unsubscribe('keycloak'); - window.cordova.plugins.browsertab.close(); - var oauth = parseCallback(event.url); - processCallback(oauth, promise); - }); - - window.cordova.plugins.browsertab.openUrl(loginUrl); - return promise.promise; - }, - - logout: function(options) { - var promise = createPromise(); - var logoutUrl = kc.createLogoutUrl(options); - - universalLinks.subscribe('keycloak', function(event) { - universalLinks.unsubscribe('keycloak'); - window.cordova.plugins.browsertab.close(); - kc.clearToken(); - promise.setSuccess(); - }); - - window.cordova.plugins.browsertab.openUrl(logoutUrl); - return promise.promise; - }, - - register : function(options) { - var promise = createPromise(); - var registerUrl = kc.createRegisterUrl(options); - universalLinks.subscribe('keycloak' , function(event) { - universalLinks.unsubscribe('keycloak'); - window.cordova.plugins.browsertab.close(); - var oauth = parseCallback(event.url); - processCallback(oauth, promise); - }); - window.cordova.plugins.browsertab.openUrl(registerUrl); - return promise.promise; - - }, - - accountManagement : function() { - var accountUrl = kc.createAccountUrl(); - if (typeof accountUrl !== 'undefined') { - window.cordova.plugins.browsertab.openUrl(accountUrl); - } else { - throw "Not supported by the OIDC server"; - } - }, - - redirectUri: function(options) { - if (options && options.redirectUri) { - return options.redirectUri; - } else if (kc.redirectUri) { - return kc.redirectUri; - } else { - return "http://localhost"; - } - } - } - } - - throw 'invalid adapter type: ' + type; - } - - var LocalStorage = function() { - if (!(this instanceof LocalStorage)) { - return new LocalStorage(); - } - - localStorage.setItem('kc-test', 'test'); - localStorage.removeItem('kc-test'); - - var cs = this; - - function clearExpired() { - var time = new Date().getTime(); - for (var i = 0; i < localStorage.length; i++) { - var key = localStorage.key(i); - if (key && key.indexOf('kc-callback-') == 0) { - var value = localStorage.getItem(key); - if (value) { - try { - var expires = JSON.parse(value).expires; - if (!expires || expires < time) { - localStorage.removeItem(key); - } - } catch (err) { - localStorage.removeItem(key); - } - } - } - } - } - - cs.get = function(state) { - if (!state) { - return; - } - - var key = 'kc-callback-' + state; - var value = localStorage.getItem(key); - if (value) { - localStorage.removeItem(key); - value = JSON.parse(value); - } - - clearExpired(); - return value; - }; - - cs.add = function(state) { - clearExpired(); - - var key = 'kc-callback-' + state.state; - state.expires = new Date().getTime() + (60 * 60 * 1000); - localStorage.setItem(key, JSON.stringify(state)); - }; - }; - - var CookieStorage = function() { - if (!(this instanceof CookieStorage)) { - return new CookieStorage(); - } - - var cs = this; - - cs.get = function(state) { - if (!state) { - return; - } - - var value = getCookie('kc-callback-' + state); - setCookie('kc-callback-' + state, '', cookieExpiration(-100)); - if (value) { - return JSON.parse(value); - } - }; - - cs.add = function(state) { - setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60)); - }; - - cs.removeItem = function(key) { - setCookie(key, '', cookieExpiration(-100)); - }; - - var cookieExpiration = function (minutes) { - var exp = new Date(); - exp.setTime(exp.getTime() + (minutes*60*1000)); - return exp; - }; - - var getCookie = function (key) { - var name = key + '='; - var ca = document.cookie.split(';'); - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) == ' ') { - c = c.substring(1); - } - if (c.indexOf(name) == 0) { - return c.substring(name.length, c.length); - } - } - return ''; - }; - - var setCookie = function (key, value, expirationDate) { - var cookie = key + '=' + value + '; ' - + 'expires=' + expirationDate.toUTCString() + '; '; - document.cookie = cookie; - } - }; - - function createCallbackStorage() { - try { - return new LocalStorage(); - } catch (err) { - } - - return new CookieStorage(); - } - - function createLogger(fn) { - return function() { - if (kc.enableLogging) { - fn.apply(console, Array.prototype.slice.call(arguments)); - } - }; - } - } - - return Keycloak; -}) diff --git a/adapters/oidc/js/tsconfig.json b/adapters/oidc/js/tsconfig.json new file mode 100644 index 0000000000..34cf7dd5c6 --- /dev/null +++ b/adapters/oidc/js/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true + } +} diff --git a/distribution/adapters/js-adapter-npm-zip/assembly.xml b/distribution/adapters/js-adapter-npm-zip/assembly.xml index ac60b3767d..ee91332a6c 100755 --- a/distribution/adapters/js-adapter-npm-zip/assembly.xml +++ b/distribution/adapters/js-adapter-npm-zip/assembly.xml @@ -37,6 +37,7 @@ dist/ **/*.js + **/*.mjs **/*.map **/*.d.ts diff --git a/distribution/adapters/js-adapter-npm-zip/pom.xml b/distribution/adapters/js-adapter-npm-zip/pom.xml index 97ee2d0308..554f230007 100755 --- a/distribution/adapters/js-adapter-npm-zip/pom.xml +++ b/distribution/adapters/js-adapter-npm-zip/pom.xml @@ -53,7 +53,7 @@ org.keycloak keycloak-js-adapter ${project.build.directory}/unpacked/js-adapter - *.js,*.map,*.d.ts + *.js,*.mjs,*.map,*.d.ts **/welcome-content/* diff --git a/distribution/adapters/js-adapter-npm-zip/src/main/resources/package.json b/distribution/adapters/js-adapter-npm-zip/src/main/resources/package.json index fc079f76f0..19ddb0b599 100644 --- a/distribution/adapters/js-adapter-npm-zip/src/main/resources/package.json +++ b/distribution/adapters/js-adapter-npm-zip/src/main/resources/package.json @@ -3,6 +3,7 @@ "version": "${project.version}", "description": "Keycloak Adapter", "main": "dist/keycloak.js", + "module": "dist/keycloak.mjs", "typings": "dist/keycloak.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -22,7 +23,7 @@ "authentication" ], "dependencies": { - "base64-js": "1.3.1", - "js-sha256": "0.9.0" + "base64-js": "^1.5.1", + "js-sha256": "^0.9.0" } } diff --git a/distribution/adapters/js-adapter-zip/assembly.xml b/distribution/adapters/js-adapter-zip/assembly.xml index 01d555b8df..5330d29d85 100755 --- a/distribution/adapters/js-adapter-zip/assembly.xml +++ b/distribution/adapters/js-adapter-zip/assembly.xml @@ -30,6 +30,7 @@ **/*.js + **/*.mjs **/*.map **/*.d.ts **/*.html diff --git a/distribution/adapters/js-adapter-zip/pom.xml b/distribution/adapters/js-adapter-zip/pom.xml index 5329a05852..ad59040c51 100755 --- a/distribution/adapters/js-adapter-zip/pom.xml +++ b/distribution/adapters/js-adapter-zip/pom.xml @@ -53,7 +53,7 @@ org.keycloak keycloak-js-adapter ${project.build.directory}/unpacked/js-adapter - *.js,*.map,*.d.ts + *.js,*.mjs,*.map,*.d.ts **/welcome-content/* diff --git a/pom.xml b/pom.xml index 9a6684889f..2c60d3a730 100644 --- a/pom.xml +++ b/pom.xml @@ -212,6 +212,8 @@ ${project.version} + + v16.13.1 http://keycloak.org diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/theme/ThemeResourceProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/theme/ThemeResourceProviderTest.java index f77355d848..89cb8e2ab7 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/theme/ThemeResourceProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/theme/ThemeResourceProviderTest.java @@ -108,7 +108,7 @@ public class ThemeResourceProviderTest extends AbstractTestRealmKeycloakTest { }, Boolean.class); assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/resources/" + resourcesVersion + "/welcome/keycloak/css/welcome.css", "body {"); - assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/js/keycloak.js", "function(root, factory)"); + assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/js/keycloak.js", "function Keycloak (config)"); // Check no files exists inside "/tmp" directory. We need to skip this test in the rare case when there are thombstone files created by different user if (filesNotExistsInTmp) { diff --git a/themes/pom.xml b/themes/pom.xml index b5d95fd5ca..4d45523c73 100755 --- a/themes/pom.xml +++ b/themes/pom.xml @@ -71,7 +71,7 @@ - v16.13.0 + ${node.version} ${project.basedir}