diff --git a/apps/web/package.json b/apps/web/package.json
index 8dd5c441d60f7f287683060569365d39409ec378..c31bb9017f2ea078ef797e79174aa40e8c948b67 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -4,7 +4,8 @@
   "version": "0.0.0",
   "type": "module",
   "scripts": {
-    "dev": "vite",
+    "dev": "vite --host local.graphpolaris.com --port 4200",
+    "dev2": "vite --host local.graphpolaris.com --port 4200",
     "build": "tsc && vite build",
     "preview": "vite preview"
   },
@@ -29,6 +30,7 @@
     "@types/react-dom": "^18.0.11",
     "@types/react-grid-layout": "^1.3.2",
     "@types/styled-components": "^5.1.26",
+    "@vitejs/plugin-basic-ssl": "^1.0.1",
     "@vitejs/plugin-react-swc": "^3.0.0",
     "graphology-types": "^0.24.7",
     "react-is": "^18.2.0",
diff --git a/apps/web/public/assets/icons/ExportIcon.png b/apps/web/public/assets/icons/ExportIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..62976b8a7902bc100cad532959e3d9e0d5fea42c
Binary files /dev/null and b/apps/web/public/assets/icons/ExportIcon.png differ
diff --git a/apps/web/public/assets/login-screen/github.png b/apps/web/public/assets/login-screen/github.png
new file mode 100644
index 0000000000000000000000000000000000000000..55f90676824d4901f6fe7a50ed11f6d4af3d6fef
Binary files /dev/null and b/apps/web/public/assets/login-screen/github.png differ
diff --git a/apps/web/public/assets/login-screen/google.png b/apps/web/public/assets/login-screen/google.png
new file mode 100644
index 0000000000000000000000000000000000000000..f27bb2433042aea5fc34e19fcf90944430ec331b
Binary files /dev/null and b/apps/web/public/assets/login-screen/google.png differ
diff --git a/apps/web/src/app/app.tsx b/apps/web/src/app/app.tsx
index bb7fca8f820d6b54ee66ac325297234873a8f57c..dcdc35b0784678e3a90e1e6f79b796f2fe0a1c2d 100644
--- a/apps/web/src/app/app.tsx
+++ b/apps/web/src/app/app.tsx
@@ -5,47 +5,35 @@ 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 { GetUserInfo } from '@graphpolaris/shared/lib/data-access/api';
+import {
+  GetAllDatabases,
+  GetUserInfo,
+} from '@graphpolaris/shared/lib/data-access/api';
 import { QueryBuilder } from '@graphpolaris/shared/lib/querybuilder';
 import {
   assignNewGraphQueryResult,
   useAppDispatch,
 } from '@graphpolaris/shared/lib/data-access/store';
-import { AuthorizationHandler } from '@graphpolaris/shared/lib/data-access/authorization';
-
-function useIsAuthorized() {
-  const [userAuthorized, setUserAuthorized] = useState(false);
-
-  const authCallback = async () => {
-    setUserAuthorized(true);
-
-    // Print the user that is currently logged in
-    const user = await GetUserInfo();
-    console.log(user);
-  };
-
-  AuthorizationHandler.instance().setCallback(authCallback);
-
-  // Attempt to Authorize the user
-  const authorize = async () => {
-    const authorized = await AuthorizationHandler.instance().Authorize();
-    setUserAuthorized(authorized);
-  };
-
-  useEffect(() => {
-    authorize();
-  }, []);
-
-  return userAuthorized;
-}
+import {
+  AuthorizationHandler,
+  useIsAuthorized,
+} from '@graphpolaris/shared/lib/data-access/authorization';
 
 export function App() {
   const dispatch = useAppDispatch();
   const userIsAuthorized = useIsAuthorized();
 
+  useEffect(() => {
+    if (userIsAuthorized) {
+      GetAllDatabases().then((d) => {
+        console.log(d);
+      });
+    }
+  }, [userIsAuthorized]);
+
   return (
     <>
-      {/* {!userIsAuthorized && <LoginScreen />} */}
+      {!userIsAuthorized && <LoginScreen />}
       <GridLayout
         className="layout"
         cols={10}
diff --git a/apps/web/src/components/navbar/AddDatabaseForm/AddDatabaseFormComponent.tsx b/apps/web/src/components/navbar/AddDatabaseForm/AddDatabaseFormComponent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c4682516870ec05ee2438e538142e626d7147952
--- /dev/null
+++ b/apps/web/src/components/navbar/AddDatabaseForm/AddDatabaseFormComponent.tsx
@@ -0,0 +1,217 @@
+/**
+ * This program has been developed by students from the bachelor Computer Science at
+ * Utrecht University within the Software Project course.
+ * © Copyright Utrecht University (Department of Information and Computing Sciences)
+ */
+
+/* istanbul ignore file */
+/* The comment above was added so the code coverage wouldn't count this file towards code coverage.
+ * We do not test components/renderfunctions/styling files.
+ * See testing plan for more details.*/
+import React from 'react';
+import { ClassNameMap } from '@material-ui/styles';
+import { TextField, Button, WithStyles, withStyles, NativeSelect } from '@material-ui/core';
+import { useStyles } from './AddDatabaseFormUIStylesheet';
+
+/** AddDatabaseFormProps is an interface containing the AuthViewModel. */
+export interface AddDatabaseFormProps extends WithStyles<typeof useStyles> {
+  open: boolean;
+  onClose(): void;
+  onSubmit(
+    username: string,
+    password: string,
+    hostname: string,
+    port: number,
+    databaseName: string,
+    internalDatabase: string,
+    databaseType: string,
+  ): void;
+}
+
+/** AddDatabaseFormState is an interface containing the databasehost information. */
+export interface AddDatabaseFormState {
+  username: string;
+  password: string;
+  hostname: string;
+  port: number;
+  databaseName: string;
+  internalDatabase: string;
+  databaseType: string;
+
+  styles: ClassNameMap;
+}
+
+/** AddDatabaseForm is the View implementation for the connect screen that will be rendered. */
+class AddDatabaseForm extends React.Component<AddDatabaseFormProps, AddDatabaseFormState> {
+  public constructor(props: AddDatabaseFormProps) {
+    super(props);
+
+    this.state = {
+      username: 'root',
+      password: 'DikkeDraak',
+      hostname: 'https://datastrophe.science.uu.nl/',
+      port: 8529,
+      databaseName: 'Tweede Kamer Dataset',
+      internalDatabase: 'TweedeKamer',
+      styles: this.props.classes,
+      databaseType: 'arangodb',
+    };
+  }
+
+  /**
+   * Validates if the port value is numerical. Only then will the state be updated.
+   * @param port The new port value.
+   */
+  private handlePortChanged(port: string): void {
+    if (!isNaN(Number(port))) this.setState({ ...this.state, port: Number(port) });
+  }
+
+  /** Handles the submit button click. Calls the onSubmit in the props with all the fields. */
+  private handleSubmitClicked(): void {
+    this.props.onSubmit(
+      this.state.username,
+      this.state.password,
+      this.state.hostname,
+      this.state.port,
+      this.state.databaseName,
+      this.state.internalDatabase,
+      this.state.databaseType,
+    );
+  }
+
+  public render(): JSX.Element {
+    const {
+      username,
+      password,
+      port,
+      hostname,
+      databaseName,
+      internalDatabase,
+      styles,
+      databaseType,
+    } = this.state;
+
+    return this.props.open ? (
+      <div
+        className={styles.wrapper}
+        onMouseDown={() => {
+          this.props.onClose();
+        }}
+      >
+        <div
+          className={styles.authWrapper}
+          onMouseDown={(e) => {
+            e.stopPropagation();
+          }}
+        >
+          <h1 className={styles.header}>Database Connect</h1>
+          <form
+            className={styles.formWrapper}
+            onSubmit={(event: React.FormEvent) => {
+              event.preventDefault();
+              this.handleSubmitClicked();
+            }}
+          >
+            <div className={styles.loginContainer}>
+              <TextField
+                className={styles.passLabel}
+                label="Database name"
+                type="databaseName"
+                value={databaseName}
+                onChange={(event) =>
+                  this.setState({ ...this.state, databaseName: event.currentTarget.value })
+                }
+                required
+              />
+            </div>
+            <div className={styles.loginContainer}>
+              <NativeSelect
+                className={styles.passLabel}
+                value={databaseType}
+                onChange={(event) => {
+                  this.setState({ ...this.state, databaseType: event.currentTarget.value });
+                }}
+              >
+                <option value="arangodb">arangodb</option>
+                <option value="neo4j">neo4j</option>
+              </NativeSelect>
+            </div>
+            <div className={styles.loginContainerRow}>
+              <TextField
+                className={styles.hostLabel}
+                label="Hostname/IP"
+                type="hostname"
+                value={hostname}
+                onChange={(event) =>
+                  this.setState({ ...this.state, hostname: event.currentTarget.value })
+                }
+                required
+              />
+              <TextField
+                className={styles.portLabel}
+                label="Port"
+                type="port"
+                value={port}
+                onChange={(event) => this.handlePortChanged(event.currentTarget.value)}
+                required
+              />
+            </div>
+            <div className={styles.loginContainer}>
+              <TextField
+                className={styles.userLabel}
+                label="Username"
+                type="username"
+                value={username}
+                onChange={(event) =>
+                  this.setState({ ...this.state, username: event.currentTarget.value })
+                }
+                required
+              />
+            </div>
+            <div className={styles.loginContainer}>
+              <TextField
+                className={styles.passLabel}
+                label="Password"
+                type="password"
+                value={password}
+                onChange={(event) =>
+                  this.setState({ ...this.state, password: event.currentTarget.value })
+                }
+                required
+              />
+            </div>
+            <div className={styles.loginContainer}>
+              <TextField
+                className={styles.passLabel}
+                label="Internal database"
+                type="internalDatabaseName"
+                value={internalDatabase}
+                onChange={(event) =>
+                  this.setState({ ...this.state, internalDatabase: event.currentTarget.value })
+                }
+                required
+              />
+            </div>
+            <div className={styles.loginContainerButton}>
+              <Button variant="outlined" type="submit">
+                Submit
+              </Button>
+              <Button
+                className={styles.cancelButton}
+                variant="outlined"
+                onClick={() => {
+                  this.props.onClose();
+                }}
+              >
+                Cancel
+              </Button>
+            </div>
+          </form>
+        </div>
+      </div>
+    ) : (
+      <></>
+    );
+  }
+}
+export default withStyles(useStyles)(AddDatabaseForm);
diff --git a/apps/web/src/components/navbar/AddDatabaseForm/add-database-form.scss b/apps/web/src/components/navbar/AddDatabaseForm/add-database-form.scss
new file mode 100644
index 0000000000000000000000000000000000000000..97642ae3758a844a1c36c7afcb9185993e8c419b
--- /dev/null
+++ b/apps/web/src/components/navbar/AddDatabaseForm/add-database-form.scss
@@ -0,0 +1,75 @@
+.wrapper {
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  width: 100vw;
+  background-color: rgba(0, 0, 0, 0.87);
+  position: absolute;
+  z-index: 1225;
+}
+
+.authWrapper {
+  font-family: Poppins, sans-serif;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: wrap;
+  justify-content: center;
+  max-width: 400px;
+  margin: auto;
+  overflow: auto;
+  min-height: 300px;
+  background-color: #f7f8fc;
+  padding: 30px;
+  border-radius: 5px;
+  padding-bottom: 300px;
+}
+
+.header {
+  text-align: center;
+}
+
+.formWrapper {
+}
+
+.loginContainer {
+  margin: 5px 0px !important;
+}
+
+.loginContainerRow {
+  display: flex;
+  flex-direction: row;
+  margin: 5px 0px;
+}
+
+.loginContainerButton {
+  margin-top: 10px !important;
+
+  & button {
+    width: 100%;
+  }
+}
+
+.hostLabel {
+  flex: 1 0 66.66667%;
+
+  & div {
+    width: 95%;
+  }
+}
+
+.portLabel {
+  flex: 1 0 33.33334%;
+}
+
+.userLabel {
+  width: 100%;
+}
+
+passLabel {
+  width: 100%;
+}
+
+cancelButton {
+  margin-top: 2.5%;
+}
+
diff --git a/apps/web/src/components/navbar/MenuList.scss b/apps/web/src/components/navbar/MenuList.scss
new file mode 100644
index 0000000000000000000000000000000000000000..af7f9f647753753c0c3077e7a1994ada4454fcbb
--- /dev/null
+++ b/apps/web/src/components/navbar/MenuList.scss
@@ -0,0 +1,17 @@
+/* This file is dependent on src/data/domain/entity/customization/colours.tsx 
+*  You can match a class name with a colour palette by naming the class 'menuList-' + colour palette name
+*/
+
+.menuList-default{
+    .MuiPaper-root{
+        background-color: #fffdfa;
+        color: #000000;
+    }
+}
+
+.menuList-dark{
+    .MuiPaper-root{
+        background-color: #171721;
+        color: #ffffff;
+    }
+}
\ No newline at end of file
diff --git a/apps/web/src/components/navbar/logogp.png b/apps/web/src/components/navbar/logogp.png
new file mode 100644
index 0000000000000000000000000000000000000000..cebd2d5f6a7e895c4858d7b9b0153a245fd0d7f9
Binary files /dev/null and b/apps/web/src/components/navbar/logogp.png differ
diff --git a/apps/web/src/components/navbar/logogpwhite.png b/apps/web/src/components/navbar/logogpwhite.png
new file mode 100644
index 0000000000000000000000000000000000000000..c83f02998f92e8b99c7c51416ac62968fe5fb302
Binary files /dev/null and b/apps/web/src/components/navbar/logogpwhite.png differ
diff --git a/apps/web/src/components/navbar/navbar.module.scss b/apps/web/src/components/navbar/navbar.module.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e1faa9a7863fcca1b4c52135300e3951de0e5b8e
--- /dev/null
+++ b/apps/web/src/components/navbar/navbar.module.scss
@@ -0,0 +1,44 @@
+.root {
+  display: flex;
+  overflow: hidden;
+}
+
+.appBar {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  background-color: #fff;
+  height: 50px;
+}
+
+.menubox {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  width: 100%;
+}
+
+.menuText {
+  margin: 5px;
+  color: #181520;
+  font-family: Poppins, sans-serif;
+  font-weight: 400;
+  font-size: 15px;
+  align-self: flex-end;
+  text-transform: none;
+}
+
+.logo {
+  margin: auto;
+  display: block;
+}
+
+.loginButton {
+  margin: 6px;
+}
+
+.loginButtonText {
+  color: black;
+  font-weight: bold;
+}
+
diff --git a/apps/web/src/components/navbar/navbar.tsx b/apps/web/src/components/navbar/navbar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..325670160bbf99d4d3512eba328e00d63d9a94a6
--- /dev/null
+++ b/apps/web/src/components/navbar/navbar.tsx
@@ -0,0 +1,343 @@
+/**
+ * This program has been developed by students from the bachelor Computer Science at
+ * Utrecht University within the Software Project course.
+ * © Copyright Utrecht University (Department of Information and Computing Sciences)
+ */
+
+/* istanbul ignore file */
+/* The comment above was added so the code coverage wouldn't count this file towards code coverage.
+ * We do not test components/renderfunctions/styling files.
+ * See testing plan for more details.*/
+import React from 'react';
+import { ClassNameMap } from '@material-ui/styles';
+import NavbarViewModel from '../../view-model/navbar/NavbarViewModel';
+import {
+  AppBar,
+  Toolbar,
+  CssBaseline,
+  Typography,
+  MenuItem,
+  ListItemText,
+  Menu,
+  IconButton,
+  Button,
+} from '@material-ui/core/';
+import { AccountCircle } from '@material-ui/icons';
+import logo from './logogp.png';
+import logo2 from './logogpwhite.png';
+import AddDatabaseForm from './AddDatabaseForm/AddDatabaseFormComponent';
+
+/** NavbarComponentProps is an interface containing the NavbarViewModel. */
+export interface NavbarComponentProps {
+  navbarViewModel: NavbarViewModel;
+  currentColours: any;
+  changeColourPalette: () => void;
+}
+
+/** NavbarComponentState is an interface containing the type of visualisations. */
+export interface NavbarComponentState {
+  styles: ClassNameMap;
+
+  isAuthorized: boolean;
+  clientID: string;
+  sessionID: string;
+  databases: string[];
+  currentDatabase: string;
+
+  // The anchor for rendering the user data (clientID, sessionID, add database, etc) menu
+  userMenuAnchor?: Element;
+  // The anchor for rendering the menu for selecting a database to use
+  selectDatabaseMenuAnchor?: Element;
+  // Determines if the addDatabaseForm will be shown
+  showAddDatabaseForm: boolean;
+}
+
+/** NavbarComponent is the View implementation for Navbar */
+export default class Navbar
+  extends React.Component<NavbarComponentProps, NavbarComponentState>
+  implements BaseView
+{
+  private navbarViewModel: NavbarViewModel;
+
+  public constructor(props: NavbarComponentProps) {
+    super(props);
+
+    const { navbarViewModel, currentColours } = props;
+    this.navbarViewModel = navbarViewModel;
+
+    this.state = {
+      isAuthorized: false,
+      styles: navbarViewModel.styles,
+      clientID: navbarViewModel.clientID,
+      sessionID: navbarViewModel.sessionID,
+      databases: [],
+      currentDatabase: navbarViewModel.currentDatabase,
+
+      userMenuAnchor: undefined,
+      selectDatabaseMenuAnchor: undefined,
+      showAddDatabaseForm: false,
+    };
+  }
+
+  public componentDidMount(): void {
+    this.navbarViewModel.attachView(this);
+  }
+
+  public componentWillUnmount(): void {
+    this.navbarViewModel.detachView();
+  }
+
+  /** onViewModelChanged updates the NavbarComponent each time the navbarViewModel changes */
+  public onViewModelChanged(): void {
+    this.setState({
+      isAuthorized: this.navbarViewModel.isAuthorized,
+      clientID: this.navbarViewModel.clientID,
+      sessionID: this.navbarViewModel.sessionID,
+      databases: this.navbarViewModel.databases,
+      currentDatabase: this.navbarViewModel.currentDatabase,
+    });
+  }
+
+  /** Closes the user menu. Also closes all nested menu's. */
+  private closeUserMenu(): void {
+    // If a nested window is open, close the main user menu a bit later
+    if (this.state.selectDatabaseMenuAnchor != undefined) {
+      this.setState({ selectDatabaseMenuAnchor: undefined });
+      setTimeout(() => this.setState({ userMenuAnchor: undefined }), 100);
+    } else this.setState({ userMenuAnchor: undefined });
+  }
+
+  /**
+   * Render will render the navigation bar
+   * @return {JSX.Element} The TypeScript code of the navigation bar
+   */
+  public render(): JSX.Element {
+    const { styles } = this.state;
+    const currentLogo =
+      this.props.currentColours.logo == 'white' ? logo2 : logo;
+
+    return (
+      <div className={styles.root}>
+        <CssBaseline />
+        <AppBar
+          title="GraphPolaris"
+          style={{
+            zIndex: 1250,
+            backgroundColor: '#' + this.props.currentColours.background,
+          }}
+          position="fixed"
+          className={styles.appBar}
+        >
+          <Toolbar style={{ marginLeft: -5 }}>
+            <a href="https://graphpolaris.com/" className={styles.logo}>
+              <img src={currentLogo} className={styles.logo} />
+            </a>
+            <div className={styles.menubox}>
+              <Button
+                className={styles.menuText}
+                style={{ color: '#' + this.props.currentColours.menuText }}
+                onClick={this.props.changeColourPalette}
+              >
+                Change Palette
+              </Button>
+              <Button
+                href="https://graphpolaris.com/"
+                className={styles.menuText}
+                style={{ color: '#' + this.props.currentColours.menuText }}
+              >
+                Home
+              </Button>
+              <Button
+                href="https://graphpolaris.com/index.php/products/"
+                className={styles.menuText}
+                style={{ color: '#' + this.props.currentColours.menuText }}
+              >
+                Products
+              </Button>
+              <Button
+                href="https://graphpolaris.com#usecases"
+                className={styles.menuText}
+                style={{ color: '#' + this.props.currentColours.menuText }}
+              >
+                Use Cases
+              </Button>
+              <Button
+                href="https://graphpolaris.com#earlyadoption"
+                className={styles.menuText}
+                style={{ color: '#' + this.props.currentColours.menuText }}
+              >
+                Contact
+              </Button>
+              {this.state.isAuthorized ? (
+                <div>
+                  <IconButton
+                    color="inherit"
+                    onClick={(event) =>
+                      this.setState({
+                        ...this.state,
+                        userMenuAnchor: event.currentTarget,
+                      })
+                    }
+                  >
+                    <AccountCircle
+                      htmlColor={'#' + this.props.currentColours.menuText}
+                    />
+                  </IconButton>
+                  <Menu
+                    id="user-menus"
+                    getContentAnchorEl={null}
+                    anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
+                    transformOrigin={{ vertical: 'top', horizontal: 'left' }}
+                    anchorEl={this.state.userMenuAnchor}
+                    keepMounted
+                    open={Boolean(this.state.userMenuAnchor)}
+                    onClose={() => this.closeUserMenu()}
+                  >
+                    <MenuItem>
+                      <ListItemText
+                        primary={'clientID: ' + this.state.clientID}
+                      />
+                    </MenuItem>
+                    <MenuItem>
+                      <ListItemText
+                        primary={'sessionID: ' + this.state.sessionID}
+                      />
+                    </MenuItem>
+                    <MenuItem
+                      onClick={() =>
+                        this.navbarViewModel.handleLoginButtonClicked('google')
+                      }
+                    >
+                      <ListItemText primary={'request new'} />
+                    </MenuItem>
+                    {/*<MenuItem onClick={() => LocalStorage.instance().Reset()}>*/}
+                    {/*  <ListItemText primary={'Empty localstorage'} />*/}
+                    {/*</MenuItem>*/}
+                    <MenuItem
+                      onClick={() =>
+                        this.setState({
+                          ...this.state,
+                          userMenuAnchor: undefined,
+                          showAddDatabaseForm: true,
+                        })
+                      }
+                    >
+                      <ListItemText primary={'Add database'} />
+                    </MenuItem>
+                    <MenuItem
+                      onClick={(event) =>
+                        this.setState({
+                          ...this.state,
+                          selectDatabaseMenuAnchor: event.currentTarget,
+                        })
+                      }
+                    >
+                      <ListItemText primary={'Change database'} />
+                    </MenuItem>
+                    <Menu
+                      id="databases-menus"
+                      getContentAnchorEl={null}
+                      anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
+                      transformOrigin={{ vertical: 'top', horizontal: 'right' }}
+                      anchorEl={this.state.selectDatabaseMenuAnchor}
+                      keepMounted
+                      disableAutoFocusItem
+                      open={Boolean(this.state.selectDatabaseMenuAnchor)}
+                      onClose={() => this.closeUserMenu()}
+                    >
+                      {this.state.databases.length > 0 ? (
+                        this.state.databases.map((database) => (
+                          <MenuItem
+                            key={database}
+                            selected={database == this.state.currentDatabase}
+                            onClick={() => {
+                              if (this.state.currentDatabase != database) {
+                                this.navbarViewModel.updateCurrentDatabase(
+                                  database
+                                );
+                                this.closeUserMenu();
+                              }
+                            }}
+                          >
+                            <ListItemText primary={database} />
+                          </MenuItem>
+                        ))
+                      ) : (
+                        <MenuItem key="placeholder" value="" disabled>
+                          no databases connected
+                        </MenuItem>
+                      )}
+                    </Menu>
+                  </Menu>
+                </div>
+              ) : (
+                <div>
+                  <Button
+                    className={styles.loginButton}
+                    onClick={(event) =>
+                      this.setState({
+                        ...this.state,
+                        userMenuAnchor: event.currentTarget,
+                      })
+                    }
+                  >
+                    <span
+                      className={styles.loginButtonText}
+                      style={{
+                        color: '#' + this.props.currentColours.menuText,
+                      }}
+                    >
+                      Login
+                    </span>
+                  </Button>
+                  <Menu
+                    id="user-menus"
+                    getContentAnchorEl={null}
+                    anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
+                    transformOrigin={{ vertical: 'top', horizontal: 'left' }}
+                    anchorEl={this.state.userMenuAnchor}
+                    keepMounted
+                    open={Boolean(this.state.userMenuAnchor)}
+                    onClose={() => this.closeUserMenu()}
+                  >
+                    <MenuItem
+                      onClick={() =>
+                        this.navbarViewModel.handleLoginButtonClicked('google')
+                      }
+                    >
+                      <ListItemText primary={'Login with Google'} />
+                    </MenuItem>
+                    <MenuItem
+                      onClick={() =>
+                        this.navbarViewModel.handleLoginButtonClicked('github')
+                      }
+                    >
+                      <ListItemText primary={'Login with GitHub'} />
+                    </MenuItem>
+                    <MenuItem
+                      onClick={() =>
+                        this.navbarViewModel.handleLoginButtonClicked('free')
+                      }
+                    >
+                      <ListItemText primary={'Login with free (debug)'} />
+                    </MenuItem>
+                  </Menu>
+                </div>
+              )}
+            </div>
+          </Toolbar>
+        </AppBar>
+        <AddDatabaseForm
+          open={this.state.showAddDatabaseForm}
+          onClose={() =>
+            this.setState({ ...this.state, showAddDatabaseForm: false })
+          }
+          onSubmit={(...params) => {
+            this.navbarViewModel.onAddDatabaseFormSubmit(...params);
+            this.setState({ ...this.state, showAddDatabaseForm: false });
+          }}
+        />
+      </div>
+    );
+  }
+}
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
index 05136727df33393019f3b7a458b6f4b08148f23c..8a74eed5864975dc493fc05b64a4acc6bb632e89 100644
--- a/apps/web/vite.config.ts
+++ b/apps/web/vite.config.ts
@@ -1,14 +1,18 @@
 /// <reference types="vitest" />
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react-swc'
-import path from 'path'
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react-swc';
+import path from 'path';
+import basicSsl from '@vitejs/plugin-basic-ssl';
 
 // https://vitejs.dev/config/
 export default defineConfig({
-  plugins: [react()],
+  plugins: [react(), basicSsl()],
   resolve: {
     alias: {
-      '@graphpolaris/shared/lib': path.resolve(__dirname, '../../libs/shared/lib')
+      '@graphpolaris/shared/lib': path.resolve(
+        __dirname,
+        '../../libs/shared/lib'
+      ),
     },
-  }
-})
+  },
+});
diff --git a/libs/shared/lib/data-access/api/database.ts b/libs/shared/lib/data-access/api/database.ts
index deabbe0f590ed058772363cb224fabd758425a88..e583b7f98b94c453b605250846a7efc44ca9d224 100644
--- a/libs/shared/lib/data-access/api/database.ts
+++ b/libs/shared/lib/data-access/api/database.ts
@@ -34,22 +34,24 @@ export function AddDatabase(request: AddDatabaseRequest): Promise<void> {
 
 export function GetAllDatabases(): Promise<Array<string>> {
   return new Promise<Array<string>>((resolve, reject) => {
+    console.log(AuthorizationHandler.instance().AccessToken());
     fetch('https://api.graphpolaris.com/user/database', {
       method: 'GET',
-      credentials: 'same-origin',
+      // credentials: 'same-origin',
       headers: new Headers({
         Authorization:
           'Bearer ' + AuthorizationHandler.instance().AccessToken(),
       }),
     })
       .then((response: Response) => {
-        if (!response.ok) {
-          reject(response.statusText);
-        }
+        // if (!response.ok) {
+        //   reject(response.statusText);
+        // }
 
         return response.json();
       })
       .then((json: any) => {
+        console.log(json);
         resolve(json.databases);
       });
   });
diff --git a/libs/shared/lib/data-access/api/user.ts b/libs/shared/lib/data-access/api/user.ts
index 06296ae3a3d7547cb1eaaa4ec9f85fe081ab2bed..825538a8278a9d8d0234c64d01a6e7d074a5c2e4 100644
--- a/libs/shared/lib/data-access/api/user.ts
+++ b/libs/shared/lib/data-access/api/user.ts
@@ -10,12 +10,12 @@ export type User = {
 
 export function GetUserInfo(): Promise<User> {
   return new Promise<User>((resolve, reject) => {
+    const auth = AuthorizationHandler.instance();
     fetch('https://api.graphpolaris.com/user/', {
       method: 'GET',
       credentials: 'same-origin',
       headers: new Headers({
-        Authorization:
-          'Bearer ' + AuthorizationHandler.instance().AccessToken(),
+        Authorization: 'Bearer ' + auth.AccessToken(),
       }),
     })
       .then((response: Response) => {
diff --git a/libs/shared/lib/data-access/authorization/authorizationHandler.ts b/libs/shared/lib/data-access/authorization/authorizationHandler.ts
index bc6001fd2aed8d24d60abf15411167af64629e81..4571c3b053f55a273620e386a8dcc3940cb343cd 100644
--- a/libs/shared/lib/data-access/authorization/authorizationHandler.ts
+++ b/libs/shared/lib/data-access/authorization/authorizationHandler.ts
@@ -36,6 +36,7 @@ export class AuthorizationHandler {
       // Store them
       this.userID = authResponse.userID ?? '';
       this.sessionID = authResponse.sessionID ?? '';
+
       this.SetAccessToken(authResponse.accessToken ?? '');
     }
 
@@ -93,8 +94,10 @@ export class AuthorizationHandler {
       // Set the new access token
       this.accessToken = authResponse.accessToken ?? '';
 
-      // Initialise the new refresh token
-      this.initialiseRefreshToken();
+      if (this.accessToken !== '') {
+        // Initialise the new refresh token
+        this.initialiseRefreshToken();
+      }
     }
   }
 
@@ -102,10 +105,14 @@ export class AuthorizationHandler {
    * initialiseRefreshToken attempts to initialise a refresh token
    */
   private async initialiseRefreshToken() {
-    fetch('https://api.graphpolaris.com/auth/refresh', {
-      method: 'POST',
-      credentials: 'include',
-    })
+    fetch(
+      'https://api.graphpolaris.com/auth/refresh?access_token=' +
+        this.accessToken,
+      {
+        method: 'GET',
+        credentials: 'include',
+      }
+    )
       .then((response) => {
         if (!response.ok) {
           throw Error(response.statusText);
@@ -158,8 +165,6 @@ export class AuthorizationHandler {
   async SetAccessToken(accessToken: string) {
     this.accessToken = accessToken;
 
-    console.log(this.accessToken);
-
     // Activate the refresh token
     this.initialiseRefreshToken();
 
diff --git a/libs/shared/lib/data-access/authorization/authorizationHook.tsx b/libs/shared/lib/data-access/authorization/authorizationHook.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..81d0d4fae7a880f127edaafcad32243725fb9795
--- /dev/null
+++ b/libs/shared/lib/data-access/authorization/authorizationHook.tsx
@@ -0,0 +1,28 @@
+import { useEffect, useState } from 'react';
+import { AuthorizationHandler } from '@graphpolaris/shared/lib/data-access';
+
+export function useIsAuthorized() {
+  const [userAuthorized, setUserAuthorized] = useState(false);
+
+  const authCallback = async () => {
+    setUserAuthorized(true);
+
+    // Print the user that is currently logged in
+    // const user = await GetUserInfo();
+    // console.log(user);
+  };
+
+  AuthorizationHandler.instance().setCallback(authCallback);
+
+  // Attempt to Authorize the user
+  const authorize = async () => {
+    const authorized = await AuthorizationHandler.instance().Authorize();
+    setUserAuthorized(authorized);
+  };
+
+  useEffect(() => {
+    authorize();
+  }, []);
+
+  return userAuthorized;
+}
diff --git a/libs/shared/lib/data-access/authorization/index.ts b/libs/shared/lib/data-access/authorization/index.ts
index 40d36480605c0faae067cdd01ace9cba3252d171..0cf2dd57d11433d17c7556f071f558b458c14c2d 100644
--- a/libs/shared/lib/data-access/authorization/index.ts
+++ b/libs/shared/lib/data-access/authorization/index.ts
@@ -1 +1,2 @@
 export { AuthorizationHandler } from './authorizationHandler';
+export * from './authorizationHook';
diff --git a/libs/shared/lib/data-access/store/schemaSlice.ts b/libs/shared/lib/data-access/store/schemaSlice.ts
index 4634eb33c99a27ba59f310a5d88bfba57321174a..bd3d0b4b70a92774e5fd947a83228e8f9b88d7f3 100644
--- a/libs/shared/lib/data-access/store/schemaSlice.ts
+++ b/libs/shared/lib/data-access/store/schemaSlice.ts
@@ -82,7 +82,7 @@ export const { readInSchemaFromBackend, setSchema } = schemaSlice.actions;
 export const schemaGraphology = (state: RootState) => {
   // This is really weird but for some reason all the attributes appeared as read-only otherwise
   let ret = new MultiGraph();
-  ret.import(MultiGraph.from(state.querybuilder.graphologySerialized).export());
+  ret.import(MultiGraph.from(state.schema.graphologySerialized).export());
   return ret;
 };
 
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 651a2726f31790745e63edd0f8268351d01308af..c0bd7f0cc8610cba4f060887d3e5d7c273fc4dfc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -83,6 +83,9 @@ importers:
       '@types/styled-components':
         specifier: ^5.1.26
         version: 5.1.26
+      '@vitejs/plugin-basic-ssl':
+        specifier: ^1.0.1
+        version: 1.0.1(vite@4.2.1)
       '@vitejs/plugin-react-swc':
         specifier: ^3.0.0
         version: 3.2.0(vite@4.2.1)
@@ -683,7 +686,7 @@ packages:
     resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.3
+      '@babel/types': 7.21.4
 
   /@babel/helper-module-transforms@7.21.2:
     resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==}
@@ -1777,20 +1780,12 @@ packages:
       '@babel/helper-hoist-variables': 7.18.6
       '@babel/helper-split-export-declaration': 7.18.6
       '@babel/parser': 7.21.3
-      '@babel/types': 7.21.3
+      '@babel/types': 7.21.4
       debug: 4.3.4(supports-color@5.5.0)
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
 
-  /@babel/types@7.21.3:
-    resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/helper-string-parser': 7.19.4
-      '@babel/helper-validator-identifier': 7.19.1
-      to-fast-properties: 2.0.0
-
   /@babel/types@7.21.4:
     resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==}
     engines: {node: '>=6.9.0'}
@@ -4174,6 +4169,17 @@ packages:
       telejson: 7.0.4
     dev: true
 
+  /@storybook/channel-postmessage@7.0.6:
+    resolution: {integrity: sha512-xBsh/+85GS4bJ08r7z1iRn26EI6hGmMgNpjpFztRigMhsq5SkD9FJb+Nh9bbaHm+yPOCqJcaHQ2aQpuJNT8dHA==}
+    dependencies:
+      '@storybook/channels': 7.0.6
+      '@storybook/client-logger': 7.0.6
+      '@storybook/core-events': 7.0.6
+      '@storybook/global': 5.0.0
+      qs: 6.11.1
+      telejson: 7.0.4
+    dev: true
+
   /@storybook/channel-websocket@7.0.5:
     resolution: {integrity: sha512-QgvxAZjEdRzPZveUibErJbaqqe97DLscPeK5YHA1/xDCPqMKo0HaQKTyT0YSsSkeE3oKXbdz9IXFXEaPmIpjzw==}
     dependencies:
@@ -4199,6 +4205,10 @@ packages:
     resolution: {integrity: sha512-WiSPXgOK63jAlDDmbTs1sVXoYe3r/4VjpfwhEcxSPU544YQVARF1ePtiGjlp8HVFhZh1Q7afbVGJ9w96++u98A==}
     dev: true
 
+  /@storybook/channels@7.0.6:
+    resolution: {integrity: sha512-+34cVmrXZ3lb1s5tDK+OWd5HLtEPSUMas0VKFJ0k9LBpFlVl9aiCZBJRvSYmWL7beauUfa+HSmJgjlD6228ChQ==}
+    dev: true
+
   /@storybook/cli@7.0.5:
     resolution: {integrity: sha512-VRrf4XG9H29FycNqthT6r4MjT0f4ynpwQAj039vUrt95rosV8ytuLFIrTwww1x/2o/VNpkWyL7MJwu6dejeZgw==}
     hasBin: true
@@ -4267,6 +4277,12 @@ packages:
       '@storybook/global': 5.0.0
     dev: true
 
+  /@storybook/client-logger@7.0.6:
+    resolution: {integrity: sha512-TC/E5BBkY+WNldNw5p5Ffr9x4UgMe48GmC50ikBpQFk6og1B7XpFGMMbj40EBB0R5cpZkQNEVQh4OvunEygNzg==}
+    dependencies:
+      '@storybook/global': 5.0.0
+    dev: true
+
   /@storybook/codemod@7.0.5:
     resolution: {integrity: sha512-Hu9CiVBHhaPJHMVpiAjr7pEtL7/AUsKT/Xxn3xUM7Ngy7TYMa62XTIMkt2Z+tAAud0HzAz/6Wv+2q+IqPr7BeQ==}
     dependencies:
@@ -4422,6 +4438,10 @@ packages:
     resolution: {integrity: sha512-bYQFZlJR3n5gFk5GVIemuL3m6aYPF6DVnzj6n9UcMZDlHcOZ2B2WbTmAUrGy0bmtj/Fd6ZJKDpBhh3cRRsYkbA==}
     dev: true
 
+  /@storybook/core-events@7.0.6:
+    resolution: {integrity: sha512-kGrtjlYtjd4iTVk+Phb4CymZaVkB+MGscKAgcO8gfgJ/Q/gq8HQLVZSIzeoCDcDSHOGlBzbg2WVtdHIHhCKlOQ==}
+    dev: true
+
   /@storybook/core-server@7.0.5:
     resolution: {integrity: sha512-h3SVzwepHTyDxS7ZPuYfHStnWC0EC05axSPKb3yeO6bCsowf+CEXgY5VayUqP8GkgLBez859m172y6B+wVXZ3g==}
     dependencies:
@@ -4588,14 +4608,14 @@ packages:
       '@storybook/preview-api': 7.0.0-rc.5
     dev: true
 
-  /@storybook/instrumenter@7.0.5:
-    resolution: {integrity: sha512-A+uPQjA8JqR23efQbMHKnmeoltAJGYEV+855X3X27aie2B4mUo3KHELyeioaqTVuh1KZ/K0dTvjpfbGSQGscvg==}
+  /@storybook/instrumenter@7.0.6:
+    resolution: {integrity: sha512-JUcDas1cYCE+ZMVOw5CKc5g6PxDe3HH+IGdh/W9wL5vmdOUvAs858m7NLxkjkQGufof+Ohbmf/Yz5gyXaZ5+Yg==}
     dependencies:
-      '@storybook/channels': 7.0.5
-      '@storybook/client-logger': 7.0.5
-      '@storybook/core-events': 7.0.5
+      '@storybook/channels': 7.0.6
+      '@storybook/client-logger': 7.0.6
+      '@storybook/core-events': 7.0.6
       '@storybook/global': 5.0.0
-      '@storybook/preview-api': 7.0.5
+      '@storybook/preview-api': 7.0.6
     dev: true
 
   /@storybook/manager-api@7.0.0-rc.5(react-dom@18.2.0)(react@18.2.0):
@@ -4735,6 +4755,26 @@ packages:
       util-deprecate: 1.0.2
     dev: true
 
+  /@storybook/preview-api@7.0.6:
+    resolution: {integrity: sha512-uNsedNyiEccBV2EDUC/xcKTbmiNCYuVHbgOoWTmBz0ZqFo9bX0jxkpyYWHEhJM79qqVqmrpiQ5jbS8QKn8TIxQ==}
+    dependencies:
+      '@storybook/channel-postmessage': 7.0.6
+      '@storybook/channels': 7.0.6
+      '@storybook/client-logger': 7.0.6
+      '@storybook/core-events': 7.0.6
+      '@storybook/csf': 0.1.0
+      '@storybook/global': 5.0.0
+      '@storybook/types': 7.0.6
+      '@types/qs': 6.9.7
+      dequal: 2.0.3
+      lodash: 4.17.21
+      memoizerific: 1.11.3
+      qs: 6.11.1
+      synchronous-promise: 2.0.17
+      ts-dedent: 2.2.0
+      util-deprecate: 1.0.2
+    dev: true
+
   /@storybook/preview@7.0.5:
     resolution: {integrity: sha512-N1IDKzmqnF+XAdACGnaWw22dmSUQHuHKyyQ/vV9upMf0hA+4gk9pc5RFEHOQO/sTbxblgfKm9Q1fIYkxgPVFxg==}
     dev: true
@@ -4933,8 +4973,8 @@ packages:
   /@storybook/testing-library@0.0.14-next.1:
     resolution: {integrity: sha512-1CAl40IKIhcPaCC4pYCG0b9IiYNymktfV/jTrX7ctquRY3akaN7f4A1SippVHosksft0M+rQTFE0ccfWW581fw==}
     dependencies:
-      '@storybook/client-logger': 7.0.5
-      '@storybook/instrumenter': 7.0.5
+      '@storybook/client-logger': 7.0.6
+      '@storybook/instrumenter': 7.0.6
       '@testing-library/dom': 8.20.0
       '@testing-library/user-event': 13.5.0(@testing-library/dom@8.20.0)
       ts-dedent: 2.2.0
@@ -5000,6 +5040,15 @@ packages:
       file-system-cache: 2.0.2
     dev: true
 
+  /@storybook/types@7.0.6:
+    resolution: {integrity: sha512-dFASQxzvldU2Nx/eJG+oL4wCchUWAKOmOSYJYhKgtGpx99oXOiWUyC0SgCpTveBJ7AppoiseyasQ9Gd/Ccycdw==}
+    dependencies:
+      '@storybook/channels': 7.0.6
+      '@types/babel__core': 7.20.0
+      '@types/express': 4.17.17
+      file-system-cache: 2.0.2
+    dev: true
+
   /@swc/core-darwin-arm64@1.3.42:
     resolution: {integrity: sha512-hM6RrZFyoCM9mX3cj/zM5oXwhAqjUdOCLXJx7KTQps7NIkv/Qjvobgvyf2gAb89j3ARNo9NdIoLjTjJ6oALtiA==}
     engines: {node: '>=10'}
@@ -5851,6 +5900,15 @@ packages:
       '@typescript-eslint/types': 5.52.0
       eslint-visitor-keys: 3.3.0
 
+  /@vitejs/plugin-basic-ssl@1.0.1(vite@4.2.1):
+    resolution: {integrity: sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==}
+    engines: {node: '>=14.6.0'}
+    peerDependencies:
+      vite: ^3.0.0 || ^4.0.0
+    dependencies:
+      vite: 4.2.1(@types/node@18.13.0)(sass@1.59.3)
+    dev: true
+
   /@vitejs/plugin-react-swc@3.2.0(vite@4.2.1):
     resolution: {integrity: sha512-IcBoXL/mcH7JdQr/nfDlDwTdIaH8Rg7LpfQDF4nAht+juHWIuv6WhpKPCSfY4+zztAaB07qdBoFz1XCZsgo3pQ==}
     peerDependencies: