Skip to content
Snippets Groups Projects
Commit 34506174 authored by Behrisch, M. (Michael)'s avatar Behrisch, M. (Michael)
Browse files

feat: :zap: adds keycloak for JWT and auth mgmt

Replaces the custom made auth-backend (auth-gateway)
with its token logic and complexity
with established open-source
FIPS 140-2 compliant authentification solution

does not use auth-gateway anymore for authentification. close: #28
parent c980f62f
No related branches found
No related tags found
1 merge request!28feat: :zap: adds keycloak for JWT and auth mgmt
Pipeline #124123 failed
VITE_BACKEND_URL=api.graphpolaris.com
VITE_STAGING=local
\ No newline at end of file
VITE_STAGING=local
......@@ -2,5 +2,8 @@ interface ImportMeta {
env: {
VITE_BACKEND_URL: string;
VITE_STAGING: string;
VITE_KEYCLOAK_URL: string;
VITE_KEYCLOAK_REALM: string;
VITE_KEYCLOAK_CLIENT: string;
}
}
\ No newline at end of file
import { useEffect, useRef, useState } from 'react';
import GridLayout from 'react-grid-layout';
import Panel from '../components/panels/panel';
import { RawJSONVis } from '@graphpolaris/shared/lib/vis/rawjsonvis/rawjsonvis';
import SemanticSubstrates from '@graphpolaris/shared/lib/vis/semanticsubstrates/semanticsubstrates';
import { Schema } from '@graphpolaris/shared/lib/schema/panel';
import {
Query2BackendQuery,
QueryBuilder,
} from '@graphpolaris/shared/lib/querybuilder';
import {
assignNewGraphQueryResult,
useAppDispatch,
} from '@graphpolaris/shared/lib/data-access/store';
import { Navbar } from '../components/navbar/navbar';
import { VisualizationPanel } from './panels/Visualization';
import {
readInSchemaFromBackend,
useAuthorization,
useAuth,
useAuthorizationCache,
useDatabaseAPI,
useQueryAPI,
useQuerybuilderGraph,
useQuerybuilderGraphology,
useQuerybuilderHash,
useSchemaAPI,
useSessionCache,
useSessionCache
} from '@graphpolaris/shared/lib/data-access';
import LoginScreen from '../components/login/loginScreen';
import { WebSocketHandler } from '@graphpolaris/shared/lib/data-access/socket';
import Broker from '@graphpolaris/shared/lib/data-access/socket/broker';
import {
assignNewGraphQueryResult,
useAppDispatch,
} from '@graphpolaris/shared/lib/data-access/store';
import { GraphQueryResultFromBackend, resetGraphQueryResults } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
import { SchemaFromBackend } from '@graphpolaris/shared/lib/model/backend';
import {
Query2BackendQuery,
QueryBuilder,
} from '@graphpolaris/shared/lib/querybuilder';
import { Schema } from '@graphpolaris/shared/lib/schema/panel';
import { useEffect, useRef } from 'react';
import LoginScreen from '../components/login/loginScreen';
import { Navbar } from '../components/navbar/navbar';
import Panel from '../components/panels/panel';
import { domain } from '../environments/variables';
import { QueryMultiGraphExport } from '@graphpolaris/shared/lib/querybuilder/graph/graphology/utils';
import { GraphQueryResultFromBackend, resetGraphQueryResults } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
import { clearQB } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
import { VisualizationPanel } from './panels/Visualization';
export function App() {
const { AuthorizeFromCache, auth } = useAuthorization(domain);
const isLogin = useAuth();
const auth = useAuthorizationCache()
const api = useDatabaseAPI(domain);
const api_schema = useSchemaAPI(domain);
const api_query = useQueryAPI(domain);
......@@ -46,9 +43,13 @@ export function App() {
const queryHash = useQuerybuilderHash();
const ws = useRef(new WebSocketHandler(domain));
// for testing purposes
// useEffect(() => {
// console.info('Authentification changed', auth)
// }, [auth]);
useEffect(() => {
// Default
AuthorizeFromCache();
Broker.instance().subscribe(
(data: SchemaFromBackend) => dispatch(readInSchemaFromBackend(data)),
'schema_result'
......@@ -77,11 +78,13 @@ export function App() {
useEffect(() => {
// Newly (un)authorized
console.log(auth.authorized);
if (auth.authorized) {
console.info("App is authorized; Getting Datatabases", isLogin);
api.GetAllDatabases({ updateSessionCache: true });
} else {
// TODO clear all data from redux store; Issue id: #31
}
}, [auth.authorized]);
}, [isLogin]);
useEffect(() => {
// New query
......
VITE_KEYCLOAK_URL=https://login.graphpolaris.com/
VITE_KEYCLOAK_REALM=graphpolaris
VITE_KEYCLOAK_CLIENT=web
\ No newline at end of file
......@@ -69,7 +69,7 @@ export const useDatabaseAPI = (domain: string) => {
async function GetAllDatabases(options: GetDatabasesOptions = {}): Promise<Array<string>> {
const { updateSessionCache: updateDatabaseCache = true } = options;
console.log(accessToken);
// console.log(accessToken);
const response = await fetch(`https://${domain}/user/database`, {
method: 'GET',
credentials: 'same-origin',
......
import { useEffect, useState } from 'react';
import { useAppDispatch, useAuthorizationCache } from '../store';
import { dispatch } from 'd3';
import { authorized, unauthorized, updateAccessToken } from '../store/authSlice';
/**
......@@ -155,6 +153,9 @@ export function useAuthorization(domain: string) {
* @returns true is authorization was successful, else returns false
*/
async function AuthorizeFromCache(): Promise<boolean> {
// Attempt to log in with a refresh-token
const authResponse = await getNewAccessToken(domain, auth.accessToken);
......
export * from './authorizationHook';
\ No newline at end of file
export * from './authorizationHook';
export * from './useAuth';
import Keycloak from "keycloak-js";
import { useEffect, useRef, useState } from "react";
import { useAppDispatch } from '../store';
import { authorized } from '../store/authSlice';
export const useAuth = () => {
const keycloak = new Keycloak({
// url: import.meta.env.VITE_KEYCLOAK_URL,
// realm: import.meta.env.VITE_KEYCLOAK_REALM,
// clientId: import.meta.env.VITE_KEYCLOAK_CLIENT,
url: 'https://login.graphpolaris.com',
realm: 'graphpolaris' ,
clientId: 'web',
});
const isRun = useRef(false);
const [isLogin, setLogin] = useState(false);
const dispatch = useAppDispatch();
useEffect(() => {
if (isRun.current) return;
isRun.current = true;
keycloak
.init({
onLoad: 'login-required',
enableLogging : false,
}).then(async (isAuthenticated) => {
// console.log("useAuth useEffect", isAuthenticated, keycloak.idTokenParsed);
setLogin(isAuthenticated);
// just for example here:
// const profile = await getUserProfile();
// console.log("useAuth useEffect profile", profile);
await dispatch(
authorized({
// Info from https://www.keycloak.org/docs/latest/securing_apps/
userID: keycloak.idTokenParsed.preferred_username ?? '',
sessionID: keycloak.idTokenParsed.sid ?? '',
accessToken: keycloak.token ?? '',
authorized: true,
})
);
});
}, []);
const getUserProfile = async () => {
return keycloak.loadUserProfile()
.then(function(profile) {
return profile;
// console.info("user info", JSON.stringify(profile, null, " "))
}).catch(function() {
alert('Failed to load user profile');
});
}
return isLogin;
};
// export useAuth;
......@@ -38,6 +38,7 @@
"graphology-layout-noverlap": "^0.4.2",
"graphology-types": "^0.24.7",
"jspdf": "^2.5.1",
"keycloak-js": "^21.1.1",
"pixi.js": "^7.1.4",
"react-cookie": "^4.1.1",
"react-grid-layout": "^1.3.4",
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment