Seafile creates a new user every time via Keycloak

Hello, I have Seafile installed in Docker.
I also have Keycloak installed in Docker.
Authentication is configured via Seafile > Keycloak > Seafile.
Everything works, the redirect works, Keycloak authenticates, and redirects back to the application, but:
Seafile creates a new user every time. Has anyone encountered this? I’ve tried everything, including different scopes, manually changing UID → email in MySQL, etc., but nothing helps.
The correct scopes are coming through curl:
{“sub":“1d9cc62f-81ea-484d-af26-6839051066b9”,“email_verified”:true,“preferred_username”:"example@inbox.ru”,“given_name”:“”,“family_name”:“”,“email”:“exemple@inbox.ru”}

Meanwhile, Seafile continues to create users of this format:
1d9cc69f94ea583daf776839051066b9@auth.local

The current settings look like this:

#Keycloak
ENABLE_OAUTH = True
OAUTH_ACTIVATE_USER_AFTER_CREATION = True
OAUTH_CREATE_UNKNOWN_USER = True
OAUTH_ENABLE_INSECURE_TRANSPORT = True

OAUTH_CLIENT_ID = “seafile”
OAUTH_CLIENT_SECRET = “TOKEN”
OAUTH_REDIRECT_URL = https:// url seafile

OAUTH_PROVIDER_DOMAIN = https:// url keycloak
OAUTH_PROVIDER = https:// url keycloak

OAUTH_AUTHORIZATION_URL =https:// url keycloak/realms/“realm”/protocol/openid-connect/auth’
OAUTH_TOKEN_URL = https:// url keycloak/realms/“realm”/protocol/openid-connect/token’
OAUTH_USER_INFO_URL = ‘https:// url keycloak/realms/“realm”/protocol/openid-connect/userinfo’

OAUTH_SCOPE = [“openid”, “profile”, “email”]
OAUTH_ATTRIBUTE_MAP = {
“sub”: (False, “not used”),
“name”: (False, “full name”),
“email”: (True, “email”),
}

etc., only the display of, for example, the uid on the email changes, but users are created anew each time.

The first user is the local admin, the rest are created via Keycloak.

Any ideas?

It appears the issue is related to how Seafile 11.0+ handles user identification via OAuth. Since version 11.0, Seafile uses Virtual User IDs (the [unique_id]@auth.local format you are seeing) and requires a specific mapping for the unique identifier to recognize existing users.

In your current configuration, you have mapped the Keycloak sub claim to "not used". This prevents Seafile from finding the existing entry in the social_auth_usersocialauth database table, leading it to treat every login as a new user.

Recommended Fix

You need to update your OAUTH_ATTRIBUTE_MAP in seahub_settings.py to map Keycloak’s unique ID (sub) to Seafile’s uid field.

Please update your settings to the following:

OAUTH_ATTRIBUTE_MAP = {   
   "sub": (True, "uid"),           # Map Keycloak unique ID to Seafile UID    
   "email": (False, "contact_email"),    
   "name": (False, "name"),
}

Why this happens:

  • UID Mapping: Setting sub to (True, "uid") ensures Seafile uses the stable Keycloak ID to look up your account.
  • Virtual IDs: Seafile generates internal IDs for social users. Once the uid mapping is correct, Seafile will consistently map that specific Keycloak sub to the same internal virtual ID instead of generating a new one each time.

Note on Existing Users:

If you have already manually modified the MySQL tables or have many duplicate accounts, you may need to clear the incorrect entries in the social_auth_usersocialauth table so that Seafile can create a fresh, correct association upon the next login.

I tried this too, and unfortunately, it didn’t help. I don’t rule out that I might have some incorrect settings on Keycloak, although all other services have no issues. Do you have any documentation on setting up Keycloak, because I’m out of ideas?
I set the values ​​as you mentioned in your message, but it didn’t help; several different users were still created.

Today I barely found time to dig around. I created a “test” user from Keycloak for this user. It’s the same sub every time.
{“sub”:“6a8fc506-d433-45e7-ad54-8f51e79a965f”,“email_verified”:true,“name”:“test testov",“preferred_username”:"test@test.com”,“given_name”:“test”,“family_name”:“testov”,“email”:“test@test.com”}
But Seafile stubbornly keeps creating new UIDs.

It accepts email and usernames fine, but something weird is happening with the UID.

The settings are yours, so what else can I do?

OAUTH_SCOPE = [“openid”, “profile”, “email”]
OAUTH_ATTRIBUTE_MAP = {
“sub”: (True, “uid”), # Map Keycloak unique ID to Seafile UID
“email”: (False, “contact_email”),
“name”: (False, “name”),
}

Can you check the content of social_auth_usersocialauth table?

empty(((

Do you see any related error logs in seahub.log?

Here is the analysis from our AI:

Based on the fact that your social_auth_usersocialauth table is empty, this is likely caused by the 32-character limit for the provider name in Seafile’s database.

When the OAUTH_PROVIDER (or OAUTH_PROVIDER_DOMAIN if used as the provider) is longer than 32 characters, Seafile fails to save the mapping in the database. Consequently, it doesn’t recognize you on the next login and creates a new “virtual” user again.

Recommended Solution:

Shorten your OAUTH_PROVIDER or OAUTH_PROVIDER_DOMAIN setting to a simple string that is under 32 characters. For example:

# Change this to a short identifier
OAUTH_PROVIDER = 'keycloak' 

Even if you use a full URL for the actual endpoint settings, the provider identifier itself must be short.

Hooray, that worked (apparently it’s a varchar). Now I just need to regain access to the first user @gmail.com. If I manually change his email to the uid from Keycloak, would that work? So that the email becomes keycloak_uid@auth.local?

From our AI again:

To regain access to your original local user account (@gmail.com) via Keycloak, you have two options according to the official documentation:

Option 1: Bind Social Login in Settings (Recommended)

This is the cleanest way to link the accounts without manual database manipulation:

  1. Log in to Seafile using your original local administrator account (the one with the email @gmail.com).
  2. Go to your Settings page.
  3. Look for the Social Login section.
  4. Click the button to bind your account to Keycloak.
  5. Next time you log in via Keycloak, Seafile will recognize the link and log you into the existing @gmail.com account.

Option 2: Manually add the mapping to the database

If you cannot log in locally for some reason, you can manually insert the mapping into the social_auth_usersocialauth table.

You will need:

  • Your Keycloak sub value (e.g., 6a8fc506-d433-45e7-ad54-8f51e79a965f).
  • Your local user’s internal email (e.g., admin@gmail.com).
  • The OAUTH_PROVIDER name you just set (e.g., keycloak).

The SQL command would look something like this:

INSERT INTO social_auth_usersocialauth (provider, uid, user_id, extra_data) 
VALUES ('keycloak', '6a8fc506-d433-45e7-ad54-8f51e79a965f', 'admin@gmail.com', '{}');

Note: Do not manually change the email in the database to the uid@auth.local format, as that is a Virtual ID generated internally for new users. Instead, use the mapping table as described above to link your existing email-based account to the Keycloak UID.

For more details on how version 11.0+ handles these mappings, you can refer to the OAuth Authentication guide.

Thank you so much, you helped me a lot. For some reason, I couldn’t find the option to log in through social networks, so I did it through MySQL. As a result, everything matched correctly. The topic can be closed.