Merge pull request #601 from Infisical/add-refresh-token-cli

add refresh token to cli
This commit is contained in:
Maidul Islam
2023-05-24 18:53:52 -04:00
committed by GitHub
6 changed files with 70 additions and 22 deletions

View File

@ -2,6 +2,7 @@ package api
import (
"fmt"
"net/http"
"github.com/Infisical/infisical-merge/packages/config"
"github.com/go-resty/resty/v2"
@ -179,6 +180,19 @@ func CallLogin2V2(httpClient *resty.Client, request GetLoginTwoV2Request) (GetLo
SetBody(request).
Post(fmt.Sprintf("%v/v2/auth/login2", config.INFISICAL_URL))
cookies := response.Cookies()
// Find a cookie by name
cookieName := "jid"
var refreshToken *http.Cookie
for _, cookie := range cookies {
if cookie.Name == cookieName {
refreshToken = cookie
break
}
}
loginTwoV2Response.RefreshToken = refreshToken.Value
if err != nil {
return GetLoginTwoV2Response{}, fmt.Errorf("CallLogin2V2: Unable to complete api request [err=%s]", err)
}
@ -247,3 +261,26 @@ func CallGetAccessibleEnvironments(httpClient *resty.Client, request GetAccessib
return accessibleEnvironmentsResponse, nil
}
func CallGetNewAccessTokenWithRefreshToken(httpClient *resty.Client, refreshToken string) (GetNewAccessTokenWithRefreshTokenResponse, error) {
var newAccessToken GetNewAccessTokenWithRefreshTokenResponse
response, err := httpClient.
R().
SetResult(&newAccessToken).
SetHeader("User-Agent", USER_AGENT).
SetCookie(&http.Cookie{
Name: "jid",
Value: refreshToken,
}).
Post(fmt.Sprintf("%v/v1/auth/token", config.INFISICAL_URL))
if err != nil {
return GetNewAccessTokenWithRefreshTokenResponse{}, err
}
if response.IsError() {
return GetNewAccessTokenWithRefreshTokenResponse{}, fmt.Errorf("CallGetNewAccessTokenWithRefreshToken: Unsuccessful response: [response=%v]", response)
}
return newAccessToken, nil
}

View File

@ -281,6 +281,7 @@ type GetLoginTwoV2Response struct {
ProtectedKey string `json:"protectedKey"`
ProtectedKeyIV string `json:"protectedKeyIV"`
ProtectedKeyTag string `json:"protectedKeyTag"`
RefreshToken string `json:"RefreshToken"`
}
type VerifyMfaTokenRequest struct {
@ -314,3 +315,7 @@ type VerifyMfaTokenErrorResponse struct {
Application string `json:"application"`
Extra []interface{} `json:"extra"`
}
type GetNewAccessTokenWithRefreshTokenResponse struct {
Token string `json:"token"`
}

View File

@ -97,7 +97,7 @@ var loginCmd = &cobra.Command{
loginOneResponse, loginTwoResponse, err := getFreshUserCredentials(email, password)
if err != nil {
fmt.Println("Unable to authenticate with the provided credentials, please try again")
log.Warn().Msg("Unable to authenticate with the provided credentials, please ensure your email and password are correct")
log.Debug().Err(err)
return
}
@ -244,9 +244,10 @@ var loginCmd = &cobra.Command{
}
userCredentialsToBeStored := &models.UserCredentials{
Email: email,
PrivateKey: string(decryptedPrivateKey),
JTWToken: loginTwoResponse.Token,
Email: email,
PrivateKey: string(decryptedPrivateKey),
JTWToken: loginTwoResponse.Token,
RefreshToken: loginTwoResponse.RefreshToken,
}
err = util.StoreUserCredsInKeyRing(userCredentialsToBeStored)
@ -414,7 +415,7 @@ func getFreshUserCredentials(email string, password string) (*api.GetLoginOneV2R
})
if err != nil {
util.HandleError(err)
return nil, nil, err
}
// **** Login 2

View File

@ -5,9 +5,10 @@ import (
)
type UserCredentials struct {
Email string `json:"email"`
PrivateKey string `json:"privateKey"`
JTWToken string `json:"JTWToken"`
Email string `json:"email"`
PrivateKey string `json:"privateKey"`
JTWToken string `json:"JTWToken"`
RefreshToken string `json:"RefreshToken"`
}
// The file struct for Infisical config file

View File

@ -9,6 +9,7 @@ import (
"github.com/Infisical/infisical-merge/packages/config"
"github.com/Infisical/infisical-merge/packages/models"
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log"
)
type LoggedInUserDetails struct {
@ -96,6 +97,20 @@ func GetCurrentLoggedInUserDetails() (LoggedInUserDetails, error) {
}
isAuthenticated := api.CallIsAuthenticated(httpClient)
if !isAuthenticated {
accessTokenResponse, _ := api.CallGetNewAccessTokenWithRefreshToken(httpClient, userCreds.RefreshToken)
if accessTokenResponse.Token != "" {
isAuthenticated = true
userCreds.JTWToken = accessTokenResponse.Token
}
}
err = StoreUserCredsInKeyRing(&userCreds)
if err != nil {
log.Debug().Msg("unable to store your user credentials with new access token")
}
if !isAuthenticated {
return LoggedInUserDetails{
IsUserLoggedIn: true, // was logged in

View File

@ -74,23 +74,12 @@ func ConfigContainsEmail(users []models.LoggedInUser, email string) bool {
}
func RequireLogin() {
currentUserDetails, err := GetCurrentLoggedInUserDetails()
// get the config file that stores the current logged in user email
configFile, _ := GetConfigFile()
if err != nil {
HandleError(err, "unable to retrieve your login details")
}
if !currentUserDetails.IsUserLoggedIn {
if configFile.LoggedInUserEmail == "" {
PrintErrorMessageAndExit("You must be logged in to run this command. To login, run [infisical login]")
}
if currentUserDetails.LoginExpired {
PrintErrorMessageAndExit("Your login expired, please login in again. To login, run [infisical login]")
}
if currentUserDetails.UserCredentials.Email == "" && currentUserDetails.UserCredentials.JTWToken == "" && currentUserDetails.UserCredentials.PrivateKey == "" {
PrintErrorMessageAndExit("One or more of your login details is empty. Please try logging in again via by running [infisical login]")
}
}
func RequireServiceToken() {