Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions js/libs/keycloak-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
37 changes: 12 additions & 25 deletions js/libs/keycloak-js/rollup.config.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -12,57 +9,47 @@ 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,
amd: { id: amdId },
};

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"],
}),
],
},
];
}
Expand Down
80 changes: 71 additions & 9 deletions js/libs/keycloak-js/src/keycloak.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'.")
Expand Down Expand Up @@ -983,23 +977,23 @@ function Keycloak (config) {

if (refreshToken) {
kc.refreshToken = refreshToken;
kc.refreshTokenParsed = jwtDecode(refreshToken);
kc.refreshTokenParsed = decodeToken(refreshToken);
} else {
delete kc.refreshToken;
delete kc.refreshTokenParsed;
}

if (idToken) {
kc.idToken = idToken;
kc.idTokenParsed = jwtDecode(idToken);
kc.idTokenParsed = decodeToken(idToken);
} else {
delete kc.idToken;
delete kc.idTokenParsed;
}

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;
Expand Down Expand Up @@ -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;
}));
}
44 changes: 0 additions & 44 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.