mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
First attempt at DECC Integration
This commit is contained in:
parent
f5d41c645c
commit
c9e0f573ee
@ -188,6 +188,8 @@
|
||||
"immer": "^7.0.5",
|
||||
"js-yaml": "^3.14.0",
|
||||
"jsonpath": "^1.0.2",
|
||||
"jwt-decode": "^3.0.0-beta.2",
|
||||
"keycloak-js": "^10.0.2",
|
||||
"lodash": "^4.17.15",
|
||||
"mac-ca": "^1.0.4",
|
||||
"marked": "^1.1.0",
|
||||
@ -240,6 +242,7 @@
|
||||
"@types/hoist-non-react-statics": "^3.3.1",
|
||||
"@types/html-webpack-plugin": "^3.2.3",
|
||||
"@types/jest": "^25.2.3",
|
||||
"@types/jwt-decode": "^2.2.1",
|
||||
"@types/material-ui": "^0.21.7",
|
||||
"@types/md5-file": "^4.0.2",
|
||||
"@types/mini-css-extract-plugin": "^0.9.1",
|
||||
|
||||
@ -13,6 +13,16 @@ function getDefaultRequestOpts(): Partial<request.Options> {
|
||||
}
|
||||
}
|
||||
|
||||
// export function globalRequestOpts(requestOpts: request.Options ) {
|
||||
// const userPrefs = userStore.getPreferences()
|
||||
// if (userPrefs.httpsProxy) {
|
||||
// requestOpts.proxy = userPrefs.httpsProxy
|
||||
// }
|
||||
// requestOpts.rejectUnauthorized = !userPrefs.allowUntrustedCAs;
|
||||
|
||||
// return requestOpts
|
||||
// }
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
@ -10,12 +10,15 @@ import { kubeConfigDefaultPath, loadConfig } from "./kube-helpers";
|
||||
import { tracker } from "./tracker";
|
||||
import logger from "../main/logger";
|
||||
import path from 'path';
|
||||
import jwt_decode from "jwt-decode";
|
||||
import { List } from "material-ui";
|
||||
|
||||
export interface UserStoreModel {
|
||||
kubeConfigPath: string;
|
||||
lastSeenAppVersion: string;
|
||||
seenContexts: string[];
|
||||
preferences: UserPreferences;
|
||||
token: Token;
|
||||
}
|
||||
|
||||
export interface UserPreferences {
|
||||
@ -29,6 +32,48 @@ export interface UserPreferences {
|
||||
kubectlBinariesPath?: string;
|
||||
}
|
||||
|
||||
export interface Token {
|
||||
preferredUserName?: string,
|
||||
token?: string;
|
||||
tokenValidTill?: number;
|
||||
refreshToken?: string;
|
||||
refreshTokenValidTill?: number;
|
||||
}
|
||||
|
||||
interface IDToken {
|
||||
jti: string,
|
||||
exp: number,
|
||||
nbf: number,
|
||||
iat: number,
|
||||
iss: string,
|
||||
aud: string,
|
||||
sub: string,
|
||||
typ: string,
|
||||
azp: string,
|
||||
auth_time: number,
|
||||
session_state: string,
|
||||
acr: string,
|
||||
iam_roles: string[],
|
||||
email_verified: boolean,
|
||||
preferred_username: string
|
||||
}
|
||||
|
||||
interface RefreshToken {
|
||||
jti: string,
|
||||
exp: number,
|
||||
nbf: number,
|
||||
iat: number,
|
||||
iss: string,
|
||||
aud: string,
|
||||
sub: string,
|
||||
typ: string,
|
||||
azp: string,
|
||||
auth_time: number,
|
||||
session_state: string,
|
||||
realm_access: Array<string[]>,
|
||||
scope: string
|
||||
}
|
||||
|
||||
export class UserStore extends BaseStore<UserStoreModel> {
|
||||
static readonly defaultTheme: ThemeId = "kontena-dark"
|
||||
|
||||
@ -63,6 +108,11 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
kubectlBinariesPath: ""
|
||||
};
|
||||
|
||||
@observable token: Token = {
|
||||
token: "",
|
||||
refreshToken: ""
|
||||
}
|
||||
|
||||
get isNewVersion() {
|
||||
return semver.gt(getAppVersion(), this.lastSeenAppVersion);
|
||||
}
|
||||
@ -114,9 +164,59 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
return path.join((app || remote.app).getPath("userData"), "binaries")
|
||||
}
|
||||
|
||||
getTokenDetails(): Token {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
decodeToken(token: string) {
|
||||
if (token.length > 0) {
|
||||
return jwt_decode<IDToken>(token);
|
||||
}
|
||||
}
|
||||
|
||||
decodeRefreshToken(refreshToken: string) {
|
||||
if (refreshToken.length > 0) {
|
||||
return jwt_decode<RefreshToken>(refreshToken);
|
||||
}
|
||||
}
|
||||
|
||||
getIDTokenIAMPermissions(): string[] {
|
||||
let tokenDecoded = this.decodeToken(this.token.token);
|
||||
const userRoles = tokenDecoded.iam_roles || [];
|
||||
return userRoles
|
||||
}
|
||||
|
||||
isTokenExpired(validTill: number): boolean {
|
||||
// Create a current UnixTime style date in ms
|
||||
const timeNow = Date.now();
|
||||
if ((new Date(validTill * 1000).getMinutes() - new Date().getMinutes()) / 1000 / 60 < 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@action
|
||||
setTokenDetails(token: string, refreshToken: string) {
|
||||
let tokenDecoded = this.decodeToken(token);
|
||||
let refreshTokenDecoded = this.decodeToken(refreshToken);
|
||||
|
||||
this.token.token = token;
|
||||
this.token.refreshToken = refreshToken;
|
||||
this.token.preferredUserName = tokenDecoded.preferred_username;
|
||||
|
||||
// Create a current UnixTime style date in secs
|
||||
const timeNow = Math.round(Date.now() / 1000);
|
||||
this.token.tokenValidTill = timeNow + tokenDecoded.exp;
|
||||
this.token.refreshTokenValidTill = timeNow + refreshTokenDecoded.exp;
|
||||
|
||||
console.info('The saved token object is: ' + JSON.stringify(this.token));
|
||||
|
||||
console.info('Check if token date is expired: ' + this.isTokenExpired(this.token.tokenValidTill));
|
||||
}
|
||||
|
||||
@action
|
||||
protected async fromStore(data: Partial<UserStoreModel> = {}) {
|
||||
const { lastSeenAppVersion, seenContexts = [], preferences, kubeConfigPath } = data
|
||||
const { lastSeenAppVersion, seenContexts = [], preferences, kubeConfigPath, token } = data
|
||||
if (lastSeenAppVersion) {
|
||||
this.lastSeenAppVersion = lastSeenAppVersion;
|
||||
}
|
||||
@ -125,6 +225,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
}
|
||||
this.seenContexts.replace(seenContexts);
|
||||
Object.assign(this.preferences, preferences);
|
||||
Object.assign(this.token, token);
|
||||
}
|
||||
|
||||
toJSON(): UserStoreModel {
|
||||
@ -133,6 +234,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
lastSeenAppVersion: this.lastSeenAppVersion,
|
||||
seenContexts: Array.from(this.seenContexts),
|
||||
preferences: this.preferences,
|
||||
token: this.token,
|
||||
}
|
||||
return toJS(model, {
|
||||
recurseEverything: true,
|
||||
|
||||
@ -10,7 +10,7 @@ jest.mock("electron", () => {
|
||||
}
|
||||
})
|
||||
|
||||
import { UserStore } from "./user-store"
|
||||
import { UserStore, Keycloak } from "./user-store"
|
||||
import { SemVer } from "semver"
|
||||
import electron from "electron"
|
||||
|
||||
@ -73,6 +73,20 @@ describe("user store tests", () => {
|
||||
us.lastSeenAppVersion = (new SemVer(electron.app.getVersion())).inc("major").format();
|
||||
expect(us.isNewVersion).toBe(false);
|
||||
})
|
||||
|
||||
it("allows setting and retrieving keycloak", () => {
|
||||
const us = UserStore.getInstance<UserStore>();
|
||||
|
||||
us.keycloak.idToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MDAzNDc4NzUsImV4cCI6MTYzMTg4Mzg3NSwiYXVkIjoia2FhcyIsInN1YiI6Ijc5ZTEzZGU1LTEwYzgtNGEwNC04ZmEwLWI1OWExYmIzMjIyZiIsImlhbV9yb2xlcyI6WyJtOmthYXNAd3JpdGVyIiwibTprYWFzQHJlYWRlciJdLCJqdGkiOiJlYjNlODY2MC02ZjU0LTRlMTUtOTg3YS01MGIzYjU1MmZmMTIiLCJ0eXAiOiJJRCIsImF6cCI6ImthYXMiLCJlbWFpbF92ZXJpZmllZCI6ImZhbHNlIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYm9iIn0.e3xt3tCNQcxy5flfaQ663KzdBLrMV5gMTt537U4pCo4";
|
||||
expect(us.keycloak.idToken).toBe("1.2.3");
|
||||
|
||||
us.keycloak.expiresIn = "1631883875";
|
||||
expect(us.keycloak.idToken).toBe("1631883875");
|
||||
|
||||
var myKeycloak: {accessToken: "a new dummy access token", idToken: "a new dummy id token", refreshToken: "a new dummy refresg token", expiresIn: "1111", refresExpiresIn: "2222"};
|
||||
us.setTokenDetails(myKeycloak);
|
||||
expect(us.keycloak).toBe(myKeycloak);
|
||||
})
|
||||
})
|
||||
|
||||
describe("migrations", () => {
|
||||
|
||||
46
src/common/utils/k8sTemplates.ts
Normal file
46
src/common/utils/k8sTemplates.ts
Normal file
@ -0,0 +1,46 @@
|
||||
export function kubeconfig({
|
||||
username, clusterName, clientId, idpCertificateAuthorityData, idpIssuerUrl,
|
||||
idToken, refreshToken, server, apiCertificate
|
||||
}) {
|
||||
return {
|
||||
apiVersion: 'v1',
|
||||
clusters: [
|
||||
{
|
||||
name: clusterName,
|
||||
cluster: {
|
||||
'certificate-authority-data': apiCertificate,
|
||||
server
|
||||
}
|
||||
}
|
||||
],
|
||||
contexts: [
|
||||
{
|
||||
context: {
|
||||
cluster: clusterName,
|
||||
user: username
|
||||
},
|
||||
name: `${username}@${clusterName}`
|
||||
}
|
||||
],
|
||||
'current-context': `${username}@${clusterName}`,
|
||||
kind: 'Config',
|
||||
preferences: {},
|
||||
users: [
|
||||
{
|
||||
name: username,
|
||||
user: {
|
||||
'auth-provider': {
|
||||
config: {
|
||||
'client-id': clientId,
|
||||
'id-token': idToken,
|
||||
'idp-certificate-authority-data': idpCertificateAuthorityData,
|
||||
'idp-issuer-url': idpIssuerUrl,
|
||||
'refresh-token': refreshToken
|
||||
},
|
||||
name: 'oidc'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
@ -13,11 +13,19 @@ import { shellSync } from "./shell-sync"
|
||||
import { getFreePort } from "./port"
|
||||
import { mangleProxyEnv } from "./proxy-env"
|
||||
import { registerFileProtocol } from "../common/register-protocol";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { ClusterStore, clusterStore } from "../common/cluster-store"
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
import { tracker } from "../common/tracker";
|
||||
import logger from "./logger"
|
||||
import * as fs from 'fs';
|
||||
import * as http from "http";
|
||||
import * as request from "request-promise-native";
|
||||
import { uniqueId } from "lodash";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { Cluster } from "../main/cluster";
|
||||
import {kubeconfig} from '../common/utils/k8sTemplates';
|
||||
import YAML from 'yaml'
|
||||
|
||||
const workingDir = path.join(app.getPath("appData"), appName);
|
||||
app.setName(appName);
|
||||
@ -28,12 +36,23 @@ if (!process.env.CICD) {
|
||||
let windowManager: WindowManager;
|
||||
let clusterManager: ClusterManager;
|
||||
let proxyServer: LensProxy;
|
||||
//let clusterStore: ClusterStore;
|
||||
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||
}
|
||||
|
||||
const keycloakWinURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:3000/keycloak_index.html`
|
||||
: `file://${__static}/keycloak_index.html`
|
||||
const { ipcMain } = require('electron')
|
||||
|
||||
const ignoredDECCNamespaces = [
|
||||
'kube-system', 'kube-public', 'openstack-provider-system', 'system',
|
||||
'kaas', 'lcm-system', 'istio-system', 'kube-node-lease', 'stacklight'
|
||||
];
|
||||
|
||||
async function main() {
|
||||
await shellSync();
|
||||
logger.info(`🚀 Starting Lens from "${workingDir}"`)
|
||||
@ -73,8 +92,34 @@ async function main() {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
//start renderer with keycloak login page
|
||||
const keycloakServer = http.createServer(function(req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
res.writeHead(200, {"Content-Type": "text/html"});
|
||||
var readSream = fs.createReadStream(__static + '/keycloak_index.html','utf8')
|
||||
readSream.pipe(res);
|
||||
}).listen(3000);
|
||||
|
||||
// create window manager and open app
|
||||
windowManager = new WindowManager(proxyPort);
|
||||
windowManager = new WindowManager(proxyPort, 3000);
|
||||
//windowManager = new WindowManager(3000);
|
||||
|
||||
//open login page in keyloak renderer
|
||||
// if (isDevelopment) {
|
||||
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
// app.commandLine.appendSwitch('allow-insecure-localhost', 'true');
|
||||
// app.commandLine.appendSwitch('ignore-certificate-errors', 'true');
|
||||
// }
|
||||
|
||||
// SSL/TSL: this is the self signed certificate support
|
||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||
// On certificate error we disable default behaviour (stop loading the page)
|
||||
// and we then say "it is all fine - true" to the callback
|
||||
console.log('cert error: ' + error);
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
});
|
||||
|
||||
//windowManager.showMain(keycloakWinURL);
|
||||
}
|
||||
|
||||
app.on("ready", main);
|
||||
@ -85,3 +130,139 @@ app.on("will-quit", async (event) => {
|
||||
if (clusterManager) clusterManager.stop()
|
||||
app.exit();
|
||||
})
|
||||
|
||||
ipcMain.on('keycloak-token', (event, idToken, refreshToken) => {
|
||||
logger.info('test keycloak close main win');
|
||||
userStore.setTokenDetails(idToken, refreshToken);
|
||||
logger.info('saved id token and refreshToken to userStore');
|
||||
|
||||
logger.info('the idToken is: ' + userStore.getTokenDetails().token);
|
||||
|
||||
var parsedToken = userStore.decodeToken (idToken);
|
||||
|
||||
var namespacesUserCanAccess: string[] = workspaceStore.workspacesList;
|
||||
|
||||
// get all namespaces this id has access to
|
||||
const namespaces = {
|
||||
method: 'GET',
|
||||
url: 'http://a09bfce9ea3074e25b8e5e7b1df576fd-1162277427.eu-west-2.elb.amazonaws.com/api/v1/namespaces',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + userStore.getTokenDetails().token
|
||||
},
|
||||
json: true
|
||||
};
|
||||
|
||||
request(namespaces)
|
||||
.then(function(response) {
|
||||
//API call ok....
|
||||
const deccNamespaces = response["items"];
|
||||
// logger.info(JSON.stringify(deccNamespaces));
|
||||
|
||||
deccNamespaces.forEach(function(namespace) {
|
||||
if (!ignoredDECCNamespaces.includes(namespace.metadata.name)) {
|
||||
// console.log("Namespace Name: " + namespace.metadata.name);
|
||||
let ns = namespace.metadata.name;
|
||||
//console.log("parsedToken.iam_roles: ", parsedToken.iam_roles);
|
||||
if (parsedToken.iam_roles.includes(`m:kaas:${ns}@reader`) || parsedToken.iam_roles.includes(`m:kaas:${ns}@writer`)) {
|
||||
// add namespace to workspaceStore if not present
|
||||
console.log(`User: ${parsedToken.preferred_username} has access to namespace: ${ns}`);
|
||||
if (!workspaceStore.getByName(ns)) {
|
||||
workspaceStore.saveWorkspace({id: uuid(), name: ns, description: `DECC Namespace: ${ns}`});
|
||||
console.log(`Added new workspace: ${ns}`);
|
||||
namespacesUserCanAccess.push(ns);
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch(function (err) {
|
||||
// API call failed...
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
// now lets add the clusters for each namespace
|
||||
workspaceStore.workspacesList.forEach(function(ws) {
|
||||
console.log(`Adding clusters for ws: ${ws.name}`);
|
||||
var clusters = {
|
||||
method: 'GET',
|
||||
url: `http://a09bfce9ea3074e25b8e5e7b1df576fd-1162277427.eu-west-2.elb.amazonaws.com/apis/cluster.k8s.io/v1alpha1/namespaces/${ws.name}/clusters`,
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + userStore.getTokenDetails().token
|
||||
},
|
||||
json: true
|
||||
};
|
||||
|
||||
request(clusters)
|
||||
.then(function(response) {
|
||||
//API call ok....
|
||||
const deccClusters = response["items"];
|
||||
deccClusters.forEach(function(deccCluster: object) {
|
||||
// check if cluster is already in the cluster store
|
||||
let clusterPresent = false;
|
||||
clusterStore.getByWorkspaceId(ws.id).forEach(wsCluster => {
|
||||
if (wsCluster.contextName === `${parsedToken.preferred_username}@${deccCluster.metadata.name}`) {
|
||||
clusterPresent = true;
|
||||
}
|
||||
});
|
||||
|
||||
if ("status" in deccCluster && !clusterPresent) {
|
||||
// clusterUCPURL = cluster.status.
|
||||
|
||||
let ucpDashboard = `https://${deccCluster.status.providerStatus.ucpDashboard.split(":", 2).reverse()[0].substring(2)}:443`;
|
||||
console.log (`ucpDashboard: ${ucpDashboard}`);
|
||||
|
||||
const jsConfig = kubeconfig({
|
||||
username: parsedToken.preferred_username,
|
||||
clusterName: deccCluster.metadata.name,
|
||||
clientId: deccCluster.status.providerStatus.oidc.clientId,
|
||||
idpCertificateAuthorityData: deccCluster.status.providerStatus.oidc.certificate,
|
||||
idpIssuerUrl: deccCluster.status.providerStatus.oidc.issuerUrl,
|
||||
server: ucpDashboard,
|
||||
apiCertificate: deccCluster.status.providerStatus.apiServerCertificate,
|
||||
idToken: idToken,
|
||||
refreshToken: refreshToken
|
||||
});
|
||||
|
||||
console.log(`Generated kubeconfig: ${YAML.stringify(jsConfig)}`)
|
||||
|
||||
console.log(`Cluster Name: ${deccCluster.metadata.name}, Cluster UCP Dashboard URL: ${deccCluster.status.providerStatus.ucpDashboard}`)
|
||||
let newCluster = new Cluster({
|
||||
id: uuid(),
|
||||
contextName: `${parsedToken.preferred_username}@${deccCluster.metadata.name}`,
|
||||
preferences: {
|
||||
// icon: "data:;base64,iVBORw0KGgoAAAANSUhEUgAAA1wAAAKoCAYAAABjkf5",
|
||||
clusterName: deccCluster.metadata.name,
|
||||
httpsProxy: undefined,
|
||||
},
|
||||
kubeConfigPath: ClusterStore.embedCustomKubeConfig(deccCluster.metadata.uid, YAML.stringify(jsConfig)),
|
||||
workspace: ws.name,
|
||||
});
|
||||
|
||||
clusterStore.addCluster(newCluster);
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch(function (err: string) {
|
||||
// API call failed...
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
|
||||
//TODO: Use vmURL instead of hardcoded localhost:9080 here
|
||||
// const winURL = process.env.NODE_ENV === 'development'
|
||||
// ? `http://localhost:9080?token=${token}`
|
||||
// : `file://${__dirname}/index.html?token=${token}`
|
||||
|
||||
//TODO: refresh token!
|
||||
windowManager.showMain();
|
||||
});
|
||||
|
||||
ipcMain.on('keycloak-token-update', (event, token) => {
|
||||
logger.error('token refresh receivied:' + token);
|
||||
//TODO: handle refresh token!
|
||||
});
|
||||
|
||||
ipcMain.on('keycloak-logout', (event, data) => {
|
||||
logger.error('logout');
|
||||
windowManager.showKeycloak();
|
||||
});
|
||||
|
||||
@ -12,7 +12,7 @@ export class WindowManager {
|
||||
|
||||
@observable activeClusterId: ClusterId;
|
||||
|
||||
constructor(protected proxyPort: number) {
|
||||
constructor(protected proxyPort: number, protected keycloakPort: number) {
|
||||
// Manage main window size and position with state persistence
|
||||
this.windowState = windowStateKeeper({
|
||||
defaultHeight: 900,
|
||||
@ -35,6 +35,22 @@ export class WindowManager {
|
||||
});
|
||||
this.windowState.manage(this.mainView);
|
||||
|
||||
// handle external links
|
||||
this.mainView.webContents.on("will-navigate", (event, link) => {
|
||||
if (link.startsWith("http://localhost")) {
|
||||
return;
|
||||
}
|
||||
if (link.startsWith("https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com")) {
|
||||
return;
|
||||
}
|
||||
if (link.startsWith("http://a09bfce9ea3074e25b8e5e7b1df576fd-1162277427.eu-west-2.elb.amazonaws.com")) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
shell.openExternal(link);
|
||||
})
|
||||
|
||||
// open external links in default browser (target=_blank, window.open)
|
||||
this.mainView.webContents.on("new-window", (event, url) => {
|
||||
event.preventDefault();
|
||||
@ -47,7 +63,7 @@ export class WindowManager {
|
||||
});
|
||||
|
||||
// load & show app
|
||||
this.showMain();
|
||||
this.showKeycloak();
|
||||
initMenu(this);
|
||||
}
|
||||
|
||||
@ -68,10 +84,10 @@ export class WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
async showMain() {
|
||||
public async showKeycloak() {
|
||||
try {
|
||||
await this.showSplash();
|
||||
await this.mainView.loadURL(`http://localhost:${this.proxyPort}`)
|
||||
await this.mainView.loadURL(`http://localhost:${this.keycloakPort}`)
|
||||
this.mainView.show();
|
||||
this.splashWindow.close();
|
||||
} catch (err) {
|
||||
@ -79,6 +95,17 @@ export class WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
public async showMain() {
|
||||
try {
|
||||
//await this.showSplash();
|
||||
await this.mainView.loadURL(`http://localhost:${this.proxyPort}`)
|
||||
this.mainView.show();
|
||||
//this.splashWindow.close();
|
||||
} catch (err) {
|
||||
dialog.showErrorBox("ERROR!", err.toString())
|
||||
}
|
||||
}
|
||||
|
||||
async showSplash() {
|
||||
if (!this.splashWindow) {
|
||||
this.splashWindow = new BrowserWindow({
|
||||
|
||||
43
static/keycloak_index.html
Normal file
43
static/keycloak_index.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!-- <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com/auth/js/keycloak.js;"> -->
|
||||
|
||||
<script src="https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com/auth/js/keycloak.js"></script>
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
var keycloak = new Keycloak({
|
||||
url: 'https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com/auth',
|
||||
realm: 'iam',
|
||||
clientId: 'kaas'
|
||||
});
|
||||
|
||||
//if param "logout" was passed to this page, logout user!
|
||||
const logoutUser = new URL(location.href).searchParams.get('logout');
|
||||
if(logoutUser){
|
||||
keycloak.init();
|
||||
keycloak.logout({redirectUri: 'http://localhost:3000'});
|
||||
}else{
|
||||
keycloak.init({ flow: 'standard', enableLogging: true, useNonce: false, onLoad: 'login-required', checkLoginIframe: false, redirectUri: 'http://localhost:3000'}).success(function(authenticated) {
|
||||
console.log('success!!');
|
||||
if (authenticated) {
|
||||
console.log("keycloak.token: " + keycloak.token);
|
||||
console.log("keycloak.idToken: " + keycloak.idToken);
|
||||
console.log("keycloak.refreshToken: " + keycloak.refreshToken);
|
||||
|
||||
console.log("keycloak object: "+ JSON.stringify(keycloak));
|
||||
ipcRenderer.send('keycloak-token', keycloak.idToken, keycloak.refreshToken);
|
||||
|
||||
//TODO: check if token refresh is possible here
|
||||
/*
|
||||
setInterval(() => {
|
||||
console.log("interval");
|
||||
keycloak.updateToken(10).error(() => keycloak.logout());
|
||||
console.log(keycloak.token);
|
||||
ipcRenderer.send('keycloak-token-update', keycloak.token);
|
||||
}, 10000);
|
||||
*/
|
||||
}
|
||||
}).error(function(error) {
|
||||
console.log('error: ' + JSON.stringify(error));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
25
yarn.lock
25
yarn.lock
@ -1905,6 +1905,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonpath/-/jsonpath-0.2.0.tgz#13c62db22a34d9c411364fac79fd374d63445aa1"
|
||||
integrity sha512-v7qlPA0VpKUlEdhghbDqRoKMxFB3h3Ch688TApBJ6v+XLDdvWCGLJIYiPKGZnS6MAOie+IorCfNYVHOPIHSWwQ==
|
||||
|
||||
"@types/jwt-decode@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jwt-decode/-/jwt-decode-2.2.1.tgz#afdf5c527fcfccbd4009b5fd02d1e18241f2d2f2"
|
||||
integrity sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A==
|
||||
|
||||
"@types/lodash@^4.14.155":
|
||||
version "4.14.155"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.155.tgz#e2b4514f46a261fd11542e47519c20ebce7bc23a"
|
||||
@ -3042,7 +3047,7 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base64-js@1.3.1, base64-js@^1.0.2:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
@ -7281,6 +7286,11 @@ js-base64@^2.1.8:
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209"
|
||||
integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==
|
||||
|
||||
js-sha256@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
|
||||
integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==
|
||||
|
||||
js-sha3@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||
@ -7505,6 +7515,19 @@ jss@10.2.0, jss@^10.0.3:
|
||||
is-in-browser "^1.1.3"
|
||||
tiny-warning "^1.0.2"
|
||||
|
||||
jwt-decode@^3.0.0-beta.2:
|
||||
version "3.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.0.0-beta.2.tgz#5d928dd0d582caab47b252a5f12ad1721f2f6eef"
|
||||
integrity sha512-AnENY5syz7PzgpTzos9sxkqKTmHU0JeJOXZFHUc41bDyybC2yzZ+1r43ZLhk7+JCwF0yjISPuVK9ZWfA1nCUPA==
|
||||
|
||||
keycloak-js@^10.0.2:
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/keycloak-js/-/keycloak-js-10.0.2.tgz#f0cf5b942627c5221f1466552c40e4624503b77b"
|
||||
integrity sha512-7nkg4Ob1khHGcNbuK36AMndKUEuIQFpNlWU9ygWs7nSBPCI9VZ8dJjjXfKJHm0ewgcqLFGPIJ6bxxRlfcQ6sLg==
|
||||
dependencies:
|
||||
base64-js "1.3.1"
|
||||
js-sha256 "0.9.0"
|
||||
|
||||
keyv@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user