Keycloak integration

We want to use Keycloak as authentication provider.

After adding keycloak settings in SOCIALACCOUNT_PROVIDERS in .env

  1. Keycloak login button does not appear on QFieldCloud sign in page
  2. Keycloak login button does not appear on QField Sync plugin in QGIS
  3. Keycloak login button appears on QField apps (v 3.7.3)
    1. On windows clicking sign in using keycloak does not open the browser and shows error “session expired“ immediately
    2. On Android, browser opens, after successful login to keycloak, returning to that app shows error “session expired“ immediately

We tried with different configuration of client (which works with other systems) but no luck in QField and QFieldCloud.

More questions that we could not find in documentation:

  • If user is signed in from Keycloak, new user will be created, how to assign roles (admin or staff)
  • How to assign the new user and Organization, or a Team automatically? does QFieldCloud consider cistom claims for example.

Hi,

sorry for the late reply.

The Social Login feature is rather new, and still under active development, therefore you need quite recent versions of all the components for it to work.

As a start, could you please let me know what your SOCIALACCOUNT_PROVIDERS setting looks like (with sensitive information redacted, of course)?

Next, what is the version of QFieldCloud that you are using? There recently was a fix regarding social logins in version v25.29, so you should be using at least this version.

What version of QGIS are you using? The minimum required QGIS version for Social Logins is QGIS 3.44. And quite a recent version of the QFieldSync plugin is needed as well (at least v4.18.0).

Regarding roles:
Currently, QFieldCloud does not automatically assign any roles or organization memberships based on claims. So far, OIDC is exclusively used for authentication (Identity), and not for authorization purposes.

But this is something we are looking into. However, because the OIDC standard claims do not include any claims for roles or organization memberships, the implementation is not completely straightforward. (Also, OIDC as a standard only concerns itself with authentication, not authorization).

So we could in the future make QFieldCloud consider a fixed set of claims, like roles and organizations, to use an example, and upon login, use those claims to update the QFieldCloud user’s roles and memberships. But that would require customers to map those claims accordingly in the IDP. So we might also need an intermediate mapping in QFieldCloud that can be configured to tell it in what claims it should look for what information. And since an active login event is the only chance QFieldCloud gets to review those claims, revoking claims that are not present any more is also a challenge that needs to be solved.

How it works right now is as follows:

  • The first time a user logs into QFieldCloud using a Social Login, a new user is created in QFieldCloud
  • The username is derived from the information in the preferred_username claim, but normalized to satisfy allowed characters, ensure uniqueness, etc..
  • This user can then be managed in QFieldCloud like any other user
  • By an admin of an organization or a project, they can be made an organization member and/or a project collaborator, and they will then acquire the respective permissions that are associated with their role.

I hope this is of some help to you!

Hi Lukas,

