Skip to content

feat(auth): sync OIDC user properties#12378

Open
AnneGerlach wants to merge 1 commit intoIQSS:developfrom
AnneGerlach:feat/10266-oidc-sync-properties
Open

feat(auth): sync OIDC user properties#12378
AnneGerlach wants to merge 1 commit intoIQSS:developfrom
AnneGerlach:feat/10266-oidc-sync-properties

Conversation

@AnneGerlach
Copy link
Copy Markdown

@AnneGerlach AnneGerlach commented May 5, 2026

What this PR does / why we need it:

This PR adds synchronization of user properties from the OIDC identity provider to the Dataverse AuthenticatedUser.

Currently, Dataverse authenticates users via bearer tokens but does not persist updated user properties from the OIDC provider. This can lead to outdated user data (e.g. incorrect email addresses), which becomes problematic for features such as notifications or user-facing metadata.

This implementation follows a comparison-based approach:

  • On each authenticated request, user properties from the OAuth2UserRecord (OIDC / Keycloak) are compared with the stored AuthenticatedUser
  • Updates are only applied if values differ
  • This avoids unnecessary database writes and keeps the solution efficient

The following fields are synchronized:

  • firstName
  • lastName
  • email
  • email verification state

In addition, this PR synchronizes the OIDC email_verified claim with Dataverse’s internal representation of email verification (emailConfirmed timestamp).

Mapping:

  • email_verified = true → set emailConfirmed timestamp
  • email_verified = false → set emailConfirmed to null
  • claim missing → keep existing value unchanged

This PR also addresses a small UI inconsistency:
(See screenshots below)

Dataverse keeps the AuthenticatedUser in the session, which can lead to stale values being displayed in the Account Information page even after the database has been updated.

To resolve this:

  • The user is reloaded from the database using a cache-bypassing query
  • Session user properties are updated in-place
  • This avoids using session.setUser(...), which would otherwise invalidate the session/view state

🏴 The feature is controlled via a feature flag:

dataverse.feature.oidc-user-property-sync

  • Disabled by default
  • Allows safe rollout and testing

Which issue(s) this PR closes:


Special notes for your reviewer:

  • The email_verified claim is treated as optional to ensure compatibility with providers that do not expose this claim
  • Email synchronization prefers displayInfo.email and falls back to available email addresses if needed
  • Updates are only persisted when values actually change

Alternative approaches were considered:

  • Timestamp-based sync (updated_at claim)
    Not feasible, as this claim is not provided by Keycloak by default and would require schema changes

  • Push-based updates from the IdP
    Not suitable, as the backend should not depend on external triggers or actively query the identity provider

👉 Therefore, a comparison-based approach was chosen to keep the implementation simple and compatible with any OIDC provider


Suggestions on how to test this:

Run all tests:

mvn test

or only the relevant ones in:

mvn -Dtest=AuthenticationServiceBeanTest test

Optional manual verification:
Before testing, ensure that an OIDC authentication provider is configured (in my case Keycloak).

  • Create/login a user via OIDC in the local setup (docker-compose-dev.yml)
  • Update user properties in Keycloak (e.g. firstname, email)
  • Generate a new token and call:
curl -i \
  -H "Authorization: Bearer $TOKEN" \
  http://localhost:8080/api/users/:me

Expected:

  • The response reflects the updated values
  • The changes are persisted in the Dataverse database
  • No update is triggered if values remain unchanged
  • the Account Information page reflects the updated first name, last name, and email without requiring logout/login

Example response:

{
  "status": "OK",
  "data": {
    "id": 2,
    "identifier": "@user",
    "displayName": "NewFirst NewLast",
    "firstName": "NewFirst",
    "lastName": "NewLast",
    "email": "newemail-user@mailinator.com",
    ...
  }
}

🤝 If helpful, I can provide a more detailed step-by-step manual test guide.


Does this PR introduce a user interface change? If mockups are available, please link/include them here:

No new UI is introduced.

However, this PR fixes an issue where the Account Information page could display stale user data after OIDC updates.

Before:
image

After:
image

Is there a release notes update needed for this change?:

Yes, a release note has been added: doc/release-notes/10266-oidc-property-sync.md

Additional documentation:

Documentation for the new feature flag has been added to the configuration guide.

Thanks for reviewing 🌻

@johannes-darms
Copy link
Copy Markdown
Contributor

@pdurbin @poikilotherm another feature from us ;)

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.

user data is not updated when changed in OIDC IdP.

2 participants