mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #2175 from akhilmhdh/feat/cli-login-fallback-missing
Missing paste token option in CLI brower login flow
This commit is contained in:
@@ -24,7 +24,6 @@ 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"
|
||||
@@ -205,6 +204,7 @@ var loginCmd = &cobra.Command{
|
||||
if !overrideDomain {
|
||||
domainQuery = false
|
||||
config.INFISICAL_URL = util.AppendAPIEndpoint(config.INFISICAL_URL_MANUAL_OVERRIDE)
|
||||
config.INFISICAL_LOGIN_URL = fmt.Sprintf("%s/login", strings.TrimSuffix(config.INFISICAL_URL, "/api"))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -713,7 +713,7 @@ func askForMFACode() string {
|
||||
return mfaVerifyCode
|
||||
}
|
||||
|
||||
func askToPasteJwtToken(stdin *readline.CancelableStdin, success chan models.UserCredentials, failure chan error) {
|
||||
func askToPasteJwtToken(success chan models.UserCredentials, failure chan error) {
|
||||
time.Sleep(time.Second * 5)
|
||||
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.")
|
||||
@@ -807,26 +807,22 @@ 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)
|
||||
go askToPasteJwtToken(success, failure)
|
||||
|
||||
for {
|
||||
select {
|
||||
case loginResponse := <-success:
|
||||
_ = closeListener(&listener)
|
||||
_ = stdin.Close()
|
||||
fmt.Println("Browser login successful")
|
||||
return loginResponse, nil
|
||||
|
||||
case err := <-failure:
|
||||
serverErr := closeListener(&listener)
|
||||
stdErr := stdin.Close()
|
||||
return models.UserCredentials{}, errors.Join(err, serverErr, stdErr)
|
||||
return models.UserCredentials{}, errors.Join(err, serverErr)
|
||||
|
||||
case <-timeout:
|
||||
_ = closeListener(&listener)
|
||||
_ = stdin.Close()
|
||||
return models.UserCredentials{}, errors.New("server timeout")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,16 +168,27 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
|
||||
const { token: newJwtToken } = await selectOrganization({ organizationId });
|
||||
|
||||
const instance = axios.create();
|
||||
await instance.post(cliUrl, {
|
||||
const payload = {
|
||||
...isCliLoginSuccessful.loginResponse,
|
||||
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))
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
await navigateUserToOrg(router, organizationId);
|
||||
router.push("/cli-redirect");
|
||||
return;
|
||||
}
|
||||
// case: no organization ID is present -- navigate to the select org page IF the user has any orgs
|
||||
// if the user has no orgs, navigate to the create org page
|
||||
else {
|
||||
|
||||
const userOrgs = await fetchOrganizations();
|
||||
|
||||
// case: user has orgs, so we navigate the user to select an org
|
||||
@@ -189,7 +200,7 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
|
||||
else {
|
||||
await navigateUserToOrg(router);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
const isLoginSuccessful = await attemptLoginMfa({
|
||||
|
||||
@@ -4,6 +4,7 @@ import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import HCaptcha from "@hcaptcha/react-hcaptcha";
|
||||
import axios from "axios";
|
||||
import { addSeconds, formatISO } from "date-fns";
|
||||
import jwt_decode from "jwt-decode";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
@@ -12,6 +13,7 @@ import attemptLogin from "@app/components/utilities/attemptLogin";
|
||||
import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config";
|
||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
import { Button, Input, Spinner } from "@app/components/v2";
|
||||
import { SessionStorageKeys } from "@app/const";
|
||||
import { useOauthTokenExchange, useSelectOrganization } from "@app/hooks/api";
|
||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||
import { fetchMyPrivateKey } from "@app/hooks/api/users/queries";
|
||||
@@ -79,11 +81,24 @@ export const PasswordStep = ({
|
||||
if (callbackPort) {
|
||||
console.log("organization id was present. new JWT token to be used in CLI:", newJwtToken);
|
||||
const instance = axios.create();
|
||||
await instance.post(cliUrl, {
|
||||
const payload = {
|
||||
privateKey,
|
||||
email,
|
||||
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);
|
||||
@@ -165,26 +180,35 @@ export const PasswordStep = ({
|
||||
);
|
||||
|
||||
const instance = axios.create();
|
||||
await instance.post(cliUrl, {
|
||||
const payload = {
|
||||
...isCliLoginSuccessful.loginResponse,
|
||||
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))
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
await navigateUserToOrg(router, organizationId);
|
||||
router.push("/cli-redirect");
|
||||
return;
|
||||
}
|
||||
// case: no organization ID is present -- navigate to the select org page IF the user has any orgs
|
||||
// if the user has no orgs, navigate to the create org page
|
||||
else {
|
||||
const userOrgs = await fetchOrganizations();
|
||||
const userOrgs = await fetchOrganizations();
|
||||
|
||||
// case: user has orgs, so we navigate the user to select an org
|
||||
if (userOrgs.length > 0) {
|
||||
navigateToSelectOrganization(callbackPort);
|
||||
}
|
||||
// case: no orgs found, so we navigate the user to create an org
|
||||
else {
|
||||
await navigateUserToOrg(router);
|
||||
}
|
||||
// case: user has orgs, so we navigate the user to select an org
|
||||
if (userOrgs.length > 0) {
|
||||
navigateToSelectOrganization(callbackPort);
|
||||
}
|
||||
// case: no orgs found, so we navigate the user to create an org
|
||||
else {
|
||||
await navigateUserToOrg(router);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user