Thanks for the relpy.
Here are my configuration:
SOCIALACCOUNT_PROVIDERS=‘{
“github”: {
“APP”: {
“client_id”: “",
“secret”: "

}
},
“openid_connect”: {
“OAUTH_PKCE_ENABLED”: true,
“APP”: {
“provider_id”: “keycloak”,
“name”: “Keycloak”,
“client_id”: “-client",
“client_secret”: "
",
“settings”: {
“server_url”: "https://
.com/realms/*/.well-known/openid-configuration”
}
}
}
}’

Our installations were outdated, we have updated to the recent mentioned versions, qfieldcloud 25.29, QGIS 3.44.6, QField Sync 4.18.0, and recent QField app from stores.

After updating I can see the social login buttons on QGIS and QFieldCloud web (they did not appear on previous versions).

But still the authentication flow is not being completed, using either github or keycloak.

After successfully login from the provider, qfield app instance prints the below error message: Authentication credentials were not provided:

app-1 | {“request_id”:“0cd7b8b97f5195ca549e6a92738a802f”,“ts”:“2026-01-08T11:06:24.542909”,“level”:“INFO”,“name”:“root”,“message”:“Authentication credentials were not provided.”,“filename”:“rest_utils.py”,“lineno”:49,“thread”:132174889248448,“source”:“app”}
app-1 | Unauthorized: /api/v1/auth/user/
app-1 | {“status_code”:401,“request”:“<WSGIRequest: GET ‘/api/v1/auth/user/’>”,“request_id”:“0cd7b8b97f5195ca549e6a92738a802f”,“ts”:“2026-01-08T11:06:24.543474”,“level”:“WARNING”,“name”:“django.request”,“message”:“Unauthorized: /api/v1/auth/user/”,“filename”:“log.py”,“lineno”:246,“thread”:132174889248448,“source”:“app”}

Regarding the users and permissions, the mentioned flow is sufficient (we can add our own automatic permission assignment later on).

Please let me know if you need more details or I can send you the keys ans sample users to try on.

Thanks
Eyad

Hi Eyad,

thank you for the exceprts from you configuration and logfiles - that helps a lot!

One thing that I’m seeing that likely is a problem, is that you are using a client secret.
(They “client_secret” key for the Keycloak client, and “secret” for the GitHub client).

Currently, QFieldCloud requires OIDC client to be configured without client secrets.
The reason for that is that client secrets must only be used for confidential clients, but with the QFieldSync plugin in QGIS and the QField mobile app, we have two clients in the ecosystem that are non-confidential. Unlike a server that is under your control, they have no way of confidentially storing a secret - anyone could extract that from the plugin source code, or the mobile app bundle.

Therefore, QFieldCloud relies on what the OIDC standard calls “public clients” or non-confidential clients.
These clients are set up in a way that no client secret is generated (and needed).

Instead, PKCE (Proof Key for Code Exchange) is used to ensure that the authorization code flow is secure even without a client secret.
In short, PKCE ensures that only the client that originally requested it can exchange an authorization code for an access token, even if the authorization code were to be intercepted by an attacker.

So, this means:

  • The configuration in SOCIALACCOUNT_PROVIDERS must not include any client secrets
  • The configuration in SOCIALACCOUNT_PROVIDERS must configure the client to use PKCE
  • The OAuth2 / OIDC clients on the IDP side (e.g. Keycloak) must be configured as public / non-confidential clients, without client secrets, and with PKCE enabled.

In Keycloak, in the configuration for the OpenID Connect client, the following settings must be set:

  • Settings → Capability config → Client authentication: OFF
  • Advanced → Advanced settings → Proof Key for Code Exchange Challenge Method: S256

With “Client authentication” turned off, there should be no “Credentials” tab in the client configuration anymore, and no client secret should be shown.

For reference, this is the configuration of they Keycloak client and SOCIALACCOUNT_PROVIDERS that I use for local development:



SOCIALACCOUNT_PROVIDERS = '{
  "openid_connect": {
    "OAUTH_PKCE_ENABLED": true,
    "APP": {
      "provider_id": "keycloak",
      "name": "Keycloak",
      "client_id": "qfc-oidc",
      "settings": {
        "server_url": "http://keycloak:7080/realms/ninjas/.well-known/openid-configuration"
      }
    }
  }
}'

I would suggest that we first focus on getting Keycloak login working just for the web interface of QFieldCloud, since that is less complex and easier to debug than the QGIS QFieldSync plugin and the mobile clients.

You can also reach out to me by email at lukas (at) opengis.ch, and I’ll try my best to help you get this working. (English or German are both fine for me).

Did you manage to get this running? I was testing QFieldCloud’s Identity Provider capabilities, and it seems to work for the most part. But when I close QField, reopen it, and open the cloud menu, I get logged out with a server error.

Depending on the time between logging in and reopening the app, the server reports “OAuth2Error: token already used” or, if waiting 5+ minutes (my Access Token Lifespan), “OAuth2Error: Invalid id_token”. Does this also happen in your local environment, or is there a way to circumvent this?

Not completely. We had to pause the Keycloak investigation to focus on another issue.

Following the instructions in Lukas’ reply, we managed to get it working, but only partially. As you mentioned, the QField app works initially (once), but it appears that the token is not being refreshed. When the server returns a 401 response, the app does not prompt the user to log in again or restart the authentication workflow.

Additionally, this fix does not work in QGIS, where we encountered token issues similar to the ones you described.

As a temporary workaround, we modified the jwtkit.py file located in the application container (you can create your own Docker layer for this):

/usr/local/lib/python3.10/site-packages/allauth/socialaccount/internal/

Instead of raising the error, we changed the behavior to simply pass it.

This partially resolves the issue for QGIS and allows token reuse. However, QField still does not work properly until the app cache and local storage are cleared.

Thank you both for your detailed feedback!

I’ve been able to reproduce the issues you both described. I’ve written a more detailed response in GitHub issue #7187, which is very specifically about this issue with token refreshes, in order to not scatter the conversation across too many places.