Skip to content

Use webfinger for OIDC parameter discovery#847

Open
kaivol wants to merge 4 commits into
opencloud-eu:mainfrom
kaivol:use-webfinger-for-oidc-parameter-discovery
Open

Use webfinger for OIDC parameter discovery#847
kaivol wants to merge 4 commits into
opencloud-eu:mainfrom
kaivol:use-webfinger-for-oidc-parameter-discovery

Conversation

@kaivol

@kaivol kaivol commented Mar 17, 2026

Copy link
Copy Markdown

Closes #811.

Client side implementation of the changes described in https://github.com/opencloud-eu/opencloud/blob/main/docs/adr/0003-oidc-client-config-discovery.md.

Based on #776.

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from b345a3c to 063efde Compare April 7, 2026 10:21
@kaivol kaivol marked this pull request as ready for review April 7, 2026 10:22
@kulmann kulmann requested a review from dragotin April 28, 2026 07:15
@RichardFevrier

RichardFevrier commented Apr 28, 2026

Copy link
Copy Markdown

Did this PR worked for you @kulmann ?

Just tried it without success on my side, when both web + iOS are working perfectly.

I have tested the webfinger with:

curl -L cloud.mydomain.com/.well-known/webfinger?resource=https://cloud.opencloud.test&rel=http://openid.net/specs/connect/1.0/issuer&platform=desktop | jq
  % Total    % Received % Xferd  Average Speed  Time    Time    Time   Current
                                 Dload  Upload  Total   Spent   Left   Speed
  0      0   0      0   0      0      0      0                              0
100    305 100    305   0      0   2324      0                              0
{
  "subject": "https://cloud.opencloud.test",
  "properties": {
    "http://opencloud.eu/ns/oidc/client_id": "OpenCloudDesktop",
    "http://opencloud.eu/ns/oidc/scopes": [
      "openid",
      "profile",
      "email",
      "groups",
      "offline_access"
    ]
  },
  "links": [
    {
      "rel": "http://openid.net/specs/connect/1.0/issuer",
      "href": "https://auth.mydomain.com"
    }
  ]
}

Which returns groups that is mandatory on my setup since Authelia groups binds to OpenCloud roles.

But when the Authelia page appears I can see that groups are not part of the request.

Edit:
debugged it further:

26-04-28 13:38:21:512 [ debug sync.credentials.oauth ]  [ OCC::OAuth::openBrowser ]:    opening browser
26-04-28 13:38:21:512 [ debug sync.credentials.oauth ]  [ isUrlValid ]: Checking URL for validity: QUrl("https://auth.mydomain.com/api/oidc/authorization?response_type=code&client_id=OpenCloudDesktop&redirect_uri=http://127.0.0.1:32979&code_challenge=Kgkj2cHF9MwXPDyTkZETDhc4Pv07hAXBxgSV8DfBhCI&code_challenge_method=S256&scope=openid offline_access email profile&prompt=consent select_account&state=c5bNXSEMgYIazaZ3aMqJjz3mI7SfpbP00YlzmVl-Q2w%3D")
[2] Sandbox: CanCreateUserNamespace() clone() failure: EPERM

You can see that scopes (scope=openid offline_access email profile) doesn't contain groups.

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from 063efde to 01406ed Compare April 29, 2026 19:03
@kaivol

kaivol commented Apr 29, 2026

Copy link
Copy Markdown
Author

@RichardFevrier thanks for testing the PR!
I made some changes, so it should work now.

I also bumped the C++ standard version to 23, i hope this is fine.

@RichardFevrier

Copy link
Copy Markdown

Thanks for your work @kaivol I'll test that tomorrow! 🤩

@guruz

guruz commented May 7, 2026

Copy link
Copy Markdown
Contributor

@RichardFevrier Have you tested this PR? :)

@guruz

guruz commented May 7, 2026

Copy link
Copy Markdown
Contributor

@kaivol FYI CI ^ says this:

/Users/runner/work/desktop/desktop/src/libsync/creds/oauth.cpp:622:35: error: no member named 'join_with' in namespace 'std::__1::ranges::views'
  622 |                     | std::views::join_with(QStringLiteral(" "))
      |                       ~~~~~~~~~~~~^

Might be related to

I also bumped the C++ standard version to 23, i hope this is fine.

I can't say anything to this topic specifically, if it's easier to keep a lower C++ standard or check if all our platforms would support 23.
CC @TheOneRing

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from 01406ed to 5e7ecb7 Compare May 7, 2026 19:07
@kaivol

kaivol commented May 7, 2026

Copy link
Copy Markdown
Author

@guruz Thanks for bringing that up.
I got rid of the join_with call and implemented the logic in a good ol' loop: diff

@guruz

guruz commented May 8, 2026

Copy link
Copy Markdown
Contributor

