Skip to content

NullPointerException in ConnectionValidator after successful OAuth token exchange (Authelia) #172

@hobasp2

Description

@hobasp2

NullPointerException in ConnectionValidator after successful OAuth token exchange

Summary

After a successful OIDC login flow (Webfinger → OIDC Discovery → Authorization → Token Exchange),
the app crashes with a NullPointerException in ConnectionValidator.checkUnauthorizedAccess()
during account setup. The login loop restarts instead of completing.

Environment

  • OpenCloud Server: 6.2.0 (rootless Podman, opencloud-rolling@sha256:92a05001f619cc1758300bb5c9ce0bf6fd5c0a0e8142aa269602237741d408e7)
  • Android App: QA Build 10 (OpenCloud-qa-29ddedb-20260507_1536-10.apk) — self-compiled from source
  • Android-App (from Google Play):versionName=1.2.3
  • OIDC Provider: Authelia 4.39.19
  • Test Device: Samsung SM-A528B (Android 13, One UI 5)
  • Authelia client config: token_endpoint_auth_method: none, consent_mode: implicit

What works ✓

The full OIDC flow completes successfully up to token exchange:

11:50:08 GetInstancesViaWebFingerOperation: Doing WebFinger request:
  https://cloud.example.org/.well-known/webfinger
  ?rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer
  &resource=https%3A%2F%2Fcloud.example.org
  &platform=android

11:50:08 GetInstancesViaWebFingerOperation: Successful WebFinger request:
  WebFingerResponse(
    subject=https://cloud.example.org,
    links=[LinkItem(rel=http://openid.net/specs/connect/1.0/issuer, href=https://auth.example.org)],
    properties=WebFingerProperties(clientId=OpenCloudAndroid, scopes=[openid, profile, email, offline_access])
  )

11:50:08 TokenRequestRemoteOperation: Successful response:
  access_token=authelia_at_...
  refresh_token=authelia_rt_...   ← Refresh Token present!
  scope=openid profile email offline_access

11:50:08 AuthenticationViewModel: Instances retrieved from authenticated webfinger:
  Success(data=[https://cloud.example.org])

What fails ✗

Immediately after the authenticated Webfinger succeeds, loginOAuth calls LoginOAuthAsyncUseCase
which internally calls GetBaseUrlRemoteOperation, which triggers ConnectionValidator
but the account object is not yet fully initialized:

11:50:09 ConnectionValidator: java.lang.NullPointerException: 
  Attempt to invoke virtual method 
  'eu.opencloud.android.lib.common.authentication.OpenCloudCredentials 
  eu.opencloud.android.lib.common.OpenCloudAccount.getCredentials()' 
  on a null object reference

  at ConnectionValidator.checkUnauthorizedAccess(ConnectionValidator.kt:181)
  at ConnectionValidator.validate(ConnectionValidator.kt:87)
  at OpenCloudClient.saveExecuteHttpMethod(OpenCloudClient.java:150)
  at OpenCloudClient.executeHttpMethod(OpenCloudClient.java:107)
  at GetBaseUrlRemoteOperation.run(GetBaseUrlRemoteOperation.kt:52)
  at RemoteOperation.execute(RemoteOperation.java:229)
  at OCRemoteAuthenticationDataSource.login(OCRemoteAuthenticationDataSource.kt:51)
  at OCRemoteAuthenticationDataSource.loginOAuth(OCRemoteAuthenticationDataSource.kt:40)
  at OCAuthenticationRepository.loginOAuth(OCAuthenticationRepository.kt:67)
  at LoginOAuthAsyncUseCase.run(LoginOAuthAsyncUseCase.kt:37)
  at AuthenticationViewModel.loginOAuth(AuthenticationViewModel.kt:188)

After this exception the app returns to the URL input screen (login loop).

Server-side Webfinger configuration

OpenCloud container environment (relevant excerpt):

Environment=OC_EXCLUDE_RUN_SERVICES=idp
Environment=OC_OIDC_ISSUER=https://auth.example.org
Environment=OC_CONFIG_DIR=/etc/opencloud

Environment=WEBFINGER_ANDROID_OIDC_CLIENT_ID=OpenCloudAndroid
Environment=WEBFINGER_ANDROID_OIDC_CLIENT_SCOPES=openid,profile,email,offline_access
Environment=WEBFINGER_IOS_OIDC_CLIENT_ID=OpenCloudIOS
Environment=WEBFINGER_IOS_OIDC_CLIENT_SCOPES=openid,profile,email,offline_access
Environment=WEBFINGER_DESKTOP_OIDC_CLIENT_ID=OpenCloudDesktop
Environment=WEBFINGER_DESKTOP_OIDC_CLIENT_SCOPES=openid,profile,email,offline_access
Environment=WEBFINGER_WEB_OIDC_CLIENT_ID=web
Environment=WEBFINGER_WEB_OIDC_CLIENT_SCOPES=openid,profile,email,offline_access

Webfinger service config (/etc/opencloud/webfinger.yaml):

webfinger:
  oidc:
    issuer: https://auth.example.org

Authelia OIDC client config (relevant client)

identity_providers:
  oidc:
    refresh_token_lifespan: "30d"
    clients:
      - client_id: OpenCloudAndroid
        client_name: OpenCloud Android
        public: true
        require_pkce: true
        pkce_challenge_method: S256
        response_types:
          - code
        grant_types:
          - authorization_code
          - refresh_token
        authorization_policy: opencloud_users
        redirect_uris:
          - oc://android.opencloud.eu
        scopes: [openid, profile, email, offline_access]
        token_endpoint_auth_method: none
        id_token_signed_response_alg: RS256
        access_token_signed_response_alg: none
        consent_mode: implicit

Curl verification — server-side platform discovery works

curl "https://cloud.example.org/.well-known/webfinger\
?resource=https://cloud.example.org\
&rel=http://openid.net/specs/connect/1.0/issuer\
&platform=android"
{
    "subject": "https://cloud.example.org",
    "properties": {
        "http://opencloud.eu/ns/oidc/client_id": "OpenCloudAndroid",
        "http://opencloud.eu/ns/oidc/scopes": ["openid", "profile", "email", "offline_access"]
    },
    "links": [
        {
            "rel": "http://openid.net/specs/connect/1.0/issuer",
            "href": "https://auth.example.org"
        }
    ]
}

Analysis

ConnectionValidator.checkUnauthorizedAccess() at line 181 calls account.getCredentials()
on an OpenCloudAccount object that appears to be null or not yet populated with credentials
at the time GetBaseUrlRemoteOperation is executed during the OAuth login flow.

The credentials (access token) have been successfully obtained from the OIDC provider at this
point, but have not yet been stored in the account — the account setup is in progress when
ConnectionValidator is called.

Steps to reproduce

  1. Fresh install of QA Build 10 or GooglePlay App eu.opencloud.android versionName=1.2.3
  2. Enter OpenCloud server URL
  3. Complete Authelia login (username + password, no TOTP required for this account)
  4. Observe: app returns to URL input screen instead of showing file list

Expected behavior

After successful token exchange, the app should complete account setup and show the file list.

Proposed fix location

ConnectionValidator.checkUnauthorizedAccess() should handle a null account/credentials
gracefully, or GetBaseUrlRemoteOperation should not be called before the account credentials
are persisted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions