From c84891671950afa777178fbaeddd4639013f74d1 Mon Sep 17 00:00:00 2001 From: Kiril Popov Date: Mon, 11 Mar 2024 11:56:35 +0200 Subject: [PATCH] done --- README.md | 16 ++++++++++++---- admin-ui/src/auth.ts | 26 +++++++++++++++++++++----- login/index.js | 26 +++++++++++++++++--------- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 35b900b..a4ce527 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,18 @@ To remove the default app stores, set the "appStores" top-level key to an empty ## Protecting the Admin UI with a login page -Users that belong to a special group (**GLUE42_SERVER_ADMIN**) can access administrative APIs and therefore use the administrative UI. +In this example the Administrative UI is customized with a [custom **authenticator**](./admin-ui/src/auth.ts). The authenticator re-directs to the login page. After the user log-ins the login sends back the generated token as a query param. Then **Admin UI** then uses this token for calls to the server. +**Note that this example is for demonstrative purposes and should not be used in production.** -In this example the Administrative UI is customized with a [custom **authenticator**](./admin-ui/src/auth.ts) that always produces a token with for a user that is part of that group. +To access **Admin UI** users must belong to a special group (**GLUE42_SERVER_ADMIN**). Check [data.ts](./server/src/data.ts) for the list of users that have that group and use one of them to login. -In a real world scenario you would need to implement a real **authenticator** or define the administrative UI as an application in Glue42 and access it from there. +To start the Admin UI follow the [instructions](./admin-ui/README.md) in the admin-ui folder. + +In a real world scenario you have the following options to protect admin-ui: + +1. Implement a custom authenticator; + 1. Implement a custom login react based login component that will authenticate the user against an in-house service and provide the token to the custom authenticator + 2. Re-use existing login page and extract the token in the custom authenticator once the user is authenticated + +2. Put the Admin UI behind a reverse proxy that would handle the authentication and pass the user info to the server -To start the Admin UI follow the [instructions](./admin-ui/README.md) in the admin-ui folder. \ No newline at end of file diff --git a/admin-ui/src/auth.ts b/admin-ui/src/auth.ts index f6701ff..4a0f70f 100644 --- a/admin-ui/src/auth.ts +++ b/admin-ui/src/auth.ts @@ -7,20 +7,36 @@ export class CustomAuthProvider implements AuthProvider { public addCredentialsToRequest = false; public addUsernameToRequest = false; public error: any = undefined; + public token: string = ""; public async loginIfNeeded(): Promise { - // do nothing, we have hardcoded isAuthenticated to true, so this is never called - console.log(`loginIfNeeded`); - this.isAuthenticated = true; + // get token query parameter + const urlParams = new URLSearchParams(window.location.search); + const token = urlParams.get("token"); + if (token) { + this.token = token; + this.isAuthenticated = true; + return Promise.resolve(); + } + + if (!this.isAuthenticated) { + document.location.href = `http://localhost:9123/?callback=${document.location.href}`; + } + return Promise.resolve(); } + public async getAccessToken(): Promise { - return "user:admin"; + return this.token; } public async getUserInfo(): Promise<{ id?: string | undefined; } | undefined> { return { - id: "admin" + id: this.token }; } + + public async logOut(): Promise { + this.token = ""; + } } diff --git a/login/index.js b/login/index.js index 67d33b6..2d8dbce 100644 --- a/login/index.js +++ b/login/index.js @@ -9,7 +9,7 @@ window.addEventListener("DOMContentLoaded", (event) => { const login = async () => { const emailElement = document.getElementById(`email`); const isEmailValid = emailElement.reportValidity(); - if (!isEmailValid){ + if (!isEmailValid) { // show validation error return; } @@ -18,13 +18,21 @@ const login = async () => { localStorage.setItem(`user`, email); const token = `user:${email}`; - await glue42gd.authDone({ - token, - user: email - }); - closeWindow(); -}; -const closeWindow = () => { - window.close(); + // if running in interop.io desktop, try to set the token and close the window + if (typeof glue42gd !== "undefined") { + await glue42gd.authDone({ + token, + user: email + }); + + window.close(); + } + + // if being used as protection of admin-ui we will redirect to the admin-ui with the token + const urlParams = new URLSearchParams(window.location.search); + const callback = urlParams.get(`callback`); + if (callback) { + window.location = callback + "?token=" + token; + } }; \ No newline at end of file