mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 01:26:09 +00:00
Fix CLI refresh token functionality + reduce token lifetime to 1d & 14d
for refresh
This commit is contained in:
@@ -101,9 +101,9 @@ const envSchema = z
|
|||||||
LOOPS_API_KEY: zpStr(z.string().optional()),
|
LOOPS_API_KEY: zpStr(z.string().optional()),
|
||||||
// jwt options
|
// jwt options
|
||||||
AUTH_SECRET: zpStr(z.string()).default(process.env.JWT_AUTH_SECRET), // for those still using old JWT_AUTH_SECRET
|
AUTH_SECRET: zpStr(z.string()).default(process.env.JWT_AUTH_SECRET), // for those still using old JWT_AUTH_SECRET
|
||||||
JWT_AUTH_LIFETIME: zpStr(z.string().default("10d")),
|
JWT_AUTH_LIFETIME: zpStr(z.string().default("1d")),
|
||||||
JWT_SIGNUP_LIFETIME: zpStr(z.string().default("15m")),
|
JWT_SIGNUP_LIFETIME: zpStr(z.string().default("15m")),
|
||||||
JWT_REFRESH_LIFETIME: zpStr(z.string().default("90d")),
|
JWT_REFRESH_LIFETIME: zpStr(z.string().default("14d")),
|
||||||
JWT_INVITE_LIFETIME: zpStr(z.string().default("1d")),
|
JWT_INVITE_LIFETIME: zpStr(z.string().default("1d")),
|
||||||
JWT_MFA_LIFETIME: zpStr(z.string().default("5m")),
|
JWT_MFA_LIFETIME: zpStr(z.string().default("5m")),
|
||||||
JWT_PROVIDER_AUTH_LIFETIME: zpStr(z.string().default("15m")),
|
JWT_PROVIDER_AUTH_LIFETIME: zpStr(z.string().default("15m")),
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
|||||||
server.addHook("onRequest", async (req) => {
|
server.addHook("onRequest", async (req) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|
||||||
if (req.url.includes(".well-known/est") || req.url.includes("/api/v3/auth/")) {
|
if (req.url.includes(".well-known/est") || req.url.includes("/api/v3/auth/") || req.url === "/api/v1/auth/token") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
200: z.object({
|
200: z.object({
|
||||||
token: z.string(),
|
token: z.string(),
|
||||||
isMfaEnabled: z.boolean(),
|
isMfaEnabled: z.boolean(),
|
||||||
mfaMethod: z.string().optional()
|
mfaMethod: z.string().optional(),
|
||||||
|
refreshToken: z.string().optional()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -101,7 +102,7 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
maxAge: 0
|
maxAge: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
return { token: tokens.access, isMfaEnabled: false };
|
return { token: tokens.access, isMfaEnabled: false, refreshToken: tokens.refresh };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -129,7 +130,8 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
encryptedPrivateKey: z.string(),
|
encryptedPrivateKey: z.string(),
|
||||||
iv: z.string(),
|
iv: z.string(),
|
||||||
tag: z.string(),
|
tag: z.string(),
|
||||||
token: z.string()
|
token: z.string(),
|
||||||
|
refreshToken: z.string().optional()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -172,7 +174,8 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
tag: data.user.tag,
|
tag: data.user.tag,
|
||||||
protectedKey: data.user.protectedKey || null,
|
protectedKey: data.user.protectedKey || null,
|
||||||
protectedKeyIV: data.user.protectedKeyIV || null,
|
protectedKeyIV: data.user.protectedKeyIV || null,
|
||||||
protectedKeyTag: data.user.protectedKeyTag || null
|
protectedKeyTag: data.user.protectedKeyTag || null,
|
||||||
|
refreshToken: data.token.refresh
|
||||||
} as const;
|
} as const;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ type GetLoginTwoV2Response struct {
|
|||||||
ProtectedKey string `json:"protectedKey"`
|
ProtectedKey string `json:"protectedKey"`
|
||||||
ProtectedKeyIV string `json:"protectedKeyIV"`
|
ProtectedKeyIV string `json:"protectedKeyIV"`
|
||||||
ProtectedKeyTag string `json:"protectedKeyTag"`
|
ProtectedKeyTag string `json:"protectedKeyTag"`
|
||||||
RefreshToken string `json:"RefreshToken"`
|
RefreshToken string `json:"refreshToken"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VerifyMfaTokenRequest struct {
|
type VerifyMfaTokenRequest struct {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ var loginCmd = &cobra.Command{
|
|||||||
infisicalClient := infisicalSdk.NewInfisicalClient(context.Background(), infisicalSdk.Config{
|
infisicalClient := infisicalSdk.NewInfisicalClient(context.Background(), infisicalSdk.Config{
|
||||||
SiteUrl: config.INFISICAL_URL,
|
SiteUrl: config.INFISICAL_URL,
|
||||||
UserAgent: api.USER_AGENT,
|
UserAgent: api.USER_AGENT,
|
||||||
AutoTokenRefresh: false,
|
AutoTokenRefresh: true,
|
||||||
CustomHeaders: customHeaders,
|
CustomHeaders: customHeaders,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -438,6 +438,7 @@ func cliDefaultLogin(userCredentialsToBeStored *models.UserCredentials) {
|
|||||||
userCredentialsToBeStored.Email = email
|
userCredentialsToBeStored.Email = email
|
||||||
userCredentialsToBeStored.PrivateKey = string(decryptedPrivateKey)
|
userCredentialsToBeStored.PrivateKey = string(decryptedPrivateKey)
|
||||||
userCredentialsToBeStored.JTWToken = newJwtToken
|
userCredentialsToBeStored.JTWToken = newJwtToken
|
||||||
|
userCredentialsToBeStored.RefreshToken = loginTwoResponse.RefreshToken
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ type UserCredentials struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
PrivateKey string `json:"privateKey"`
|
PrivateKey string `json:"privateKey"`
|
||||||
JTWToken string `json:"JTWToken"`
|
JTWToken string `json:"JTWToken"`
|
||||||
RefreshToken string `json:"RefreshToken"`
|
RefreshToken string `json:"refreshToken"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The file struct for Infisical config file
|
// The file struct for Infisical config file
|
||||||
|
|||||||
@@ -94,19 +94,15 @@ func GetCurrentLoggedInUserDetails(setConfigVariables bool) (LoggedInUserDetails
|
|||||||
SetHeader("Accept", "application/json")
|
SetHeader("Accept", "application/json")
|
||||||
|
|
||||||
isAuthenticated := api.CallIsAuthenticated(httpClient)
|
isAuthenticated := api.CallIsAuthenticated(httpClient)
|
||||||
// TODO: add refresh token
|
if !isAuthenticated {
|
||||||
// if !isAuthenticated {
|
accessTokenResponse, refreshErr := api.CallGetNewAccessTokenWithRefreshToken(httpClient, userCreds.RefreshToken)
|
||||||
// accessTokenResponse, err := api.CallGetNewAccessTokenWithRefreshToken(httpClient, userCreds.RefreshToken)
|
if refreshErr == nil && accessTokenResponse.Token != "" {
|
||||||
// if err == nil && accessTokenResponse.Token != "" {
|
isAuthenticated = true
|
||||||
// isAuthenticated = true
|
userCreds.JTWToken = accessTokenResponse.Token
|
||||||
// userCreds.JTWToken = accessTokenResponse.Token
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// err = StoreUserCredsInKeyRing(&userCreds)
|
_ = StoreUserCredsInKeyRing(&userCreds)
|
||||||
// if err != nil {
|
|
||||||
// log.Debug().Msg("unable to store your user credentials with new access token")
|
|
||||||
// }
|
|
||||||
|
|
||||||
if !isAuthenticated {
|
if !isAuthenticated {
|
||||||
return LoggedInUserDetails{
|
return LoggedInUserDetails{
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export const selectOrganization = async (data: {
|
|||||||
}) => {
|
}) => {
|
||||||
const { data: res } = await apiRequest.post<{
|
const { data: res } = await apiRequest.post<{
|
||||||
token: string;
|
token: string;
|
||||||
|
refreshToken: string;
|
||||||
isMfaEnabled: boolean;
|
isMfaEnabled: boolean;
|
||||||
mfaMethod?: MfaMethod;
|
mfaMethod?: MfaMethod;
|
||||||
}>("/api/v3/auth/select-organization", data);
|
}>("/api/v3/auth/select-organization", data);
|
||||||
|
|||||||
@@ -76,7 +76,9 @@ export const PasswordStep = ({
|
|||||||
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
||||||
if (organizationId) {
|
if (organizationId) {
|
||||||
const finishWithOrgWorkflow = async () => {
|
const finishWithOrgWorkflow = async () => {
|
||||||
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({ organizationId });
|
const { token, isMfaEnabled, mfaMethod, refreshToken } = await selectOrganization({
|
||||||
|
organizationId
|
||||||
|
});
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
@@ -94,10 +96,11 @@ export const PasswordStep = ({
|
|||||||
const payload = {
|
const payload = {
|
||||||
privateKey,
|
privateKey,
|
||||||
email,
|
email,
|
||||||
JTWToken: token
|
JTWToken: token,
|
||||||
|
refreshToken
|
||||||
};
|
};
|
||||||
await instance.post(cliUrl, payload).catch(() => {
|
await instance.post(cliUrl, payload).catch(() => {
|
||||||
// if error happens to communicate we set the token with an expiry in sessino storage
|
// if error happens to communicate we set the token with an expiry in session storage
|
||||||
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(
|
||||||
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
||||||
@@ -187,7 +190,7 @@ export const PasswordStep = ({
|
|||||||
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
||||||
if (organizationId) {
|
if (organizationId) {
|
||||||
const finishWithOrgWorkflow = async () => {
|
const finishWithOrgWorkflow = async () => {
|
||||||
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({
|
const { token, isMfaEnabled, mfaMethod, refreshToken } = await selectOrganization({
|
||||||
organizationId
|
organizationId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -206,10 +209,11 @@ export const PasswordStep = ({
|
|||||||
const instance = axios.create();
|
const instance = axios.create();
|
||||||
const payload = {
|
const payload = {
|
||||||
...isCliLoginSuccessful.loginResponse,
|
...isCliLoginSuccessful.loginResponse,
|
||||||
JTWToken: token
|
JTWToken: token,
|
||||||
|
refreshToken
|
||||||
};
|
};
|
||||||
await instance.post(cliUrl, payload).catch(() => {
|
await instance.post(cliUrl, payload).catch(() => {
|
||||||
// if error happens to communicate we set the token with an expiry in sessino storage
|
// if error happens to communicate we set the token with an expiry in session storage
|
||||||
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(
|
||||||
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export const SelectOrganizationSection = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { token, isMfaEnabled, mfaMethod } = await selectOrg
|
const { token, isMfaEnabled, mfaMethod, refreshToken } = await selectOrg
|
||||||
.mutateAsync({
|
.mutateAsync({
|
||||||
organizationId: organization.id,
|
organizationId: organization.id,
|
||||||
userAgent: callbackPort ? UserAgentType.CLI : undefined
|
userAgent: callbackPort ? UserAgentType.CLI : undefined
|
||||||
@@ -151,13 +151,14 @@ export const SelectOrganizationSection = () => {
|
|||||||
const payload = {
|
const payload = {
|
||||||
JTWToken: token,
|
JTWToken: token,
|
||||||
email: user?.email,
|
email: user?.email,
|
||||||
privateKey
|
privateKey,
|
||||||
|
refreshToken
|
||||||
} as IsCliLoginSuccessful["loginResponse"];
|
} as IsCliLoginSuccessful["loginResponse"];
|
||||||
|
|
||||||
// send request to server endpoint
|
// send request to server endpoint
|
||||||
const instance = axios.create();
|
const instance = axios.create();
|
||||||
await instance.post(`http://127.0.0.1:${callbackPort}/`, payload).catch(() => {
|
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
|
// if error happens to communicate we set the token with an expiry in session storage
|
||||||
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
// the cli-redirect page has logic to show this to user and ask them to paste it in terminal
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(
|
||||||
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
SessionStorageKeys.CLI_TERMINAL_TOKEN,
|
||||||
|
|||||||
Reference in New Issue
Block a user