[GH-ISSUE #4198] [OIDC] Kysely + CamelCasePlugin choke with redirectURLs #18492

Closed
opened 2026-04-15 16:58:06 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @julen on GitHub (Aug 24, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/4198

Background

Hi there 👋, we are using Kysely alongside its CamelCasePlugin to ensure our DB tables and columns are defined in snake case while the interaction via TS remains in camel case. This is something we do across our entire DB, and it also applies to the tables handled by better-auth.

While using the OIDC plugin, we created a new client and when going through the authorization flow, it'd always fail with a "Invalid redirect URI" error.

The Issue

Debugging has shown oauthApplication.redirectURLs comes as undefined from the DB, and this happens because by default the field name cannot be reliably translated both ways: the DB field redirect_urls gets mapped to redirectUrls, but the code expects a redirectURLs column.

Potential Solutions

The CamelCasePlugin can be customized to work around this case:

  • Use the underscoreBetweenUppercaseLetters option, s.t. redirectURLs becomes the redirect_u_r_l_s column in the DB. That'd allow the reverse mapping to work. Not good looking, but oh well.
  • Customize the CamelCasePlugin to special-case this scenario. This is what we are currently doing:
class BetterAuthCompatibleCamelCasePlugin extends CamelCasePlugin {
	protected override camelCase(str: string): string {
		if (str === "redirect_urls") {
			return "redirectURLs";
		}

		return super.camelCase(str);
	}
}

Another possibility would be for better-auth to re-define redirectURLs as redirecUrls — and more broadly apply this principle to its core + plugin field names — use strict camel case, with no exceptions for acronyms.

Test Case

I pushed a commit on my fork at 73a8de84f1 that showcases the issue in a test case.

Is This a Bug?

I'm not sure this can be considered a bug per-se.

On the one hand, better-auth has been working flawlessly with our original database configuration, and we had no reason to think we would have problems when starting to use a new plugin. I checked across all the core + plugin schemas, and redirectURLs is the only occurrence where an acronym remains capitalized, so from that standpoint, this is an inconsistency with undesired side-effects.

If better-auth is supposed to work out-of-the-box with Kysely + CamelCasePlugin, then it'd be fair to enforce all schema fields to be strictly defined using camel case (no acronym exceptions).

On the other hand, if there are no compatibility guarantees from better-auth's side for using Kysely plugins, then maybe it'd be a good idea to warn users about this in the database documentation.

In any case, I hope this report is helpful for other folks who might run into the same issue.

Originally created by @julen on GitHub (Aug 24, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/4198 ## Background Hi there 👋, we are using Kysely alongside its [`CamelCasePlugin`](https://kysely-org.github.io/kysely-apidoc/classes/CamelCasePlugin.html) to ensure our DB tables and columns are defined in snake case while the interaction via TS remains in camel case. This is something we do across our entire DB, and it also applies to the tables handled by better-auth. While using the OIDC plugin, we created a new client and when going through the authorization flow, it'd always fail with a [_"Invalid redirect URI"_ error](https://github.com/better-auth/better-auth/blob/4696b9e7ec02a061af5473a414a99cbdb3bb67f8/packages/better-auth/src/plugins/oidc-provider/authorize.ts/#L121-L123). ## The Issue Debugging has shown `oauthApplication.redirectURLs` comes as `undefined` from the DB, and this happens because by default the field name cannot be reliably translated both ways: the DB field `redirect_urls` gets mapped to `redirectUrls`, but the code expects a `redirectURLs` column. ## Potential Solutions The `CamelCasePlugin` can be customized to work around this case: * Use the `underscoreBetweenUppercaseLetters` option, s.t. `redirectURLs` becomes the `redirect_u_r_l_s` column in the DB. That'd allow the reverse mapping to work. Not good looking, but oh well. * Customize the `CamelCasePlugin` to special-case this scenario. This is what we are currently doing: ```ts class BetterAuthCompatibleCamelCasePlugin extends CamelCasePlugin { protected override camelCase(str: string): string { if (str === "redirect_urls") { return "redirectURLs"; } return super.camelCase(str); } } ``` Another possibility would be for better-auth to re-define `redirectURLs` as `redirecUrls` — and more broadly apply this principle to its core + plugin field names — use strict camel case, with no exceptions for acronyms. ## Test Case I pushed a commit on my fork at https://github.com/julen/better-auth/commit/73a8de84f1d6af8aa7666257ed0ad262f71217f8 that showcases the issue in a test case. ## Is This a Bug? I'm not sure this can be considered a bug per-se. On the one hand, better-auth has been working flawlessly with our original database configuration, and we had no reason to think we would have problems when starting to use a new plugin. I checked across all the core + plugin schemas, and `redirectURLs` is the only occurrence where an acronym remains capitalized, so from that standpoint, this is an inconsistency with undesired side-effects. If better-auth is supposed to work out-of-the-box with Kysely + `CamelCasePlugin`, then it'd be fair to enforce all schema fields to be strictly defined using camel case (no acronym exceptions). On the other hand, if there are no compatibility guarantees from better-auth's side for using Kysely plugins, then maybe it'd be a good idea to warn users about this in the database documentation. In any case, I hope this report is helpful for other folks who might run into the same issue.
GiteaMirror added the locked label 2026-04-15 16:58:06 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 24, 2025):

You're right—redirectURLs is the only field in better-auth that uses an acronym with uppercase letters in camelCase, while all other fields follow strict camelCase (like clientId, userId, jwksEndpoint) across both core and plugins. This inconsistency causes issues with Kysely's CamelCasePlugin, which maps redirect_urls to redirectUrls, not redirectURLs, resulting in the field being undefined and breaking the OIDC flow [source].

Your workaround—customizing the plugin or using underscoreBetweenUppercaseLetters—is currently the best approach. If better-auth were to rename redirectURLs to redirectUrls, it would align with the rest of the codebase and resolve this mapping issue for everyone using Kysely or similar tools. Since this is the only field with this pattern, the migration impact would be narrowly scoped to the OIDC plugin and should be manageable [source].

There’s no official naming convention policy or documentation about acronym casing or Kysely plugin compatibility in better-auth right now [source]. Until this is standardized, it would be helpful for the docs to warn about this edge case.

For now, customizing your CamelCasePlugin as you’ve done is the most robust fix. If you want to future-proof your setup, you could monitor for a potential rename to redirectUrls in better-auth and plan a simple migration for your DB and code when/if that happens. For new plugins or schema fields, sticking to strict camelCase (no acronym exceptions) is the safest bet to avoid similar issues.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3218023596 --> @dosubot[bot] commented on GitHub (Aug 24, 2025): <!-- Answer --> You're right—`redirectURLs` is the only field in better-auth that uses an acronym with uppercase letters in camelCase, while all other fields follow strict camelCase (like `clientId`, `userId`, `jwksEndpoint`) across both core and plugins. This inconsistency causes issues with Kysely's `CamelCasePlugin`, which maps `redirect_urls` to `redirectUrls`, not `redirectURLs`, resulting in the field being `undefined` and breaking the OIDC flow [[source]](https://github.com/better-auth/better-auth/blob/8c23eb07396478a51b4dc7de669c010cdadc5479/packages/better-auth/src/plugins/oidc-provider/types.ts). Your workaround—customizing the plugin or using `underscoreBetweenUppercaseLetters`—is currently the best approach. If better-auth were to rename `redirectURLs` to `redirectUrls`, it would align with the rest of the codebase and resolve this mapping issue for everyone using Kysely or similar tools. Since this is the only field with this pattern, the migration impact would be narrowly scoped to the OIDC plugin and should be manageable [[source]](https://github.com/better-auth/better-auth/blob/8c23eb07396478a51b4dc7de669c010cdadc5479/packages/better-auth/src/plugins/oidc-provider/schema.ts). There’s no official naming convention policy or documentation about acronym casing or Kysely plugin compatibility in better-auth right now [[source]](https://better-auth.com/docs/concepts/database). Until this is standardized, it would be helpful for the docs to warn about this edge case. For now, customizing your `CamelCasePlugin` as you’ve done is the most robust fix. If you want to future-proof your setup, you could monitor for a potential rename to `redirectUrls` in better-auth and plan a simple migration for your DB and code when/if that happens. For new plugins or schema fields, sticking to strict camelCase (no acronym exceptions) is the safest bet to avoid similar issues. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d2852862-2726-4015-ba03-5e0ed18ae0a0?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4198)
Author
Owner

@ping-maxwell commented on GitHub (Aug 24, 2025):

Hmm, I think it should be customized at the better-auth plugin schema level.
Usually plugins have options to modify the schema, which includes the ability to rename field names, but I just checked and it seems we don't have schema customization in the oidc plugin options

<!-- gh-comment-id:3218275885 --> @ping-maxwell commented on GitHub (Aug 24, 2025): Hmm, I think it should be customized at the better-auth plugin schema level. Usually plugins have options to modify the schema, which includes the ability to rename field names, but I just checked and it seems we don't have schema customization in the oidc plugin options
Author
Owner

@julen commented on GitHub (Aug 24, 2025):

Indeed—that was filed separately as #4199 earlier today with the fix at #4200.

<!-- gh-comment-id:3218287392 --> @julen commented on GitHub (Aug 24, 2025): Indeed—that was filed separately as #4199 earlier today with the fix at #4200.
Author
Owner

@ping-maxwell commented on GitHub (Aug 24, 2025):

Oh awesome, make sure to update the docs (feel free to look at my PR to know what I mean)
I'll just close mine

<!-- gh-comment-id:3218288156 --> @ping-maxwell commented on GitHub (Aug 24, 2025): Oh awesome, make sure to update the docs (feel free to look at my PR to know what I mean) I'll just close mine
Author
Owner

@julen commented on GitHub (Aug 24, 2025):

Thanks for the quick feedback @ping-maxwell — it's updated now.

<!-- gh-comment-id:3218308554 --> @julen commented on GitHub (Aug 24, 2025): Thanks for the quick feedback @ping-maxwell — it's updated now.
Author
Owner

@julen commented on GitHub (Aug 24, 2025):

Hmm, I think it should be customized at the better-auth plugin schema level.

Btw, to be clear, note that the issue presented here is orthogonal to being able to modify the schema, and no { schema: { oauthApplication: { fields: { redirectURLs: 'redirect_urls' } } } } config would help because the CamelCasePlugin makes redirect_urls available as redirectUrls.

<!-- gh-comment-id:3218341934 --> @julen commented on GitHub (Aug 24, 2025): > Hmm, I think it should be customized at the better-auth plugin schema level. Btw, to be clear, note that the issue presented here is orthogonal to being able to modify the schema, and no `{ schema: { oauthApplication: { fields: { redirectURLs: 'redirect_urls' } } } }` config would help because the `CamelCasePlugin` makes `redirect_urls` available as `redirectUrls`.
Author
Owner

@ping-maxwell commented on GitHub (Aug 24, 2025):

Oh, I see

In that case I think it makes sense for you to have that workaround in your custom plugin for kysely

<!-- gh-comment-id:3218402701 --> @ping-maxwell commented on GitHub (Aug 24, 2025): Oh, I see In that case I think it makes sense for you to have that workaround in your custom plugin for kysely
Author
Owner

@julen commented on GitHub (Aug 26, 2025):

While we have a workaround in place, our use of type generation (via kysely-codegen) requires additional third-party package patches to maintain type safety. From a DX perspective, this creates an unfortunate situation where we must implement multiple workarounds for functionality that should work seamlessly out-of-the-box.

Given that Kysely is a built-in adapter, I think it's fair to expect its built-in plugins to function flawlessly without requiring these additional steps. I understand that schema changes are generally undesirable, but considering the plugin is advertised as being in active development and potentially unsuitable for production use, perhaps the better-auth team should reconsider whether the field could still be renamed to redirectUrls to improve the overall developer experience.

<!-- gh-comment-id:3223296693 --> @julen commented on GitHub (Aug 26, 2025): While we have a workaround in place, our use of type generation (via kysely-codegen) requires additional third-party package patches to maintain type safety. From a DX perspective, this creates an unfortunate situation where we must implement multiple workarounds for functionality that should work seamlessly out-of-the-box. Given that Kysely is a built-in adapter, I think it's fair to expect its built-in plugins to function flawlessly without requiring these additional steps. I understand that schema changes are generally undesirable, but considering the plugin is advertised as being in active development and potentially unsuitable for production use, perhaps the better-auth team should reconsider whether the field could still be renamed to `redirectUrls` to improve the overall developer experience.
Author
Owner

@rusel1989 commented on GitHub (Aug 26, 2025):

Hi @ping-maxwell , I'd like to support @julen 's case. As he mentions we had to resort to quite ugly workaround, to get around this issue. And given the Kysely is the default I was also expecting plugins like CamelCasePlugin to work without any issues.

<!-- gh-comment-id:3223988512 --> @rusel1989 commented on GitHub (Aug 26, 2025): Hi @ping-maxwell , I'd like to support @julen 's case. As he mentions we had to resort to quite ugly workaround, to get around this issue. And given the Kysely is the default I was also expecting plugins like `CamelCasePlugin` to work without any issues.
Author
Owner

@ping-maxwell commented on GitHub (Aug 26, 2025):

I'll bring it up to the team.

<!-- gh-comment-id:3225965155 --> @ping-maxwell commented on GitHub (Aug 26, 2025): I'll bring it up to the team.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18492