@kaivol one more failure :) ^

@TheOneRing FYI, i can't seem to be able to ask macos and windows to re-run if linux already failed ^

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from 5e7ecb7 to e259baa Compare May 8, 2026 17:27
@kaivol

kaivol commented May 8, 2026

Copy link
Copy Markdown
Author

I'm a little confused, the CI error seems to be in the OpenVFS plugin, not at all related to my changes 😕
A quick look at the CI overview shows that builds are failing for some time already.

@guruz

guruz commented May 9, 2026

Copy link
Copy Markdown
Contributor

@kaivol You're right, sorry!
Could you re-base on current main branch, it should be green now for Linux.
https://github.com/opencloud-eu/desktop/commits/main/

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from e259baa to dbeb743 Compare May 9, 2026 08:51
@guruz

guruz commented May 9, 2026

Copy link
Copy Markdown
Contributor

^ OAuth test fails

@kaivol kaivol force-pushed the use-webfinger-for-oidc-parameter-discovery branch from a83044a to b7e4712 Compare May 9, 2026 18:22
@kaivol

kaivol commented May 9, 2026

Copy link
Copy Markdown
Author

Okay, I adjusted the OAuth test and added a response for the .well-known/webfinger request.

Let me know if you agree with the changes.

KaroUniform pushed a commit to KaroUniform/desktop that referenced this pull request May 26, 2026
Override openIdConnectScopes() in OpenCloudTheme to include the
"groups" scope alongside the default openid/offline_access/email/profile
set.

IDPs that scope-gate their group claim (Authelia, Keycloak and Authentik
in default config) only emit it when the corresponding scope is requested
in the authorization request. Without it, server-side role mapping via
PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM=groups fails with "no roles in user
claims" and login dies on the post-OAuth user-info step with "Failed to
get user info from server".

Stopgap until opencloud-eu#847 (webfinger-based OIDC parameter discovery) lands
upstream. Refs opencloud-eu#217.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@guruz

guruz commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

I can confirm this PR works, I'm logged in a test server with a different client_id and additional scopes.

I'll post my review comments later, it's only small stuff I think.

Thank you for the PR @kaivol

By the way I see this in log:

26-06-06 11:18:37:232 [ warning sync.credentials.manager ]:	set "OpenCloud_credentials:(REMOVED).opencloud.rocks:f6fc19c6-aad5-43ba-a244-191f75967795:http/oauthtoken" has not yet finished. duration(0h, 3min, 45s, 491ms)

@guruz

This comment was marked as off-topic.

@guruz

guruz commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Here in code before, it differs in error signal emission if it's about refresh token or not:
https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L646

While your new code does not:
https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L556
(and following emissions)

Maybe you could just always emit both in your added code (would need to be checked and tested if really only one is connected)?
Q_EMIT result(Error);
Q_EMIT refreshError(Error);
Or of course check if (_isRefreshingToken) and only emit one of them.

@kaivol

kaivol commented Jun 8, 2026

Copy link
Copy Markdown
Author

I took a look at the current OAuth::fetchWellKnown function and now I'm a little confused about the emitted signals:

  • On network error, we emit result(Error) (or refreshError(...) if _isRefreshingToken)
  • If the JSON value is illegal we emit fetchWellKnownFinished()
  • On any other JSON related issue we emit both result(Error) and fetchWellKnownFinished()

Also, the _wellKnownFinished variable is set to true before a signal is emitted.

Could you please clarify the meaning of _wellKnownFinished and the different signals, in particular which signals should be emitted under which conditions?

@guruz

guruz commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

I was more talking about the lack of refreshError being emitted.

This is about the refresh token:
https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/httpcredentials.cpp#L264

Signal refreshError (but not error) is connected a few lines above:
https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/httpcredentials.cpp#L246

So _oAuthJob->refreshAuthentication(_refreshToken) is called.
Which then here https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp calls fetchWellKnown() (from restored()) ..
Which (...) then sends a webfinger request https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L552
When then here
https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L556 and https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L563 and https://github.com/kaivol/opencloud-desktop/blob/b7e471209a0ede21fb12b59bd22aba26bfbad19e/src/libsync/creds/oauth.cpp#L573 (... etc following)
doesn't emit refreshError but just error.
So it gets stuck here (in error case) while refreshing token.

On network error, we emit result(Error) (or refreshError(...) if _isRefreshingToken)

No you're not for the webfinger stuff, see my links ^
Only the code for the later req.setUrl(oidcWellKnownUrl); does (partly, hmmm)

Could you please clarify the meaning of _wellKnownFinished and the different signals, in particular which signals should be emitted under which conditions?

I cannot, I'm not versed with this code :) I was only wondering about the error vs refreshError.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use webfinger for OIDC parameter discovery

3 participants