[PR #5224] [CLOSED] feat(oidc-provider): add verify option for client secret hashing #5865

Closed
opened 2026-03-13 12:39:31 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/5224
Author: @DarthGigi
Created: 10/10/2025
Status: Closed

Base: canaryHead: feat/oidc-provider-verify-option


📝 Commits (1)

  • 3e1be31 feat(oidc-provider): add verify option for client secret hashing

📊 Changes

2 files changed (+14 additions, -2 deletions)

View changed files

📝 packages/better-auth/src/plugins/oidc-provider/index.ts (+6 -0)
📝 packages/better-auth/src/plugins/oidc-provider/types.ts (+8 -2)

📄 Description

Add a verify option for OIDC provider client secret hashing

Problem

When using the OIDC provider plugin with non-deterministic hashing algorithms like Argon2 or bcrypt for storing client secrets, authentication fails with invalid client_secret errors.

The current client secret verification logic re-hashes the incoming secret and compares it to the stored hash:

const hashedClientSecret = await hash(clientSecret);
if (hashedClientSecret !== storedClientSecret) {
  return false;
}

This approach only works for deterministic hashing algorithms (e.g., SHA-256) where the same input always produces the same output. However, algorithms like Argon2 and bcrypt generate different hashes each time because they use random salts, making direct comparison impossible.

Solution

Add an optional verify callback to the storeClientSecret configuration, following the same pattern used for password hashing in Better Auth:

storeClientSecret: {
  hash(clientSecret) {
    return argon2.hash(clientSecret);
  },
  verify(data) {
    return argon2.verify(data.hash, data.clientSecret);
  }
}

Changes

  • types.ts: Added an optional verify function to the storeClientSecret hash configuration
  • index.ts: Updated verifyStoredClientSecret to use the custom verify callback if provided

Backwards Compatibility

The verify option is fully optional, so existing code using deterministic hashing (SHA-256, etc.) continues to work without any changes.

// Existing code - still works
storeClientSecret: {
  hash(clientSecret) {
    return sha256(clientSecret)
  }
}

// New code - with verify
storeClientSecret: {
  hash(clientSecret) {
    return argon2.hash(clientSecret);
  },
  verify(data) {
    return argon2.verify(data.hash, data.clientSecret);
  }
}

This follows the established pattern from Better Auth's password verification system, which already supports custom verify functions for the same reason.


Summary by cubic

Adds an optional verify callback for OIDC client secret hashing to support non-deterministic algorithms (Argon2, bcrypt) and fix invalid client_secret errors. Existing deterministic hashing continues to work.

  • New Features
    • storeClientSecret now supports verify({ hash, clientSecret }): Promise.
    • Verification uses this callback when provided, enabling Argon2/bcrypt without re-hashing.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/5224 **Author:** [@DarthGigi](https://github.com/DarthGigi) **Created:** 10/10/2025 **Status:** ❌ Closed **Base:** `canary` ← **Head:** `feat/oidc-provider-verify-option` --- ### 📝 Commits (1) - [`3e1be31`](https://github.com/better-auth/better-auth/commit/3e1be313b2cc54bb676638077ffa528305c9c206) feat(oidc-provider): add verify option for client secret hashing ### 📊 Changes **2 files changed** (+14 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `packages/better-auth/src/plugins/oidc-provider/index.ts` (+6 -0) 📝 `packages/better-auth/src/plugins/oidc-provider/types.ts` (+8 -2) </details> ### 📄 Description ## Add a verify option for OIDC provider client secret hashing ### Problem When using the OIDC provider plugin with non-deterministic hashing algorithms like `Argon2` or `bcrypt` for storing client secrets, authentication fails with `invalid client_secret` errors. The current client secret verification logic re-hashes the incoming secret and compares it to the stored hash: ```typescript const hashedClientSecret = await hash(clientSecret); if (hashedClientSecret !== storedClientSecret) { return false; } ``` This approach only works for deterministic hashing algorithms (e.g., SHA-256) where the same input always produces the same output. However, algorithms like Argon2 and bcrypt generate different hashes each time because they use random salts, making direct comparison impossible. ### Solution Add an optional `verify` callback to the `storeClientSecret` configuration, following the same pattern used for password hashing in Better Auth: ```typescript storeClientSecret: { hash(clientSecret) { return argon2.hash(clientSecret); }, verify(data) { return argon2.verify(data.hash, data.clientSecret); } } ``` ### Changes - **`types.ts`**: Added an optional `verify` function to the `storeClientSecret` hash configuration - **`index.ts`**: Updated `verifyStoredClientSecret` to use the custom verify callback if provided ### Backwards Compatibility The `verify` option is fully optional, so existing code using deterministic hashing (SHA-256, etc.) continues to work without any changes. ```typescript // Existing code - still works storeClientSecret: { hash(clientSecret) { return sha256(clientSecret) } } // New code - with verify storeClientSecret: { hash(clientSecret) { return argon2.hash(clientSecret); }, verify(data) { return argon2.verify(data.hash, data.clientSecret); } } ``` ### Related This follows the established pattern from Better Auth's password verification system, which already supports custom verify functions for the same reason. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds an optional verify callback for OIDC client secret hashing to support non-deterministic algorithms (Argon2, bcrypt) and fix invalid client_secret errors. Existing deterministic hashing continues to work. - **New Features** - storeClientSecret now supports verify({ hash, clientSecret }): Promise<boolean>. - Verification uses this callback when provided, enabling Argon2/bcrypt without re-hashing. <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-03-13 12:39:31 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#5865