From 352159b44bf452dac0925e428fc1491c330dd3c9 Mon Sep 17 00:00:00 2001 From: Emanuele Libralato Date: Tue, 19 Jan 2021 17:33:02 +0100 Subject: [PATCH 1/2] fix(enterprise): fix start interval when using access tokens --- core/src/commands/logout.ts | 3 ++- core/src/enterprise/api.ts | 54 +++++++++++++++++++------------------ core/src/enterprise/auth.ts | 25 ++++++++++++----- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/core/src/commands/logout.ts b/core/src/commands/logout.ts index bf24512d82..a18ded7095 100644 --- a/core/src/commands/logout.ts +++ b/core/src/commands/logout.ts @@ -9,6 +9,7 @@ import { Command, CommandParams, CommandResult } from "./base" import { printHeader } from "../logger/util" import dedent = require("dedent") +import { logout } from "../enterprise/auth" export class LogOutCommand extends Command { name = "logout" @@ -32,7 +33,7 @@ export class LogOutCommand extends Command { log.debug({ msg: `Logging out of ${garden.enterpriseApi?.getDomain()}` }) log.info({ msg: `Logging out of Garden Enterprise.` }) try { - await garden.enterpriseApi.logout() + await logout(garden.enterpriseApi, log) log.info({ msg: `Succesfully logged out from Garden Enterprise.` }) } catch (error) { log.error(error) diff --git a/core/src/enterprise/api.ts b/core/src/enterprise/api.ts index 1243c531cf..a1549f148e 100644 --- a/core/src/enterprise/api.ts +++ b/core/src/enterprise/api.ts @@ -70,19 +70,38 @@ export class EnterpriseApi { return } this.enterpriseDomain = enterpriseDomain + + // Retrieve an authentication token const authToken = await this.readAuthToken() if (authToken && commandAllowed) { - this.log.debug({ msg: `Refreshing auth token and starting refresh interval.` }) + // Verify a valid token is present + this.log.debug({ msg: `Refreshing auth token and trying to start refresh interval.` }) const tokenIsValid = await this.checkClientAuthToken(this.log) + if (!tokenIsValid) { - await this.refreshToken() + // If the token is an Access Token and it's invalid we return. + if (gardenEnv.GARDEN_AUTH_TOKEN) { + this.log.error({ + msg: + "The provided access token is expired or revoked, please create a new one from the Garden Enterprise UI.", + }) + return + } else { + // Try to refresh an expired JWT + // This will throw if it fails to refresh + await this.refreshToken() + } } // At this point we can be sure the user is logged in because we have // a valid token or refreshing the token did not go through. // TODO: Refactor to make a bit more robust (cc @emanuele and @thsig, you // know what I'm talking about.) this.isUserLoggedIn = true - this.startInterval() + // Start refresh interval if using JWT + if (!gardenEnv.GARDEN_AUTH_TOKEN) { + this.log.debug({ msg: `Starting refresh interval.` }) + this.startInterval() + } } } @@ -90,7 +109,8 @@ export class EnterpriseApi { this.log.debug({ msg: `Will run refresh function every ${this.intervalMsec} ms.` }) this.intervalId = setInterval(() => { this.refreshToken().catch((err) => { - this.log.debug(err) + this.log.debug({ msg: "Something went wrong while trying to refresh the authentication token." }) + this.log.debug({ msg: err.message }) }) }, this.intervalMsec) } @@ -106,9 +126,11 @@ export class EnterpriseApi { const invalidCredentialsErrorMsg = "Your Garden Enteprise credentials have expired. Please login again." const token = await ClientAuthToken.findOne() - if (!token) { - throw new RuntimeError(invalidCredentialsErrorMsg, {}) + if (!token || gardenEnv.GARDEN_AUTH_TOKEN) { + this.log.debug({ msg: "Nothing to refresh, returning." }) + return } + if (isAfter(new Date(), sub(token.validity, { seconds: refreshThreshold }))) { try { const res = await this.get(this.log, "token/refresh", { @@ -207,26 +229,6 @@ export class EnterpriseApi { return token } - async logout() { - const token = await ClientAuthToken.findOne() - if (!token) { - // Noop when the user is not logged in - return - } - try { - await this.post(this.log, "token/logout", { - headers: { - Cookie: `rt=${token?.refreshToken}`, - }, - }) - - await this.clearAuthToken() - } catch (error) { - this.log.error({ msg: "An error occurred while logging out." }) - this.log.debug({ msg: JSON.stringify(error, null, 2) }) - } - } - /** * If a persisted client auth token exists, deletes it. */ diff --git a/core/src/enterprise/auth.ts b/core/src/enterprise/auth.ts index 42911a3dc4..2f7e276cc1 100644 --- a/core/src/enterprise/auth.ts +++ b/core/src/enterprise/auth.ts @@ -16,6 +16,8 @@ import getPort = require("get-port") import { LogEntry } from "../logger/log-entry" import { InternalError } from "../exceptions" import { EnterpriseApi, AuthTokenResponse } from "./api" +import { ClientAuthToken } from "../db/entities/client-auth-token" +import { gardenEnv } from "../constants" /** * Logs in to Garden Enterprise if needed, and returns a valid client auth token. @@ -55,13 +57,22 @@ export async function login(enterpriseApi: EnterpriseApi, log: LogEntry): Promis } export async function logout(enterpriseApi: EnterpriseApi, log: LogEntry): Promise { - const savedToken = await enterpriseApi.readAuthToken() - // Ping platform with saved token (if it exists) - if (savedToken) { - log.debug("Local client auth token found, verifying it with platform...") - if (await enterpriseApi.checkClientAuthToken(log)) { - log.debug("Local client token is valid, no need for login.") - } + const token = await ClientAuthToken.findOne() + if (!token || gardenEnv.GARDEN_AUTH_TOKEN) { + // Noop when the user is not logged in or an access token is in use + return + } + try { + await enterpriseApi.post(log, "token/logout", { + headers: { + Cookie: `rt=${token?.refreshToken}`, + }, + }) + + await enterpriseApi.clearAuthToken() + } catch (error) { + log.error({ msg: "An error occurred while logging out." }) + log.debug({ msg: JSON.stringify(error, null, 2) }) } } From f308a6ebc3b472a2f7a7cc646a6a6e00b478d54a Mon Sep 17 00:00:00 2001 From: Emanuele Libralato Date: Tue, 19 Jan 2021 17:57:28 +0100 Subject: [PATCH 2/2] fix: pr requests (TBS) --- core/src/enterprise/api.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/enterprise/api.ts b/core/src/enterprise/api.ts index a1549f148e..c1d6e1b1db 100644 --- a/core/src/enterprise/api.ts +++ b/core/src/enterprise/api.ts @@ -81,11 +81,10 @@ export class EnterpriseApi { if (!tokenIsValid) { // If the token is an Access Token and it's invalid we return. if (gardenEnv.GARDEN_AUTH_TOKEN) { - this.log.error({ - msg: - "The provided access token is expired or revoked, please create a new one from the Garden Enterprise UI.", - }) - return + throw new RuntimeError( + "The provided access token is expired or has been revoked, please create a new one from the Garden Enterprise UI.", + {} + ) } else { // Try to refresh an expired JWT // This will throw if it fails to refresh