From f41272d4dfbe6cb67d44039f2b94bc2d9ef1e20b Mon Sep 17 00:00:00 2001 From: = Date: Sun, 21 Jul 2024 19:24:54 +0530 Subject: [PATCH 1/4] feat: added option for manually adding token in browser login failure --- cli/go.mod | 4 +-- cli/go.sum | 3 +- cli/packages/cmd/login.go | 73 ++++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/cli/go.mod b/cli/go.mod index 82f84cebb..4f37e1232 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( github.com/bradleyjkemp/cupaloy/v2 v2.8.0 github.com/charmbracelet/lipgloss v0.5.0 + github.com/chzyer/readline v1.5.1 github.com/creack/pty v1.1.21 github.com/denisbrodbeck/machineid v1.0.1 github.com/fatih/semgroup v1.2.0 @@ -49,7 +50,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect github.com/aws/smithy-go v1.20.2 // indirect - github.com/chzyer/readline v1.5.1 // indirect github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect @@ -94,7 +94,7 @@ require ( golang.org/x/net v0.25.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.183.0 // indirect diff --git a/cli/go.sum b/cli/go.sum index e0791eec2..fd08b3f1a 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -621,8 +621,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index abf664ed0..720c33dbf 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -24,6 +24,7 @@ import ( "github.com/Infisical/infisical-merge/packages/models" "github.com/Infisical/infisical-merge/packages/srp" "github.com/Infisical/infisical-merge/packages/util" + "github.com/chzyer/readline" "github.com/fatih/color" "github.com/go-resty/resty/v2" "github.com/manifoldco/promptui" @@ -229,6 +230,7 @@ var loginCmd = &cobra.Command{ fmt.Println("Logging in via browser... To login via interactive mode run [infisical login -i]") userCredentialsToBeStored, err = browserCliLogin() if err != nil { + fmt.Printf("Logging in via browser failed. %s", err.Error()) //default to cli login on error cliDefaultLogin(&userCredentialsToBeStored) } @@ -713,10 +715,63 @@ func askForMFACode() string { return mfaVerifyCode } +func askToPasteJwtToken(stdin *readline.CancelableStdin, success chan models.UserCredentials, failure chan error) { + time.Sleep(time.Second * 5) + + prompt := &promptui.Prompt{ + Label: "Did you see a prompt in your browser asking you to paste a token?", + IsConfirm: true, + Stdin: stdin, + } + + _, err := prompt.Run() + if err != nil { + if errors.Is(err, promptui.ErrAbort) { + stdin.Close() + return + } + failure <- err + return + } + + prompt = &promptui.Prompt{ + Label: "Paste your token", + Mask: '*', + Stdin: stdin, + } + infisicalPastedToken, err := prompt.Run() + if err != nil { + failure <- err + return + } + + userCredentials, err := decodePastedBase64Token(infisicalPastedToken) + if err != nil { + failure <- err + return + } + success <- *userCredentials +} + +func decodePastedBase64Token(token string) (*models.UserCredentials, error) { + data, err := base64.StdEncoding.DecodeString(token) + if err != nil { + return nil, err + } + var loginResponse models.UserCredentials + + err = json.Unmarshal(data, &loginResponse) + if err != nil { + return nil, err + } + + return &loginResponse, nil +} + // Manages the browser login flow. // Returns a UserCredentials object on success and an error on failure func browserCliLogin() (models.UserCredentials, error) { - SERVER_TIMEOUT := 60 * 10 + SERVER_TIMEOUT := 10 * 60 //create listener listener, err := net.Listen("tcp", "127.0.0.1:0") @@ -738,7 +793,6 @@ func browserCliLogin() (models.UserCredentials, error) { success := make(chan models.UserCredentials) failure := make(chan error) timeout := time.After(time.Second * time.Duration(SERVER_TIMEOUT)) - quit := make(chan bool) //terminal state oldState, err := term.GetState(int(os.Stdin.Fd())) @@ -760,24 +814,27 @@ func browserCliLogin() (models.UserCredentials, error) { log.Debug().Msgf("Callback server listening on port %d", callbackPort) + stdin := readline.NewCancelableStdin(os.Stdin) go http.Serve(listener, corsHandler) + go askToPasteJwtToken(stdin, success, failure) for { select { case loginResponse := <-success: _ = closeListener(&listener) + _ = stdin.Close() + fmt.Println("Browser login successfull") return loginResponse, nil - case <-failure: - err = closeListener(&listener) - return models.UserCredentials{}, err + case err := <-failure: + serverErr := closeListener(&listener) + stdErr := stdin.Close() + return models.UserCredentials{}, errors.Join(err, serverErr, stdErr) case <-timeout: _ = closeListener(&listener) + _ = stdin.Close() return models.UserCredentials{}, errors.New("server timeout") - - case <-quit: - return models.UserCredentials{}, errors.New("quitting browser login, defaulting to cli...") } } } From 1ee65205a00da99335cb7692e9aae14a3cff0a21 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 21 Jul 2024 19:25:41 +0530 Subject: [PATCH 2/4] feat: ui option to paste token on sending token to cli fails --- frontend/src/const.ts | 4 + frontend/src/hooks/api/users/queries.tsx | 2 + frontend/src/pages/cli-redirect.tsx | 82 +++++++++++++++++-- .../src/pages/login/select-organization.tsx | 16 +++- .../Login/components/MFAStep/MFAStep.tsx | 17 +++- .../ShareSecretPublicPage.tsx | 61 ++++++++------ 6 files changed, 146 insertions(+), 36 deletions(-) diff --git a/frontend/src/const.ts b/frontend/src/const.ts index 880d2f021..d2623431d 100644 --- a/frontend/src/const.ts +++ b/frontend/src/const.ts @@ -57,6 +57,10 @@ export const plans = plansProd || plansDev; export const leaveConfirmDefaultMessage = "Your changes will be lost if you leave the page. Are you sure you want to continue?"; +export enum SessionStorageKeys { + CLI_TERMINAL_TOKEN = "CLI_TERMINAL_TOKEN" +} + export const secretTagsColors = [ { id: 1, diff --git a/frontend/src/hooks/api/users/queries.tsx b/frontend/src/hooks/api/users/queries.tsx index ea3f44676..4629ce4e6 100644 --- a/frontend/src/hooks/api/users/queries.tsx +++ b/frontend/src/hooks/api/users/queries.tsx @@ -1,6 +1,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "@app/config/request"; +import { SessionStorageKeys } from "@app/const"; import { setAuthToken } from "@app/reactQuery"; import { APIKeyDataV2 } from "../apiKeys/types"; @@ -293,6 +294,7 @@ export const useLogoutUser = (keepQueryClient?: boolean) => { localStorage.removeItem("PRIVATE_KEY"); localStorage.removeItem("orgData.id"); localStorage.removeItem("projectData.id"); + sessionStorage.removeItem(SessionStorageKeys.CLI_TERMINAL_TOKEN); if (!keepQueryClient) { queryClient.clear(); diff --git a/frontend/src/pages/cli-redirect.tsx b/frontend/src/pages/cli-redirect.tsx index 9838d3ea1..c617e9fb2 100644 --- a/frontend/src/pages/cli-redirect.tsx +++ b/frontend/src/pages/cli-redirect.tsx @@ -1,23 +1,89 @@ import Head from "next/head"; import Image from "next/image"; +import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { IconButton, SecretInput } from "@app/components/v2"; +import { SessionStorageKeys } from "@app/const"; +import { useTimedReset } from "@app/hooks"; + +const getTerminalCliToken = () => { + const cliTerminalTokenInfo = sessionStorage.getItem(SessionStorageKeys.CLI_TERMINAL_TOKEN); + if (!cliTerminalTokenInfo) return; + + const { expiry, data } = JSON.parse(cliTerminalTokenInfo); + if (new Date() > new Date(expiry)) { + sessionStorage.removeItem(SessionStorageKeys.CLI_TERMINAL_TOKEN); + return; + } + + // eslint-disable-next-line + return data as string; +}; export default function CliRedirect() { + const [isUrlCopied, , setIsUrlCopied] = useTimedReset({ + initialState: false + }); + const cliToken = getTerminalCliToken(); + + const copyUrlToClipboard = () => { + if (cliToken) { + navigator.clipboard.writeText(cliToken); + setIsUrlCopied(true); + sessionStorage.removeItem(SessionStorageKeys.CLI_TERMINAL_TOKEN); + } + }; + return (
Infisical CLI | Login Successful! -
-
+
+
Infisical Logo
-

- Head back to your terminal -

-

- You've successfully logged in to the Infisical CLI -

+ {cliToken ? ( + <> +
+

+ Login successful! +

+

+ However, your token could not be sent to the CLI +

+
+
+ +
+ + Copy to + clipboard + +
+
+

+ After copying, return to terminal screen and paste it there +

+ + ) : ( + <> +

+ Head back to your terminal +

+

+ You've successfully logged in to the Infisical CLI +

+ + )}
); diff --git a/frontend/src/pages/login/select-organization.tsx b/frontend/src/pages/login/select-organization.tsx index 22006408e..349952ba5 100644 --- a/frontend/src/pages/login/select-organization.tsx +++ b/frontend/src/pages/login/select-organization.tsx @@ -7,11 +7,13 @@ import { useRouter } from "next/router"; import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import axios from "axios"; +import { addSeconds, formatISO } from "date-fns"; import jwt_decode from "jwt-decode"; import { createNotification } from "@app/components/notifications"; import { IsCliLoginSuccessful } from "@app/components/utilities/attemptCliLogin"; import { Button, Spinner } from "@app/components/v2"; +import { SessionStorageKeys } from "@app/const"; import { useUser } from "@app/context"; import { useGetOrganizations, useLogoutUser, useSelectOrganization } from "@app/hooks/api"; import { Organization } from "@app/hooks/api/types"; @@ -94,9 +96,19 @@ export default function LoginPage() { // send request to server endpoint const instance = axios.create(); - await instance.post(`http://127.0.0.1:${callbackPort}/`, payload); - // cli page + await instance.post(`http://127.0.0.1:${callbackPort}/`, payload).catch(() => { + // if error happens to communicate we set the token with an expiry in sessino storage + // the cli-redirect page has logic to show this to user and ask them to paste it in terminal + sessionStorage.setItem( + SessionStorageKeys.CLI_TERMINAL_TOKEN, + JSON.stringify({ + expiry: formatISO(addSeconds(new Date(), 30)), + data: window.btoa(JSON.stringify(payload)) + }) + ); + }); router.push("/cli-redirect"); + // cli page } else { navigateUserToOrg(router, organization.id); } diff --git a/frontend/src/views/Login/components/MFAStep/MFAStep.tsx b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx index 5f04454bc..70f3eee25 100644 --- a/frontend/src/views/Login/components/MFAStep/MFAStep.tsx +++ b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx @@ -3,6 +3,7 @@ import ReactCodeInput from "react-code-input"; import { useTranslation } from "react-i18next"; import { useRouter } from "next/router"; import axios from "axios"; +import { addSeconds, formatISO } from "date-fns"; import jwt_decode from "jwt-decode"; import Error from "@app/components/basic/Error"; @@ -11,6 +12,7 @@ import attemptCliLoginMfa from "@app/components/utilities/attemptCliLoginMfa"; import attemptLoginMfa from "@app/components/utilities/attemptLoginMfa"; import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button } from "@app/components/v2"; +import { SessionStorageKeys } from "@app/const"; import { useSendMfaToken } from "@app/hooks/api/auth"; import { useSelectOrganization, verifyMfaToken } from "@app/hooks/api/auth/queries"; import { fetchOrganizations } from "@app/hooks/api/organization/queries"; @@ -79,11 +81,24 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => { if (callbackPort) { const cliUrl = `http://127.0.0.1:${callbackPort}/`; const instance = axios.create(); - await instance.post(cliUrl, { + const payload = { email, privateKey, JTWToken: newJwtToken + }; + await instance.post(cliUrl, payload).catch(() => { + // if error happens to communicate we set the token with an expiry in sessino storage + // the cli-redirect page has logic to show this to user and ask them to paste it in terminal + sessionStorage.setItem( + SessionStorageKeys.CLI_TERMINAL_TOKEN, + JSON.stringify({ + expiry: formatISO(addSeconds(new Date(), 30)), + data: window.btoa(JSON.stringify(payload)) + }) + ); }); + router.push("/cli-redirect"); + return; } await navigateUserToOrg(router, organizationId); } diff --git a/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx b/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx index 297c20bf8..661c8505e 100644 --- a/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx +++ b/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo } from "react"; +import { useMemo } from "react"; import Head from "next/head"; import Image from "next/image"; import Link from "next/link"; @@ -20,7 +20,7 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean const [hashedHex, key] = urlEncodedPublicKey ? urlEncodedPublicKey.toString().split("-") : ["", ""]; - + const publicKey = decodeURIComponent(urlEncodedPublicKey as string); const { isLoading, data } = useGetActiveSharedSecretByIdAndHashedHex( id as string, @@ -46,12 +46,6 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean initialState: false }); - useEffect(() => { - if (isUrlCopied) { - setTimeout(() => setIsUrlCopied(false), 2000); - } - }, [isUrlCopied]); - const copyUrlToClipboard = () => { navigator.clipboard.writeText(decryptedSecret); setIsUrlCopied(true); @@ -59,12 +53,12 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean const { popUp, handlePopUpToggle } = usePopUp(["createSharedSecret"] as const); return ( -
+
Secret Shared | Infisical -
+
@@ -77,9 +71,15 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean />
-
-

- {id ? "Someone shared a secret via Infisical with you" : "Share a secret via Infisical"} +
+

+ {id + ? "Someone shared a secret via Infisical with you" + : "Share a secret via Infisical"}

@@ -114,7 +114,7 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean className="mt-3 w-full text-sm font-normal leading-[1.2rem] text-mineshaft-300 hover:text-mineshaft-100" >
)} -
+
-
-
-

