Repository: kinde-oss/js-utils
Pull request #123: feat: support reauth functionality
Author: login: DanielRivers
Created: 2025-05-16T15:50:56Z | Merged: 2025-05-19T13:28:49Z

# Explain your changes

This adds support for reauth, this allows JS libraries to recover and restart auth when auth page has been bookmarked

# Checklist

- [x] I have read the [“Pull requests” section](https://github.com/kinde-oss/.github/blob/main/.github/CONTRIBUTING.md#pull-requests) in the [contributing guidelines](https://github.com/kinde-oss/.github/blob/main/.github/CONTRIBUTING.md).
- [x] I agree to the terms within the [code of conduct](https://github.com/kinde-oss/.github/blob/main/.github/CODE_OF_CONDUCT.md).

🛟 _If you need help, consider asking for advice over in the [Kinde community](https://thekindecommunity.slack.com)._



Diff:
diff --git a/lib/types.ts b/lib/types.ts
index 359fe84b..05c3b4cd 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -29,6 +29,8 @@ export type LoginMethodParams<T = Record<string, string>> = Partial<
     | "hasSuccessPage"
     | "workflowDeploymentId"
     | "properties"
+    | "supportsReauth"
+    | "reauthState"
     | "planInterest"
   >
 >;
@@ -78,7 +80,7 @@ export type LoginOptions<T = Record<string, string>> = {
    *
    * This can be found in the application settings in the Kinde dashboard
    */
-  clientId: string;
+  clientId?: string;
   /**
    * Code challenge for PKCE
    */
@@ -168,6 +170,14 @@ export type LoginOptions<T = Record<string, string>> = {
    * Properties to be passed
    */
   properties?: T & KindeProperties;
+  /**
+   * Define if the auth instigator support reauth on expired flows
+   */
+  supportsReauth?: boolean;
+  /**
+   * Base64 encoded auth parameters
+   */
+  reauthState?: string;
   /**
    * Plan the user has indicated interest in
    */
diff --git a/lib/utils/generateAuthUrl.test.ts b/lib/utils/generateAuthUrl.test.ts
index 0d0f7ae9..1564ad1a 100644
--- a/lib/utils/generateAuthUrl.test.ts
+++ b/lib/utils/generateAuthUrl.test.ts
@@ -382,4 +382,73 @@ describe("generateAuthUrl", () => {
     result.url.searchParams.delete("state");
     expect(result.url.toString()).toBe(expectedUrl);
   });
+
+  it("missing clientId", async () => {
+    const options: LoginOptions = {
+      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
+      redirectURL: "https://example2.com",
+    };
+    const domain = "https://auth.example.com";
+    expect(() =>
+      generateAuthUrl(domain, IssuerRouteTypes.login, options),
+    ).rejects.toThrow(`Error generating auth URL: Client ID missing`);
+  });
+
+  it("throws on non-Base64 reauthState", async () => {
+    const options: LoginOptions = {
+      scope: [Scopes.openid],
+      redirectURL: "https://example.com",
+      reauthState: "!!!", // invalid Base64
+    };
+    const domain = "https://auth.example.com";
+
+    await expect(
+      generateAuthUrl(domain, IssuerRouteTypes.login, options),
+    ).rejects.toThrow(/Error handing reauth state:/);
+  });
+
+  it("invalid reauthState", async () => {
+    const options: LoginOptions = {
+      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
+      redirectURL: "https://example2.com",
+      reauthState: "e3Rlc3Q6MTIz",
+    };
+    const domain = "https://auth.example.com";
+    expect(() =>
+      generateAuthUrl(domain, IssuerRouteTypes.login, options),
+    ).rejects.toThrow(
+      /Error handing reauth state: Expected property name or '}' in JSON/,
+    );
+  });
+
+  it("support reauth state", async () => {
+    const domain = "https://auth.example.com";
+    const options: LoginOptions = {
+      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
+      redirectURL: "https://example2.com",
+      reauthState:
+        "eyJjbGllbnRfaWQiOiJjbGllbnRyZWF1dGgiLCJvcmdfY29kZSI6Im9yZ2NvZGVyZWF1dGgifQ==",
+    };
+
+    const expectedUrl =
+      "https://auth.example.com/oauth2/auth?client_id=clientreauth&response_type=code&redirect_uri=https%3A%2F%2Fexample2.com&audience=&scope=openid+profile+offline&org_code=orgcodereauth&code_challenge_method=S256";
+
+    const result = await generateAuthUrl(
+      domain,
+      IssuerRouteTypes.login,
+      options,
+    );
+    const nonce = result.url.searchParams.get("nonce");
+    expect(nonce).not.toBeNull();
+    expect(nonce!.length).toBe(16);
+    const state = result.url.searchParams.get("state");
+    expect(state).not.toBeNull();
+    expect(state!.length).toBe(32);
+    const codeChallenge = result.url.searchParams.get("code_challenge");
+    expect(codeChallenge!.length).toBeGreaterThanOrEqual(27);
+    result.url.searchParams.delete("code_challenge");
+    result.url.searchParams.delete("nonce");
+    result.url.searchParams.delete("state");
+    expect(result.url.toString()).toBe(expectedUrl);
+  });
 });
diff --git a/lib/utils/generateAuthUrl.ts b/lib/utils/generateAuthUrl.ts
index 875309ff..a3ec7bd4 100644
--- a/lib/utils/generateAuthUrl.ts
+++ b/lib/utils/generateAuthUrl.ts
@@ -2,6 +2,7 @@ import { base64UrlEncode, getInsecureStorage, StorageKeys } from "../main";
 import { IssuerRouteTypes, LoginOptions, PromptTypes } from "../types";
 import { generateRandomString } from "./generateRandomString";
 import { mapLoginMethodParamsForUrl } from "./mapLoginMethodParamsForUrl";
+import { snakeToCamelCase } from "./snakeToCamelCase";
 
 const whiteListedProperties = [
   // UTM tags
@@ -65,6 +66,28 @@ export const generateAuthUrl = async (
 }> => {
   const authPath = `${domain}/oauth2/auth`;
   const activeStorage = getInsecureStorage();
+
+  if (loginOptions.reauthState) {
+    try {
+      const decodedReauthParams: LoginOptions = snakeToCamelCase<LoginOptions>(
+        JSON.parse(atob(loginOptions.reauthState)),
+      );
+      loginOptions = {
+        ...loginOptions,
+        ...decodedReauthParams,
+      };
+      delete loginOptions.reauthState;
+    } catch (ex: unknown) {
+      const errorDescription =
+        ex instanceof Error ? ex.message : "Unknown error";
+      throw new Error(`Error handing reauth state: ${errorDescription}`);
+    }
+  }
+
+  if (!loginOptions.clientId) {
+    throw new Error(`Error generating auth URL: Client ID missing`);
+  }
+
   const searchParams: Record<string, string> = {
     client_id: loginOptions.clientId,
     response_type: loginOptions.responseType || "code",
diff --git a/lib/utils/mapLoginMethodParamsForUrl.test.ts b/lib/utils/mapLoginMethodParamsForUrl.test.ts
index a34b21e0..688fc240 100644
--- a/lib/utils/mapLoginMethodParamsForUrl.test.ts
+++ b/lib/utils/mapLoginMethodParamsForUrl.test.ts
@@ -68,6 +68,22 @@ describe("mapLoginMethodParamsForUrl", () => {
     expect(result).toEqual(expectedOutput);
   });
 
+  it("should map with supports_reauth", () => {
+    const options: Partial<LoginMethodParams> = {
+      supportsReauth: true,
+    };
+
+    const expectedOutput = {
+      scope: "email profile openid offline",
+      audience: "",
+      supports_reauth: "true",
+    };
+
+    const result = mapLoginMethodParamsForUrl(options);
+    console.log(result);
+    expect(result).toEqual(expectedOutput);
+  });
+
   it("should sanitize the redirect URL", () => {
     const options: Partial<LoginMethodParams> = {
       redirectURL: "https://example.com/",
diff --git a/lib/utils/mapLoginMethodParamsForUrl.ts b/lib/utils/mapLoginMethodParamsForUrl.ts
index 75de2e11..8e5ed18a 100644
--- a/lib/utils/mapLoginMethodParamsForUrl.ts
+++ b/lib/utils/mapLoginMethodParamsForUrl.ts
@@ -26,6 +26,7 @@ export const mapLoginMethodParamsForUrl = (
     org_name: options.orgName,
     has_success_page: options.hasSuccessPage?.toString(),
     workflow_deployment_id: options.workflowDeploymentId,
+    supports_reauth: options.supportsReauth?.toString(),
     plan_interest: options.planInterest,
   };
 
diff --git a/lib/utils/snakeToCamelCase.test.ts b/lib/utils/snakeToCamelCase.test.ts
new file mode 100644
index 00000000..e6970e1f
--- /dev/null
+++ b/lib/utils/snakeToCamelCase.test.ts
@@ -0,0 +1,26 @@
+import { describe, expect, it } from "vitest";
+import { snakeToCamelCase } from "./snakeToCamelCase";
+
+describe("snakeToCamelCase", () => {
+  it("converts properties from snake to camelCase", () => {
+    const input = {
+      first_name: "John",
+      lastName: "Doe",
+      contact_info: {
+        phone_number: "123-456-7890",
+        email_address: "john@example.com",
+      },
+      favorite_colors: ["deep_blue", "light_green"],
+    };
+
+    expect(snakeToCamelCase(input)).toStrictEqual({
+      firstName: "John",
+      lastName: "Doe",
+      contactInfo: {
+        phoneNumber: "123-456-7890",
+        emailAddress: "john@example.com",
+      },
+      favoriteColors: ["deep_blue", "light_green"],
+    });
+  });
+});
diff --git a/lib/utils/snakeToCamelCase.ts b/lib/utils/snakeToCamelCase.ts
new file mode 100644
index 00000000..a8a7376b
--- /dev/null
+++ b/lib/utils/snakeToCamelCase.ts
@@ -0,0 +1,14 @@
+export const snakeToCamelCase = <T = unknown>(obj: object): T => {
+  if (typeof obj !== "object" || obj === null) return obj;
+
+  if (Array.isArray(obj)) {
+    return obj.map((item) => snakeToCamelCase(item)) as T;
+  }
+
+  return Object.fromEntries(
+    Object.entries(obj).map(([key, value]) => [
+      key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()),
+      snakeToCamelCase(value),
+    ]),
+  ) as T;
+};


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>lib/utils/snakeToCamelCase.ts (1)</summary><blockquote>

`1-14`: **Well-implemented utility function with proper type handling**

The implementation looks good - it correctly handles the recursive conversion of object keys from snake_case to camelCase, including proper handling of nested objects and arrays.

One consideration:

Consider adding protection against circular references, which could cause stack overflows:

```diff
+// Keep track of processed objects to prevent circular reference issues
+export const snakeToCamelCase = <T = unknown>(obj: object, seen = new WeakSet()): T => {
   if (typeof obj !== "object" || obj === null) return obj;
+  
+  if (seen.has(obj)) {
+    // Return a safe value or throw an error for circular references
+    return obj as T;
+  }
+  
+  seen.add(obj);

   if (Array.isArray(obj)) {
-    return obj.map((item) => snakeToCamelCase(item)) as T;
+    return obj.map((item) => snakeToCamelCase(item, seen)) as T;
   }

   return Object.fromEntries(
     Object.entries(obj).map(([key, value]) => [
       key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()),
-      snakeToCamelCase(value),
+      snakeToCamelCase(value, seen),
     ]),
   ) as T;
 };
```

</blockquote></details>
<details>
<summary>lib/utils/mapLoginMethodParamsForUrl.test.ts (1)</summary><blockquote>

`71-85`: **Good test case, but remove debugging code**

The test case correctly verifies the new reauthentication support functionality, following the same pattern as other tests.


Remove the `console.log(result)` statement on line 83 as it appears to be debugging code:

```diff
    const result = mapLoginMethodParamsForUrl(options);
-   console.log(result);
    expect(result).toEqual(expectedOutput);
```

</blockquote></details>
<details>
<summary>lib/utils/generateAuthUrl.ts (1)</summary><blockquote>

`70-85`: **Good implementation of reauthState processing with robust error handling.**

The code correctly:
1. Decodes the base64 string
2. Parses the JSON 
3. Converts snake_case keys to camelCase
4. Merges the decoded parameters with existing loginOptions

The error handling is thorough, capturing both specific error messages and unknown errors.


Consider using object destructuring instead of the `delete` operator for better performance:

```diff
- delete loginOptions.reauthState;
+ const { reauthState, ...restOfLoginOptions } = loginOptions;
+ loginOptions = restOfLoginOptions;
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3b5112efc8d8b00e693793bb8ddac253272da30a and 4856b0b624d78d970c3d51a994c07ffd580bef90.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `lib/types.ts` (3 hunks)
* `lib/utils/generateAuthUrl.test.ts` (1 hunks)
* `lib/utils/generateAuthUrl.ts` (2 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.test.ts` (1 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.test.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>lib/utils/snakeToCamelCase.test.ts (1)</summary><blockquote>

<details>
<summary>lib/utils/snakeToCamelCase.ts (1)</summary>

* `snakeToCamelCase` (1-14)

</details>

</blockquote></details>
<details>
<summary>lib/utils/generateAuthUrl.ts (2)</summary><blockquote>

<details>
<summary>lib/types.ts (1)</summary>

* `LoginOptions` (75-180)

</details>
<details>
<summary>lib/utils/snakeToCamelCase.ts (1)</summary>

* `snakeToCamelCase` (1-14)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>lib/utils/generateAuthUrl.ts</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>
<details>
<summary>🪛 GitHub Actions: Build and test</summary>

<details>
<summary>lib/utils/generateAuthUrl.test.ts</summary>

[error] 406-406: Test failure: AssertionError - expected function to throw error including 'Error handing reauth state: Expected property name or '}' in JSON at position 1 (line 1 column 2)' but got 'Error handing reauth state: Expected property name or '}' in JSON at position 1'.

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>lib/utils/mapLoginMethodParamsForUrl.ts (1)</summary>

`29-29`: **Good addition of reauthentication support**

The addition of the `supports_reauth` parameter follows the established pattern for boolean parameters in this function, maintaining consistency with the existing codebase.

</details>
<details>
<summary>lib/utils/generateAuthUrl.ts (2)</summary>

`5-5`: **Great addition of the snakeToCamelCase utility.**

Adding this import allows for consistent conversion of snake_case keys from the reauthState to camelCase, which matches JavaScript conventions.

---

`87-89`: **Good addition of clientId validation.**

This early validation ensures clear feedback when a required parameter is missing, improving developer experience.

</details>
<details>
<summary>lib/types.ts (3)</summary>

`32-33`: **Good addition of reauth-related properties to the LoginMethodParams type.**

These additions ensure type safety when using the new reauth functionality.

---

`82-82`: **Verify the intention of making clientId optional.**

While the type now marks `clientId` as optional, `generateAuthUrl.ts` requires it to be present. This suggests `clientId` might be provided via `reauthState` in some scenarios, but could confuse developers.

Is this intentional? If `clientId` is always required except when provided via `reauthState`, consider adding this information to the documentation.

---

`172-179`: **Clear documentation for the new properties.**

The documentation clearly explains the purpose of each new property, which helps developers understand when and how to use them.

</details>
<details>
<summary>lib/utils/generateAuthUrl.test.ts (2)</summary>

`386-395`: **Good test for clientId validation.**

This test verifies that an appropriate error is thrown when `clientId` is missing.

---

`411-440`: **Comprehensive test for reauthState processing.**

The test effectively verifies:
1. Proper decoding of the base64-encoded reauthState
2. Conversion of snake_case keys to camelCase
3. Merging of decoded parameters with existing loginOptions
4. Generation of the expected URL with the merged parameters

This validates the core functionality of the reauth feature.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T15:53:53Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (2)</summary><blockquote>

`70-85`: **The reauth state handling logic looks solid, but has a performance concern.**

The implementation correctly:
- Decodes base64 encoded reauth state
- Converts from snake_case to camelCase using the utility function
- Merges the decoded parameters into the login options
- Provides descriptive error messages

However, the `delete` operator (line 79) is flagged by static analysis as a potential performance issue.


Consider this alternative that avoids using the `delete` operator:

```diff
- loginOptions = {
-   ...loginOptions,
-   ...decodedReauthParams,
- };
- delete loginOptions.reauthState;
+ const { reauthState, ...restOptions } = loginOptions;
+ loginOptions = {
+   ...restOptions,
+   ...decodedReauthParams,
+ };
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

---

`72-74`: **Consider adding input validation for reauthState.**

The code correctly handles parsing errors, but adding explicit validation of the decoded content before using it would provide an additional layer of security.


```diff
  const decodedReauthParams: LoginOptions = snakeToCamelCase<LoginOptions>(
    JSON.parse(atob(loginOptions.reauthState)),
  );
+ // Validate critical fields in decodedReauthParams
+ if (decodedReauthParams.clientId && typeof decodedReauthParams.clientId !== 'string') {
+   throw new Error('Invalid clientId in reauth state');
+ }
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4856b0b624d78d970c3d51a994c07ffd580bef90 and e165c7dbe289fad67771d5ca53af6a4a21e615a2.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `lib/types.ts` (3 hunks)
* `lib/utils/generateAuthUrl.test.ts` (1 hunks)
* `lib/utils/generateAuthUrl.ts` (2 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.test.ts` (1 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.test.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary>

* lib/utils/mapLoginMethodParamsForUrl.ts
* lib/utils/snakeToCamelCase.test.ts
* lib/utils/mapLoginMethodParamsForUrl.test.ts
* lib/utils/generateAuthUrl.test.ts
* lib/utils/snakeToCamelCase.ts
* lib/types.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>lib/utils/generateAuthUrl.ts (2)</summary><blockquote>

<details>
<summary>lib/types.ts (1)</summary>

* `LoginOptions` (75-180)

</details>
<details>
<summary>lib/utils/snakeToCamelCase.ts (1)</summary>

* `snakeToCamelCase` (1-14)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>lib/utils/generateAuthUrl.ts</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (3)</summary>

`5-5`: **Good use of modular imports for new functionality.**

The addition of the `snakeToCamelCase` utility import supports the new reauth functionality while maintaining good separation of concerns.

---

`87-89`: **Good early validation for required parameters.**

Adding this validation check for `clientId` is a valuable improvement that ensures errors are caught early before proceeding with URL generation. This follows the "fail fast" principle and provides a clear error message.

---

`70-89`: <details>
<summary>❓ Verification inconclusive</summary>

**Verify security implications of the reauth functionality.**

The implementation parses and processes data from an external source (the `reauthState` parameter). While there is error handling in place, it's important to ensure this functionality doesn't introduce security vulnerabilities.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check for other places where reauthState is handled in the codebase

echo "Checking for reauthState usage across the codebase..."
rg "reauthState" --type ts

echo "Checking for places where decoded parameters are directly used in sensitive operations..."
rg -A 5 "JSON\.parse\(.*\)" --type ts
```

Length of output: 1176

---



</details>

**Verify the security of the `reauthState` merge in generateAuthUrl.ts**

It looks like `reauthState` is only decoded and merged here (lib/utils/generateAuthUrl.ts lines 70–89) and there are tests covering invalid JSON, but untrusted or tampered state could still inject or override arbitrary `loginOptions` fields.

Please confirm that:

- `reauthState` is only ever generated by and returned from a trusted backend.
- It’s integrity-protected (e.g. signed or HMAC’d), or
- You enforce a strict allowlist of expected keys when merging decoded parameters.

Without one of these safeguards, a malicious `reauthState` could override sensitive options (redirect URIs, scopes, etc.).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T16:03:40Z
user: login: coderabbitai[bot]
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T16:03:43Z
user: login: coderabbitai[bot]
body: > [!CAUTION]
> Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.  If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

**Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (1)</summary><blockquote>

`70-85`: **Well implemented reauth state handling with proper error handling.**

The implementation correctly decodes the base64 encoded state, parses it as JSON, converts from snake_case to camelCase, and merges it with existing options. The error handling is robust with appropriate error message formatting.

However, there's a potential performance optimization:

```diff
- loginOptions = {
-   ...loginOptions,
-   ...decodedReauthParams,
- };
- delete loginOptions.reauthState;
+ loginOptions = Object.fromEntries(
+   Object.entries({
+     ...loginOptions,
+     ...decodedReauthParams
+   }).filter(([key]) => key !== 'reauthState')
+ );
```

This approach creates a new object without the `reauthState` property instead of using the `delete` operator, which can have performance implications according to the static analysis tool.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🛑 Comments failed to post (1)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (1)</summary><blockquote>

70-85: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Verify handling of malformed base64 input.**

The current implementation will catch errors from `JSON.parse()` for malformed JSON, but errors specific to base64 decoding might not have distinct error messages.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there are tests that specifically test malformed base64 input

echo "Checking for tests that verify malformed base64 input handling..."
rg -A 10 "reauthState.*invalid|invalid.*reauthState" --type ts
```

Length of output: 1037

---



</details>

**Add coverage for invalid Base64 in reauthState**  

The existing test in `lib/utils/generateAuthUrl.test.ts` covers a Base64‐encoded string that decodes to malformed JSON, but there’s no test for when `reauthState` itself isn’t valid Base64. Since `atob(...)` will throw in that case—and different runtimes may emit different error messages—please:

- In `lib/utils/generateAuthUrl.test.ts`, add a test case where `reauthState` is a non-Base64 string (e.g. `"!!!"`).
- Assert that `generateAuthUrl(...)` rejects with an error matching `/Error handing reauth state:/`.
- (Optional) If you want more consistency across environments, normalize the caught error message before rethrowing (e.g. wrap any decode exception under a single “Invalid reauthState” message).

Example test snippet:

```ts
it("throws on non-Base64 reauthState", async () => {
  const options: LoginOptions = {
    scope: [Scopes.openid],
    redirectURL: "https://example.com",
    reauthState: "!!!",  // invalid Base64
  };
  await expect(
    generateAuthUrl(domain, IssuerRouteTypes.login, options),
  ).rejects.toThrow(/Error handing reauth state:/);
});
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In lib/utils/generateAuthUrl.ts around lines 70 to 85, the current code catches
JSON parse errors but does not explicitly handle errors from invalid Base64
input in reauthState. To fix this, add a test case in
lib/utils/generateAuthUrl.test.ts where reauthState is a non-Base64 string like
"!!!" and assert that generateAuthUrl rejects with an error matching /Error
handing reauth state:/. Optionally, normalize the error message in the catch
block to provide a consistent "Invalid reauthState" message for any decoding
errors before rethrowing.
```

</details>

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T12:52:20Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (1)</summary><blockquote>

`70-85`: **Good implementation of reauth state handling**

The code successfully handles the reauthState parameter by:
1. Decoding the base64 string
2. Parsing the JSON
3. Converting snake_case keys to camelCase
4. Merging with existing options
5. Providing clear error messages on failure

The error handling is robust, with detailed error descriptions being captured.


Consider replacing the `delete` operator with an alternate approach for better performance:

```diff
-      delete loginOptions.reauthState;
+      loginOptions = { ...loginOptions };
+      loginOptions.reauthState = undefined;
```

The static analysis tool flagged this as the `delete` operator can impact JavaScript engine optimizations.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7553042f8cc72400f34c911a614942527565051f and cf5329aa036b6ce7b5152c42aa52d5b49549ec92.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `lib/types.ts` (3 hunks)
* `lib/utils/generateAuthUrl.test.ts` (1 hunks)
* `lib/utils/generateAuthUrl.ts` (2 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.test.ts` (1 hunks)
* `lib/utils/mapLoginMethodParamsForUrl.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.test.ts` (1 hunks)
* `lib/utils/snakeToCamelCase.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary>

* lib/utils/mapLoginMethodParamsForUrl.ts
* lib/utils/mapLoginMethodParamsForUrl.test.ts
* lib/utils/snakeToCamelCase.test.ts
* lib/utils/snakeToCamelCase.ts
* lib/types.ts
* lib/utils/generateAuthUrl.test.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>lib/utils/generateAuthUrl.ts</summary>

[error] 79-79: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.


(lint/performance/noDelete)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>lib/utils/generateAuthUrl.ts (2)</summary>

`5-5`: **Import looks good**

The import of the `snakeToCamelCase` utility is correctly added to support the new reauth functionality.

---

`87-89`: **Good early validation for client ID**

Adding this validation ensures that we fail fast if the required clientId is missing, which is a best practice.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T12:53:54Z

Review comments:
diff_hunk: @@ -0,0 +1,26 @@
+import { describe, expect, it } from "vitest";
+import { snakeToCamelCase } from "./snakeToCamelCase";
+
+describe("splitString", () => {
+  it("converts properties from snake to camelCase", () => {
+    const input = {
+      first_name: "John",
+      lastName: "Doe",
+      contact_info: {
+        phone_number: "123-456-7890",
+        email_address: "john@example.com",
+      },
+      favorite_colors: ["deep_blue", "light_green"],
+    };
+
+    expect(snakeToCamelCase(input)).toStrictEqual({
+      firstName: "John",
+      lastName: "Doe",
+      contactInfo: {
+        phoneNumber: "123-456-7890",
+        emailAddress: "john@example.com",
+      },
+      favoriteColors: ["deep_blue", "light_green"],
+    });
+  });
+});
path: lib/utils/snakeToCamelCase.test.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Update test suite name and consider adding edge case tests**

The test provides good coverage of the basic functionality, but there are two improvements needed:


1. Change the test suite name from "splitString" to "snakeToCamelCase" to match the function being tested:

```diff
-describe("splitString", () => {
+describe("snakeToCamelCase", () => {
```

2. Consider adding tests for edge cases like null values and non-object inputs:

```javascript
it("handles null and non-object values", () => {
  expect(snakeToCamelCase(null)).toBe(null);
  expect(snakeToCamelCase("not_an_object")).toBe("not_an_object");
  expect(snakeToCamelCase(123)).toBe(123);
});

it("handles empty objects and arrays", () => {
  expect(snakeToCamelCase({})).toStrictEqual({});
  expect(snakeToCamelCase([])).toStrictEqual([]);
});
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In lib/utils/snakeToCamelCase.test.ts around lines 4 to 26, rename the test
suite from "splitString" to "snakeToCamelCase" to correctly reflect the function
being tested. Additionally, add new test cases to cover edge scenarios such as
handling null, non-object inputs, empty objects, and empty arrays to improve
test coverage and robustness.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-16T15:53:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -382,4 +382,60 @@ describe("generateAuthUrl", () => {
     result.url.searchParams.delete("state");
     expect(result.url.toString()).toBe(expectedUrl);
   });
+
+  it("missing clientId", async () => {
+    const options: LoginOptions = {
+      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
+      redirectURL: "https://example2.com",
+    };
+    const domain = "https://auth.example.com";
+    expect(() =>
+      generateAuthUrl(domain, IssuerRouteTypes.login, options),
+    ).rejects.toThrow(`Error generating auth URL: Client ID missing`);
+  });
+
+  it("invalid reauthState", async () => {
+    const options: LoginOptions = {
+      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
+      redirectURL: "https://example2.com",
+      reauthState: "e3Rlc3Q6MTIz",
+    };
+    const domain = "https://auth.example.com";
+    expect(() =>
+      generateAuthUrl(domain, IssuerRouteTypes.login, options),
+    ).rejects.toThrow(
+      `Error handing reauth state: Expected property name or '}' in JSON at position 1 (line 1 column 2)`,
+    );
+  });
path: lib/utils/generateAuthUrl.test.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix error message assertion in test.**

The test is failing because the expected error message doesn't match the actual error message.

The pipeline failure indicates a discrepancy in the error message format. Fix the test assertion to match the actual error message format:

```diff
  expect(() =>
    generateAuthUrl(domain, IssuerRouteTypes.login, options),
  ).rejects.toThrow(
-    `Error handing reauth state: Expected property name or '}' in JSON at position 1 (line 1 column 2)`,
+    `Error handing reauth state: Expected property name or '}' in JSON at position 1`,
  );
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
  it("invalid reauthState", async () => {
    const options: LoginOptions = {
      scope: [Scopes.openid, Scopes.profile, Scopes.offline_access],
      redirectURL: "https://example2.com",
      reauthState: "e3Rlc3Q6MTIz",
    };
    const domain = "https://auth.example.com";
    expect(() =>
      generateAuthUrl(domain, IssuerRouteTypes.login, options),
    ).rejects.toThrow(
      `Error handing reauth state: Expected property name or '}' in JSON at position 1`,
    );
  });
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Actions: Build and test</summary>

[error] 406-406: Test failure: AssertionError - expected function to throw error including 'Error handing reauth state: Expected property name or '}' in JSON at position 1 (line 1 column 2)' but got 'Error handing reauth state: Expected property name or '}' in JSON at position 1'.

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In lib/utils/generateAuthUrl.test.ts around lines 397 to 409, the test for
invalid reauthState fails because the expected error message does not match the
actual error message thrown. Update the expect().rejects.toThrow() assertion to
use the exact error message produced by the code when handling the invalid
reauthState, ensuring the string matches precisely to fix the test failure.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit e165c7d
created_at: 2025-05-16T15:53:52Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-16T15:51:04Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

"""
## Walkthrough

This change enhances authentication-related types and utilities to support reauthentication flows. It introduces new optional properties (`supportsReauth`, `reauthState`) to types and functions, updates error handling and parameter mapping in authentication URL generation, and adds a utility for converting snake_case to camelCase. Corresponding tests are added and updated for the new logic.

## Changes

| File(s)                                                                                  | Change Summary |
|------------------------------------------------------------------------------------------|---------------|
| `lib/types.ts`                                                                           | Extended `LoginMethodParams` and `LoginOptions` types with optional `supportsReauth` and `reauthState` properties; made `clientId` optional in `LoginOptions`. |
| `lib/utils/generateAuthUrl.ts`                                                           | Enhanced `generateAuthUrl` to process `reauthState` (base64 decode, parse, camelCase conversion), merge it into options, and validate presence of `clientId`. |
| `lib/utils/generateAuthUrl.test.ts`                                                      | Added tests for missing `clientId`, invalid/valid `reauthState` handling, and parameter extraction from decoded reauth state in `generateAuthUrl`. |
| `lib/utils/mapLoginMethodParamsForUrl.ts`                                                | Updated to map `supportsReauth` to `supports_reauth` as a string in URL parameters. |
| `lib/utils/mapLoginMethodParamsForUrl.test.ts`                                           | Added test verifying `supports_reauth` is included in mapped parameters when set. |
| `lib/utils/snakeToCamelCase.ts`                                                          | Added new utility function to recursively convert object keys from snake_case to camelCase. |
| `lib/utils/snakeToCamelCase.test.ts`                                                     | New test file verifying deep snake_case to camelCase conversion in objects and arrays. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Caller
    participant generateAuthUrl
    participant snakeToCamelCase

    Caller->>generateAuthUrl: Call with loginOptions (may include reauthState)
    alt reauthState present in loginOptions
        generateAuthUrl->>generateAuthUrl: Base64 decode reauthState
        generateAuthUrl->>generateAuthUrl: Parse JSON
        generateAuthUrl->>snakeToCamelCase: Convert keys to camelCase
        snakeToCamelCase-->>generateAuthUrl: Return converted object
        generateAuthUrl->>generateAuthUrl: Merge into loginOptions, remove reauthState
    end
    generateAuthUrl->>generateAuthUrl: Validate clientId present
    generateAuthUrl-->>Caller: Return generated auth URL or throw error
```

## Possibly related PRs

- [kinde-oss/js-utils#6](https://github.com/kinde-oss/js-utils/pull/6): Also modifies `generateAuthUrl`, but focuses on handling `state` and `nonce` parameters rather than reauthentication.
- [kinde-oss/js-utils#78](https://github.com/kinde-oss/js-utils/pull/78): Changes `LoginMethodParams` to a `Partial` type, making all properties optional; both PRs modify the same type but with different approaches.

## Suggested reviewers

- DaveOrDead
"""

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!NOTE]
> <details>
> <summary>⚡️ AI Code Reviews for VS Code, Cursor, Windsurf</summary>
> 
> CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
> Learn more [here](http://coderabbit.ai/ide).
> 
> </details>

---

> [!NOTE]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between cf5329aa036b6ce7b5152c42aa52d5b49549ec92 and f946b11a172f6d685f7e6a02022940c4fc2bb953.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `lib/utils/generateAuthUrl.test.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* lib/utils/generateAuthUrl.test.ts

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=kinde-oss/js-utils&utm_content=123):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-05-16T16:02:20Z
body: ## [Codecov](https://app.codecov.io/gh/kinde-oss/js-utils/pull/123?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kinde-oss) Report
All modified and coverable lines are covered by tests :white_check_mark:

:loudspeaker: Thoughts on this report? [Let us know!](https://github.com/codecov/feedback/issues/255)
author_association: NONE