diff --git a/packages/hoppscotch-common/src/composables/oauth2/useOAuth2GrantTypes.ts b/packages/hoppscotch-common/src/composables/oauth2/useOAuth2GrantTypes.ts index edb650b8..f46fc923 100644 --- a/packages/hoppscotch-common/src/composables/oauth2/useOAuth2GrantTypes.ts +++ b/packages/hoppscotch-common/src/composables/oauth2/useOAuth2GrantTypes.ts @@ -178,6 +178,9 @@ export const useOAuth2GrantTypes = ( id: "plain" | "S256" label: string } | null> = refWithCallbackOnChange( + // If the collection was imported before `codeVerifierMethod` existed, + // default to 'plain' when PKCE is enabled so the UI and validation + // remain consistent. auth.value.grantTypeInfo.codeVerifierMethod ? { id: auth.value.grantTypeInfo.codeVerifierMethod, @@ -186,7 +189,12 @@ export const useOAuth2GrantTypes = ( ? "Plain" : "SHA-256", } - : null, + : auth.value.grantTypeInfo.isPKCE + ? { + id: "plain", + label: "Plain", + } + : null, (value) => { if (!("codeVerifierMethod" in auth.value.grantTypeInfo) || !value) { return @@ -249,7 +257,12 @@ export const useOAuth2GrantTypes = ( clientSecret: clientSecret.value, scopes: scopes.value, isPKCE: isPKCE.value, - codeVerifierMethod: codeChallenge.value?.id, + // Ensure older collections without `codeVerifierMethod` get a default + // so schema validation does not fail. Default to 'plain' when PKCE + // is enabled. + codeVerifierMethod: + codeChallenge.value?.id ?? + (isPKCE.value ? ("plain" as const) : undefined), authRequestParams: preparedAuthRequestParams.value, tokenRequestParams: preparedTokenRequestParams.value, refreshRequestParams: preparedRefreshRequestParams.value, diff --git a/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts b/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts index b7136699..623bd539 100644 --- a/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts +++ b/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts @@ -303,6 +303,31 @@ const getHoppReqAuth = ( const token = replacePMVarTemplating( getVariableValue(auth.oauth2, "accessToken") ?? "" ) + const clientSecret = replacePMVarTemplating( + getVariableValue(auth.oauth2, "clientSecret") ?? "" + ) + + // Check for PKCE settings + const usePkce = getVariableValue(auth.oauth2, "usePkce") + const isPKCE = usePkce === "true" + + // Get challenge algorithm, default to S256 if PKCE is enabled but no algorithm specified + const challengeAlgorithm = getVariableValue( + auth.oauth2, + "challengeAlgorithm" + ) + let codeVerifierMethod: "plain" | "S256" | undefined + + if (isPKCE) { + // Postman uses "SHA-256" or "plain" - normalize to our format + // Default to S256 for any value other than "plain" + if (challengeAlgorithm === "plain") { + codeVerifierMethod = "plain" + } else { + // Covers "S256", "SHA-256", undefined, and any other value + codeVerifierMethod = "S256" + } + } return { authType: "oauth-2", @@ -314,8 +339,9 @@ const getHoppReqAuth = ( scopes: scope, token: token, tokenEndpoint: accessTokenURL, - clientSecret: "", - isPKCE: false, + clientSecret: clientSecret, + isPKCE: isPKCE, + ...(codeVerifierMethod ? { codeVerifierMethod } : {}), authRequestParams: [], tokenRequestParams: [], refreshRequestParams: [], diff --git a/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts b/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts index 2558b0db..b3ba218d 100644 --- a/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts +++ b/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts @@ -91,11 +91,19 @@ const initAuthCodeOauthFlow = async ({ let codeVerifier: string | undefined let codeChallenge: string | undefined + // Ensure backward compatibility for collections that were imported before + // `codeVerifierMethod` was added. If PKCE is enabled but the method is + // missing, default to 'plain' as requested by the user. + const codeVerifierMethodNormalized = + isPKCE && !codeVerifierMethod ? ("plain" as const) : codeVerifierMethod + if (isPKCE) { codeVerifier = generateCodeVerifier() + // codeVerifierMethodNormalized might be undefined only if isPKCE is false, + // but here we guard with isPKCE so it's safe to pass a value. codeChallenge = await generateCodeChallenge( codeVerifier, - codeVerifierMethod + codeVerifierMethodNormalized ) } @@ -137,7 +145,8 @@ const initAuthCodeOauthFlow = async ({ clientSecret, clientID, isPKCE, - codeVerifierMethod, + // Persist the normalized method so subsequent redirect handling has a value + codeVerifierMethod: codeVerifierMethodNormalized, scopes, authRequestParams, refreshRequestParams,