- Open source secret management for developers +

+
+

+ Open source{" "} + + secret management + {" "} + for developers

-
+

Infisical - {" "} is the all-in-one secret management platform to securely manage secrets, configs, and certificates across your team and infrastructure. + {" "} + is the all-in-one secret management platform to securely manage secrets, configs, + and certificates across your team and infrastructure.

- - Try Infisical + + Try Infisical
- +
From eb45bed7d9e9d3b64998b374ee87cb3cc15719a2 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 21 Jul 2024 22:34:23 +0530 Subject: [PATCH 3/4] feat: updated text over cli --- cli/packages/cmd/login.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 720c33dbf..2f85719fe 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -717,19 +717,13 @@ func askForMFACode() string { func askToPasteJwtToken(stdin *readline.CancelableStdin, success chan models.UserCredentials, failure chan error) { time.Sleep(time.Second * 5) - prompt := &promptui.Prompt{ - Label: "Did you see a prompt in your browser asking you to paste a token?", - IsConfirm: true, - Stdin: stdin, + Label: "Press ENTER to paste your token manually", + Stdin: stdin, } _, err := prompt.Run() if err != nil { - if errors.Is(err, promptui.ErrAbort) { - stdin.Close() - return - } failure <- err return } @@ -747,7 +741,8 @@ func askToPasteJwtToken(stdin *readline.CancelableStdin, success chan models.Use userCredentials, err := decodePastedBase64Token(infisicalPastedToken) if err != nil { - failure <- err + fmt.Println("Invalid user credentials provided", err) + os.Exit(1) return } success <- *userCredentials From 8b10cf863d62a6c6d378d6525e02daf460c3ffbd Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Sun, 21 Jul 2024 23:35:09 -0400 Subject: [PATCH 4/4] add verify jwt, update text phrasing and fix double render input field --- cli/go.mod | 10 +++--- cli/go.sum | 24 +++++++------- cli/packages/cmd/login.go | 50 ++++++++++++++--------------- frontend/src/pages/cli-redirect.tsx | 12 +++---- 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/cli/go.mod b/cli/go.mod index 4f37e1232..045b2d287 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/bradleyjkemp/cupaloy/v2 v2.8.0 - github.com/charmbracelet/lipgloss v0.5.0 + github.com/charmbracelet/lipgloss v0.9.1 github.com/chzyer/readline v1.5.1 github.com/creack/pty v1.1.21 github.com/denisbrodbeck/machineid v1.0.1 @@ -12,13 +12,12 @@ require ( github.com/gitleaks/go-gitdiff v0.8.0 github.com/h2non/filetype v1.1.3 github.com/infisical/go-sdk v0.3.0 - github.com/mattn/go-isatty v0.0.14 + github.com/mattn/go-isatty v0.0.18 github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a github.com/muesli/mango-cobra v1.2.0 github.com/muesli/reflow v0.3.0 github.com/muesli/roff v0.1.0 github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a github.com/rs/cors v1.11.0 github.com/rs/zerolog v1.26.1 @@ -50,6 +49,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect github.com/aws/smithy-go v1.20.2 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect @@ -69,12 +69,12 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/mattn/go-colorable v0.1.9 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/muesli/mango v0.1.0 // indirect github.com/muesli/mango-pflag v0.1.0 // indirect - github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 // indirect + github.com/muesli/termenv v0.15.2 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml v1.9.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/cli/go.sum b/cli/go.sum index fd08b3f1a..2aa6a446e 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -83,13 +83,15 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= -github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= +github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= +github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -292,13 +294,12 @@ github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69Y github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -324,13 +325,12 @@ github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbY github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= -github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= -github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 h1:STjmj0uFfRryL9fzRA/OupNppeAID6QJYPMavTL7jtY= -github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= @@ -340,8 +340,6 @@ github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5d github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= @@ -612,13 +610,13 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 2f85719fe..18d2d5a7b 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -28,7 +28,6 @@ import ( "github.com/fatih/color" "github.com/go-resty/resty/v2" "github.com/manifoldco/promptui" - "github.com/pkg/browser" "github.com/posthog/posthog-go" "github.com/rs/cors" "github.com/rs/zerolog/log" @@ -227,10 +226,9 @@ var loginCmd = &cobra.Command{ //call browser login function if !interactiveLogin { - fmt.Println("Logging in via browser... To login via interactive mode run [infisical login -i]") userCredentialsToBeStored, err = browserCliLogin() if err != nil { - fmt.Printf("Logging in via browser failed. %s", err.Error()) + fmt.Printf("Login via browser failed. %s", err.Error()) //default to cli login on error cliDefaultLogin(&userCredentialsToBeStored) } @@ -717,34 +715,38 @@ func askForMFACode() string { func askToPasteJwtToken(stdin *readline.CancelableStdin, success chan models.UserCredentials, failure chan error) { time.Sleep(time.Second * 5) - prompt := &promptui.Prompt{ - Label: "Press ENTER to paste your token manually", - Stdin: stdin, - } + fmt.Println("\n\nOnce login is completed via browser, the CLI should be authenticated automatically.") + fmt.Println("However, if browser fails to communicate with the CLI, please paste the token from the browser below.") - _, err := prompt.Run() + fmt.Print("\n\nToken: ") + bytePassword, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { failure <- err - return + fmt.Println("\nError reading input:", err) + os.Exit(1) } - prompt = &promptui.Prompt{ - Label: "Paste your token", - Mask: '*', - Stdin: stdin, - } - infisicalPastedToken, err := prompt.Run() - if err != nil { - failure <- err - return - } + infisicalPastedToken := strings.TrimSpace(string(bytePassword)) userCredentials, err := decodePastedBase64Token(infisicalPastedToken) if err != nil { + failure <- err fmt.Println("Invalid user credentials provided", err) os.Exit(1) - return } + + // verify JTW + httpClient := resty.New(). + SetAuthToken(userCredentials.JTWToken). + SetHeader("Accept", "application/json") + + isAuthenticated := api.CallIsAuthenticated(httpClient) + if !isAuthenticated { + fmt.Println("Invalid user credentials provided", err) + failure <- err + os.Exit(1) + } + success <- *userCredentials } @@ -778,11 +780,7 @@ func browserCliLogin() (models.UserCredentials, error) { callbackPort := listener.Addr().(*net.TCPAddr).Port url := fmt.Sprintf("%s?callback_port=%d", config.INFISICAL_LOGIN_URL, callbackPort) - //open browser and login - err = browser.OpenURL(url) - if err != nil { - return models.UserCredentials{}, err - } + fmt.Printf("\n\nTo complete your login, open this address in your browser: %v \n", url) //flow channels success := make(chan models.UserCredentials) @@ -818,7 +816,7 @@ func browserCliLogin() (models.UserCredentials, error) { case loginResponse := <-success: _ = closeListener(&listener) _ = stdin.Close() - fmt.Println("Browser login successfull") + fmt.Println("Browser login successful") return loginResponse, nil case err := <-failure: diff --git a/frontend/src/pages/cli-redirect.tsx b/frontend/src/pages/cli-redirect.tsx index c617e9fb2..3838edd5a 100644 --- a/frontend/src/pages/cli-redirect.tsx +++ b/frontend/src/pages/cli-redirect.tsx @@ -49,10 +49,13 @@ export default function CliRedirect() { <>

- Login successful! + Unable to reach CLI

-

- However, your token could not be sent to the CLI +

+ Your login was successful but, Infisical couldn't automatically push your login token to the CLI. +

+

+ Please copy the token below and manually provide it to your CLI.

@@ -70,9 +73,6 @@ export default function CliRedirect() {
-

- After copying, return to terminal screen and paste it there -

) : ( <>