Skip to content

feat: add Kanidm OIDC support with PKCE and ID token algo config#682

Open
mikimandoki wants to merge 2 commits into
oss-apps:mainfrom
mikimandoki:feat/kanidm-support
Open

feat: add Kanidm OIDC support with PKCE and ID token algo config#682
mikimandoki wants to merge 2 commits into
oss-apps:mainfrom
mikimandoki:feat/kanidm-support

Conversation

@mikimandoki

@mikimandoki mikimandoki commented Jun 17, 2026

Copy link
Copy Markdown

Description

While I was attempting to set up Kanidm to work with SplitPro I had hit a few roadblocks:

  1. Kanidm includes an issued_token_type field in its token response which isn't in the Prisma schema, causing a DB crash before the account could be created. Rather than adding another provider-specific case to linkAccount, this PR replaces the entire chain with a generic sanitisation pass using Prisma.AccountScalarFieldEnum as the source of truth. Any provider with non-standard fields now works without further changes.

  2. Kanidm also enforces PKCE and ES256 by default, both of which were previously not supported by SplitPro. These can now be configured by optional env vars. I also added an example kanidm env config.

To test these changes, I ran the updated code on my NAS in a Docker container and finally managed to authenticate with Kanidm. Disabling PKCE or defaulting to RS256 both fail on the default Kanidm config.

Checklist

  • I have read CONTRIBUTING.md in its entirety
  • I have performed a self-review of my own code
  • I have added unit tests to cover my changes
  • The last commit successfully passed pre-commit checks
  • Any AI code was thoroughly reviewed by me

Comment thread src/server/auth.ts
type: 'oauth',
wellKnown: env.OIDC_WELL_KNOWN_URL,
authorization: { params: { scope: 'openid email profile' } },
checks: env.OIDC_PKCE_ENABLED ? ['pkce'] : [],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand OIDC, the encryption configs should be provided from the well known url endpoint. I am against opening up the env var config to the whole breadth of OAuth2 options as this would just continue increasing and be a bad incentive for AI agents.

I am not familiar with Kandim, but please double check it's not an issue on their end or with your configuration, as setting these options by hand should not be required.

@mikimandoki mikimandoki Jun 22, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback. I'm no OIDC expert myself. Here's what I could find out:

Kanidm correctly advertises ES256 and its PKCE requirements in the .well-known files. These are the defaults Kanidm ships with. Disabling them is possible but the commands are along the lines of "enable legacy crypto" etc., highly suggesting that users should only mess with this if necessary.

wget -qO- https://kanidm:8443/oauth2/openid/splitpro/.well-known/openid-configuration 2>/dev/null 

"id_token_signing_alg_values_supported":["ES256"],
"code_challenge_methods_supported":["S256"]

The issue appears to lie in openid-client NextAuth v4 ships.

openid-client defaults to RS256 and intentionally ignores id_token_signing_alg_values_supported from discovery. The expectation per spec is that the OP signs tokens with whatever alg the client was registered with. Since SplitPro passes credentials directly to openid-client with no additional configuration, and Kanidm defaults to ES256, the mismatch has to be resolved on the client side via id_token_signed_response_alg. The maintainer has expressed this as well: panva/openid-client#115 (comment)

As far as I can tell adding in the checks and client params is the intended way to deal with this, however, I have come across a different implementation as well:
danny-avila/LibreChat#5348 reads the discovered value and passes that on to the client. Happy to give this approach shot if it is more desirable.

Comment thread src/server/auth.ts
refresh_expires_in: _refresh_expires_in,
...standardAccountData
} = account as AdapterAccount & Record<string, unknown>;
const knownAccountFields = new Set<string>(Object.values(Prisma.AccountScalarFieldEnum));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very cool

Comment thread docs/CONFIGURATION.md Outdated
OIDC_WELL_KNOWN_URL="https://keycloak.example.com/realms/My_Realm/.well-known/openid-configuration"
```

### OIDC (Kanidm)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This document should be concise and does not have space for the myriad of OAuth providers out there. Respective values should be available in the provider's docs, please remove this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough - changes made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants