Strip remaining dependencies from Keycloak JS (#33295)

Closes #33277

Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
Jon Koops 2024-09-26 15:06:32 +02:00 committed by GitHub
parent ccfdf9c251
commit cdfd46f191
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 83 additions and 85 deletions

View file

@ -68,16 +68,9 @@
"authentication"
],
"devDependencies": {
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-inject": "^5.0.5",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.0",
"es6-promise": "^4.2.8",
"rollup": "^4.22.4",
"shx": "^0.3.4"
},
"dependencies": {
"jwt-decode": "^4.0.0"
}
}

View file

@ -1,7 +1,4 @@
import commonjs from "@rollup/plugin-commonjs";
import inject from "@rollup/plugin-inject";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import terser from '@rollup/plugin-terser';
import terser from "@rollup/plugin-terser";
import path from "node:path";
import type { OutputOptions, RollupOptions } from "rollup";
import { defineConfig } from "rollup";
@ -12,18 +9,15 @@ interface DefineOptionsArgs {
amdId: string;
}
const sourceFile = (file: string) => path.join("src", file);
const targetFile = (file: string) => path.join("dist", file);
function defineOptions({
file,
name,
amdId,
}: DefineOptionsArgs): RollupOptions[] {
const sourceDir = "src";
const targetDir = "dist";
const commonOptions = {
input: path.join(sourceDir, `${file}.js`),
plugins: [commonjs(), nodeResolve()],
} satisfies RollupOptions;
const input = sourceFile(`${file}.js`);
const umdOutput: OutputOptions = {
format: "umd",
name,
@ -31,38 +25,31 @@ function defineOptions({
};
return [
// Modern ES module variant, with externalized dependencies.
// Modern ES module variant.
{
...commonOptions,
input,
output: [
{
file: path.join(targetDir, `${file}.mjs`),
file: targetFile(`${file}.mjs`),
},
],
external: ["jwt-decode"],
},
// Legacy Universal Module Definition, or “UMD”, with inlined dependencies.
// Legacy Universal Module Definition, or “UMD”.
{
...commonOptions,
input,
output: [
{
...umdOutput,
file: path.join(targetDir, `${file}.js`),
file: targetFile(`${file}.js`),
},
{
...umdOutput,
file: path.join(targetDir, `${file}.min.js`),
file: targetFile(`${file}.min.js`),
sourcemap: true,
sourcemapExcludeSources: true,
plugins: [terser()],
},
],
plugins: [
...commonOptions.plugins,
inject({
Promise: ["es6-promise/dist/es6-promise.min.js", "Promise"],
}),
],
},
];
}

View file

@ -14,12 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { jwtDecode } from 'jwt-decode';
if (typeof Promise === 'undefined') {
throw Error('Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill.');
}
function Keycloak (config) {
if (!(this instanceof Keycloak)) {
throw new Error("The 'Keycloak' constructor must be invoked with 'new'.")
@ -983,7 +977,7 @@ function Keycloak (config) {
if (refreshToken) {
kc.refreshToken = refreshToken;
kc.refreshTokenParsed = jwtDecode(refreshToken);
kc.refreshTokenParsed = decodeToken(refreshToken);
} else {
delete kc.refreshToken;
delete kc.refreshTokenParsed;
@ -991,7 +985,7 @@ function Keycloak (config) {
if (idToken) {
kc.idToken = idToken;
kc.idTokenParsed = jwtDecode(idToken);
kc.idTokenParsed = decodeToken(idToken);
} else {
delete kc.idToken;
delete kc.idTokenParsed;
@ -999,7 +993,7 @@ function Keycloak (config) {
if (token) {
kc.token = token;
kc.tokenParsed = jwtDecode(token);
kc.tokenParsed = decodeToken(token);
kc.sessionId = kc.tokenParsed.sid;
kc.authenticated = true;
kc.subject = kc.tokenParsed.sub;
@ -1770,3 +1764,71 @@ async function sha256Digest(message) {
const hash = await crypto.subtle.digest("SHA-256", data);
return hash;
}
/**
* @param {string} token
*/
function decodeToken(token) {
const [header, payload] = token.split(".");
if (typeof payload !== "string") {
throw new Error("Unable to decode token, payload not found.");
}
let decoded;
try {
decoded = base64UrlDecode(payload);
} catch (error) {
throw new Error("Unable to decode token, payload is not a valid Base64URL value.", { cause: error });
}
try {
return JSON.parse(decoded);
} catch (error) {
throw new Error("Unable to decode token, payload is not a valid JSON value.", { cause: error });
}
}
/**
* @param {string} input
*/
function base64UrlDecode(input) {
let output = input
.replaceAll("-", "+")
.replaceAll("_", "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw new Error("Input is not of the correct length.");
}
try {
return b64DecodeUnicode(output);
} catch (error) {
return atob(output);
}
}
/**
* @param {string} input
*/
function b64DecodeUnicode(input) {
return decodeURIComponent(atob(input).replace(/(.)/g, (m, p) => {
let code = p.charCodeAt(0).toString(16).toUpperCase();
if (code.length < 2) {
code = "0" + code;
}
return "%" + code;
}));
}

View file

@ -379,29 +379,13 @@ importers:
version: 10.9.2(@swc/core@1.7.22)(@types/node@22.7.2)(typescript@5.6.2)
js/libs/keycloak-js:
dependencies:
jwt-decode:
specifier: ^4.0.0
version: 4.0.0
devDependencies:
'@rollup/plugin-commonjs':
specifier: ^26.0.1
version: 26.0.1(rollup@4.22.4)
'@rollup/plugin-inject':
specifier: ^5.0.5
version: 5.0.5(rollup@4.22.4)
'@rollup/plugin-node-resolve':
specifier: ^15.3.0
version: 15.3.0(rollup@4.22.4)
'@rollup/plugin-terser':
specifier: ^0.4.4
version: 0.4.4(rollup@4.22.4)
'@rollup/plugin-typescript':
specifier: ^12.1.0
version: 12.1.0(rollup@4.22.4)(tslib@2.7.0)(typescript@5.6.2)
es6-promise:
specifier: ^4.2.8
version: 4.2.8
rollup:
specifier: ^4.22.4
version: 4.22.4
@ -1255,15 +1239,6 @@ packages:
rollup:
optional: true
'@rollup/plugin-inject@5.0.5':
resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
'@rollup/plugin-node-resolve@15.3.0':
resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==}
engines: {node: '>=14.0.0'}
@ -2608,9 +2583,6 @@ packages:
resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
engines: {node: '>= 0.4'}
es6-promise@4.2.8:
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
@ -3440,10 +3412,6 @@ packages:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
jwt-decode@4.0.0:
resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==}
engines: {node: '>=18'}
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@ -5803,14 +5771,6 @@ snapshots:
optionalDependencies:
rollup: 4.22.4
'@rollup/plugin-inject@5.0.5(rollup@4.22.4)':
dependencies:
'@rollup/pluginutils': 5.1.0(rollup@4.22.4)
estree-walker: 2.0.2
magic-string: 0.30.11
optionalDependencies:
rollup: 4.22.4
'@rollup/plugin-node-resolve@15.3.0(rollup@4.22.4)':
dependencies:
'@rollup/pluginutils': 5.1.0(rollup@4.22.4)
@ -7316,8 +7276,6 @@ snapshots:
is-date-object: 1.0.5
is-symbol: 1.0.4
es6-promise@4.2.8: {}
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
@ -8241,8 +8199,6 @@ snapshots:
object.assign: 4.1.5
object.values: 1.2.0
jwt-decode@4.0.0: {}
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1