From: Azharul Haque <haque@azharul.com>
To: Shan Shaji <s.shaji@proxmox.com>
Cc: pve-devel@lists.proxmox.com
Subject: Re: [PATCH 0/2] android: register OpenID Connect callback activity for #4281
Date: Fri, 11 Sep 2026 19:07:10 -0400 [thread overview]
Message-ID: <CAFCWXbg4aP0W_wykcU3stz7dV_YPCq9Yk09G22Zxf0E-p72yjg@mail.gmail.com> (raw)
In-Reply-To: <DLCLPWPHT2TR.3GOEMJGD9C0QW@proxmox.com>
Hi Shan,
Fair pushback on the examples, let me be more precise, and drop the one
that doesn't actually hold up.
The iOS keyboard extension one doesn't work, you're right to flag it.
Even with Full Access, a keyboard extension only sees what's typed while
it's the active keyboard, it has no way to read the browser's address
bar, page content, or another app's UI. I shouldn't have included it.
The others do have a real mechanism, though:
- Crash reporter / session-replay SDKs (Sentry, Crashlytics, and
friends are common in apps like ours) routinely auto-capture
navigation events and outgoing request URLs as breadcrumbs for crash
context, entirely automatically, no malicious code involved. If one's
in the dependency tree, the deep-link callback URL or the
/access/openid/login request URL can end up in a crash report
without anyone intending it to.
- A logging proxy or an MDM-installed root CA both do the same thing
via TLS interception: get a CA trusted on the device (corporate MDM
profile, or a user manually trusting a debugging proxy's cert), and
every plaintext HTTPS request the app makes, including the POST to
/access/openid/login carrying state+code, is visible in transit.
Doesn't touch the app-to-app redirect at all, but does expose the
next hop.
- Android accessibility-service abuse is the real one on that
platform, it's how a lot of existing banking trojans steal OTPs, by
registering for AccessibilityEvents and reading whatever's on
screen. Auth Tabs avoid the URL-bar flash Custom Tabs has, so there's
less to read during the happy path, but anywhere we'd fall back to
Custom Tabs (pre-Chrome-132 devices, per your original mail) that
exposure is back.
Net: drop the keyboard-extension line, keep the other three, and the
core point stands regardless, none of this is closed by PVE holding
the verifier itself, since the verifier check never happens on a path
any of these can see.
On the embedded WebView idea: I looked at the series you pointed to.
That's a genuinely different way to sidestep needing a server change,
using PVE's own origin as the redirect URI instead of a custom scheme,
so there's no OS-level redirect hop to intercept at all. But RFC 8252
8.12 doesn't just caution against that, it says native apps MUST NOT
do it, and explains why: the hosting app can read every keystroke on
the login form and copy the session cookies, i.e. it gets the user's
actual IdP credential, not just the OAuth grant. That's strictly worse
than the gap we've been discussing. I'd rather stay on the
system-browser flow we have now (Auth Tabs / ASWebAuthenticationSession)
and leave the WebView approach alone, even though it's tempting as a
no-server-changes option.
No rush on the BFF question or the code review, take the time you need.
Azharul
On Fri, Sep 11, 2026 at 11:44 AM Shan Shaji <s.shaji@proxmox.com> wrote:
> Hi Azharul,
>
> Please consider this as an initial reply.
>
> On Thu Sep 10, 2026 at 12:37 AM CEST, Azharul Haque wrote:
> > Hi Shan,
> >
> > Dug into the server side before replying. PVE's /access/openid/auth-url
> > and /access/openid/login (src/PVE/API2/OpenId.pm in pve-access-control)
> > only take {realm, redirect-url} and {state, code, redirect-url}
> > respectively, no code_challenge/code_verifier field in the API for a
> > client to plug into.
>
> Thanks for taking the time to dig into this. I was aware about this.
> Should have mentioned this in my earlier reply. Sorry!
>
> [snip]
>
> > 2. state+code leaks after our app has them but before they reach PVE:
> > a crash reporter snapshotting the callback URL, a logging proxy in
> > between, or something on a compromised device reading it out from
> > under the app, an
>
> > Android accessibility-service/clipboard scraper, a rogue iOS
> > keyboard extension,
>
> I couldn't understand how the above services can access the
> parameters.
>
> > MDM profile either way. Nothing defends this today, not the
> > platform APIs (they only guard the redirect hop), not PVE's
> > server-held verifier (it never checks who's calling /login), and
> > it's identical exposure on both platforms since it's the same
> > /login endpoint either way.
>
> Without server-side changes, we could fetch the authorization URL and
> open it in an embedded WebView (embedded user agent). The PVE HTTPS
> origin could be used as the redirect URI. The app could intercept
> navigation to that URI, extract both the code and state parameters,
> and submit them to /access/openid/login, similar to this
> implementation [1]. However, AFAIU, this is against the RFC 8252 8.12 [2].
>
> Also, didn't completely go through the code changes in that series.
>
> > Real client-side PKCE would close that second gap: app generates a
> > verifier, sends the challenge at auth-url time, PVE forwards that
> > challenge to the IdP instead of its own, and /login requires the
> > verifier back before it'll redeem the code. But we can't add that from
> > the app alone, /login has no code_verifier field to send it to.
>
> > It'd need a pve-access-control change to accept a client-supplied
> > code_challenge/code_verifier and use that instead of (or in addition to)
> > the one it generates itself now.
>
> [snip]
>
> > Is a server-side change along those lines something you'd consider, or
>
> I'm not entirely sure about that, as I haven't had a chance to go
> through the code yet. Perhaps someone else could chime in; otherwise,
> I'll investigate and get back to you in the coming days.
>
> > is there a reason PVE holding the verifier itself instead of the client
> > is a deliberate design choice I'm missing?
>
> I think it has some BFF [0] like properties but I have to double check
> it. Will get back.
>
> [snip]
>
> - [0]
> https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps?utm_source=gemini#name-backend-for-frontend-bff
> - [1]
> https://lore.proxmox.com/all/20250429150757.130996-1-a.abraham@proxmox.com/T/#t
> - [2] https://datatracker.ietf.org/doc/html/rfc8252#section-8.12
>
>
>
>
prev parent reply other threads:[~2026-09-14 7:34 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 5:40 [PATCH 0/2] android: register OpenID Connect callback activity for #4281 Azharul Haque
2026-08-10 5:40 ` [PATCH 1/2] fix #4281: android: register OpenID Connect callback activity Azharul Haque
2026-08-10 5:40 ` [PATCH 2/2] fix #4281: android: match renamed OpenID callback scheme Azharul Haque
2026-08-10 13:59 ` [PATCH 0/2] android: register OpenID Connect callback activity for #4281 Shan Shaji
2026-08-10 14:47 ` [PATCH v2 0/7] app: implement OpenID Connect (OAuth) realm login (#4281) Azharul Haque
2026-08-10 14:47 ` [PATCH dart-api-client v2 1/2] fix #4281: access: add `type` property to `PveAccessDomainModel` Azharul Haque
2026-08-20 9:17 ` Shan Shaji
2026-08-20 13:37 ` Azharul Haque
2026-08-20 14:39 ` Shan Shaji
2026-08-21 2:56 ` Azharul Haque
2026-08-21 8:00 ` Shan Shaji
2026-08-10 14:47 ` [PATCH dart-api-client v2 2/2] fix #4281: access: add OpenID Connect auth-url/login helpers Azharul Haque
2026-08-20 9:48 ` Shan Shaji
2026-08-20 13:41 ` Azharul Haque
2026-08-10 14:47 ` [PATCH login-manager v2 1/3] fix #4281: ui: add OpenID Connect login flow to login form Azharul Haque
2026-08-20 12:31 ` Shan Shaji
2026-08-10 14:47 ` [PATCH login-manager v2 2/3] fix #4281: ui: fix stale Continue button state on realm switch Azharul Haque
2026-08-10 14:47 ` [PATCH login-manager v2 3/3] fix #4281: ui: use a namespaced OpenID callback scheme Azharul Haque
2026-08-20 14:28 ` Shan Shaji
2026-08-10 14:47 ` [PATCH flutter-frontend v2 1/2] fix #4281: android: register OpenID Connect callback activity Azharul Haque
2026-08-20 14:01 ` Shan Shaji
2026-08-10 14:47 ` [PATCH flutter-frontend v2 2/2] fix #4281: android: match renamed OpenID callback scheme Azharul Haque
2026-08-21 3:41 ` [PATCH v3 00/10] app: implement OpenID Connect (OAuth) realm login (#4281) Azharul Haque
2026-08-21 3:41 ` [PATCH dart-api-client v3 1/2] fix #4281: access: add `type` property to `PveAccessDomainModel` Azharul Haque
2026-08-21 3:41 ` [PATCH dart-api-client v3 2/2] fix #4281: access: add OpenID Connect auth-url/login helpers Azharul Haque
2026-08-26 12:49 ` Shan Shaji
2026-08-21 3:41 ` [PATCH login-manager v3 1/5] fix #4281: deps: add flutter_web_auth_2 dependency Azharul Haque
2026-08-21 3:41 ` [PATCH login-manager v3 2/5] refactor: ui: factor out shared login tail into _finishLogin Azharul Haque
2026-08-26 13:41 ` Shan Shaji
2026-08-21 3:41 ` [PATCH login-manager v3 3/5] refactor: ui: split password form into its own widget Azharul Haque
2026-08-26 9:32 ` Shan Shaji
2026-08-21 3:41 ` [PATCH login-manager v3 4/5] fix #4281: ui: add OpenID Connect login flow to login form Azharul Haque
2026-08-21 3:41 ` [PATCH login-manager v3 5/5] fix #4281: ui: fix stale Continue button state on realm switch Azharul Haque
2026-08-26 10:24 ` Shan Shaji
2026-08-21 3:41 ` [PATCH flutter-frontend v3 1/3] chore: regenerate plugin registrant for flutter_web_auth_2 Azharul Haque
2026-08-21 3:41 ` [PATCH flutter-frontend v3 2/3] fix #4281: android: set taskAffinity="" on MainActivity Azharul Haque
2026-08-27 10:40 ` Shan Shaji
2026-08-21 3:41 ` [PATCH flutter-frontend v3 3/3] fix #4281: android: register OpenID Connect callback activity Azharul Haque
2026-08-26 11:41 ` [PATCH v3 00/10] app: implement OpenID Connect (OAuth) realm login (#4281) Shan Shaji
2026-09-01 9:30 ` [PATCH 0/2] android: register OpenID Connect callback activity for #4281 Shan Shaji
2026-09-09 22:37 ` Azharul Haque
2026-09-11 15:44 ` Shan Shaji
2026-09-11 23:07 ` Azharul Haque [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAFCWXbg4aP0W_wykcU3stz7dV_YPCq9Yk09G22Zxf0E-p72yjg@mail.gmail.com \
--to=haque@azharul.com \
--cc=pve-devel@lists.proxmox.com \
--cc=s.shaji@proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.