Skip to content

AJDA-3380: fix the Google OIDC tab after the usability test - #1138

Closed
Iamfle4ka wants to merge 5 commits into
keboola:mainfrom
Iamfle4ka:AJDA-3380-oidc-google-tab
Closed

Iamfle4ka wants to merge 5 commits into
keboola:mainfrom
Iamfle4ka:AJDA-3380-oidc-google-tab

Conversation

@Iamfle4ka

@Iamfle4ka Iamfle4ka commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Why

Michal (design) spent 40 minutes following the Google tab of /data-apps/authentication/ and hit a snag at nearly every step; the recording is the input for this PR. One of the snags turned out to be a wrong claim on our side: the page said an External app in Testing lets in only its listed test users. Google exempts apps that request only openid, email and profile from that rule ("users do not need to be in the trusted user list, they will not see a warning message", support.google.com/cloud/answer/15549945), and that is exactly what the Keboola proxy requests (oauth2-proxy's default OIDC scope; keboola-as-code sets none). So an External app lets in anyone with a Google account, Testing or not, and Internal is what restricts sign-in to the organization. Michal's test showed that, and so did the run below.

Part of AJDA-3380 (Apps docs review for the 1 Oct GA).

What changes

src/content/docs/data-apps/authentication.mdx only.

  • Google tab rewritten around what the reader actually sees: Google Auth Platform with direct links to Overview, Branding, Audience and Clients; both states of the consent screen (a project showing Get started versus one already configured); the Test users / Publish app instruction replaced by the Internal versus External rule above; the exact redirect-URI field with a filled-in example; the error headline Google shows (Access blocked: This app's request is invalid) and where Request details is; the encrypted KBC::ProjectSecureGKMS:: value behind the eye icon on the secret field; "You now have" checkpoints after each block.
  • Shared steps: Step 1 starts from an existing app, however it was built, and only then says how to create one; the App URL screenshot is the one that shows the Overview tab; the admin-rights prerequisite is stated up front, including that Kai and kbagent cannot do this part (MCP authentication_type is no-auth | basic-auth | default; CLI --auth is password | public); Step 3 covers a running app (Redeploy App) versus a stopped one (Start App), says to test each account in a fresh private window, and gives /_proxy/sign_out for ending a session between tests.
  • Entra, Okta and Auth0 tabs: checkpoint lines, plus the corrections from the documentation pass described below.

Verification

  • npm run build clean, judged by its exit code; node scripts/audit-phase2.mjs shows nothing on this page.
  • fact-checker (repo agent, Opus): no CRITICAL, no MAJOR; 28 claims confirmed against Google's help pages, oauth2-proxy and keboola-as-code sources, the MCP server, and the repo's screenshots. Its seven minor findings are folded into commit 2.

Live run, 22 Sep

The tab was followed end to end against real infrastructure: a new Google Cloud project keboola-docs-test in the ext.keboola.com organization, OAuth client docs-test-google-2026-09-22, and a throwaway Streamlit app in project 264.

Test Setup Expected Result
1 Internal audience, account inside the organization signs in signed in, app rendered
2 External audience, status Testing, zero test users signs in anyway signed in, no warning, no consent friction
3 Internal audience, account outside the organization refused not run, and not planned: it needs a second Google account, and the remaining time before the freeze goes to the other three providers

Test 2 is what this PR rests on. The sign-in URL the proxy generates carries scope=openid+email+profile in the address bar, so Google's own exemption rule covers it and we are no longer arguing from the source code alone.

Seven things the run corrected in the text (commit 3): authorized domains are added from the redirect URI automatically, so Branding is optional; the "Get started" branch has to key off the content area, because Branding / Audience / Clients sit in the left menu either way; the Audience page shows publishing status, user cap and test users only for External; the secret field is masked after saving and the encrypted value hides behind the eye icon; the deploy wizard asks three things; the consent screen also appears on first sign-in for an Internal app; /_proxy/sign_out added.

One thing stayed unverified here: the Request details label on Google's error page and the redirect_uri_mismatch wording come from Michal's test, since the typo was never re-created during this run.

One edge the page leaves out on purpose: if an app ever gets an allowed-roles list, oauth2-proxy adds the groups scope and Google's exemption stops applying. The UI has no such field for OIDC providers today.

Documentation pass on the other three tabs, 23 Sep

Entra, Okta and Auth0 have never been run against a live tenant. Each was checked against the vendor's current public documentation instead, and each check found something.

Okta, and this one is critical. On an Integrator Free Plan org the default authorization server ships without an access policy, so every token request fails until you add one. A reader on the most common free org type would have followed our instructions exactly and hit a failure with nothing in our troubleshooting list matching it. Three more from the same check: the menu parenthetical was backwards, since Applications and Resources is the Identity Engine label and Applications → Applications the Classic one; the wizard may ask which experience to use; and /login/signout is not an endpoint Okta documents anywhere, so the logout guidance now uses the end_session_endpoint from discovery, and step 4 no longer tells readers to delete the sign-out redirect URI that the logout flow needs.

Entra. The assignment flow stopped one click short of Assign, so nothing was saved. Worse, testing the restriction while signed in as a Global Administrator gives a false pass, because the requirement does not apply to them, and that is exactly the account a reader is likely to be using. The role sentence named a floor where Microsoft documents alternatives. The claim I most expected to be stale, P1 or P2 for group assignment, is still what Microsoft documents in three places and is unchanged.

Auth0. A post-logout redirect has to be registered under Allowed Logout URLs or Auth0 refuses it, which we never mentioned. And "copy the issuer from discovery" broke for custom-domain tenants, who have two domains and would have copied the wrong one. Discovery is now the primary instruction; the trailing slash was confirmed against two real discovery documents rather than prose.

Live runs of all three are planned before the freeze, once tenants exist. Two things only a live run can settle: Okta's two error strings, which Okta does not publish anywhere, and whether either redirect-URI field arrives prefilled.

For the Apps team, not this PR

  • A copy button for the callback URL inside the OIDC form would have saved Michal his typo.
  • Revealing the secret shows the encrypted KBC::… string, which reads as if the secret had been replaced. Hiding it entirely would be better.
  • The Auth0 preset placeholder has no trailing slash while Auth0's issuer does.

🤖 Generated with Claude Code

Nikita and others added 2 commits September 22, 2026 15:11
Michal's 40-minute run through the Google tab, checked against Google's
own docs, turned up one wrong claim and a row of snags:

- Testing does not gate sign-in for Keboola apps. The proxy requests only
  openid, email and profile (oauth2-proxy default; keboola-as-code sets no
  scope), and Google exempts exactly those scopes from the test-user list.
  The page said the opposite. Now: Internal limits sign-in to the org,
  External lets any Google account in, publishing is irrelevant.
- Step 1 starts from an existing app, however it was built; Kai keeps the
  OIDC settings on later changes (MCP authentication_type=default).
- Direct links to the Google Auth Platform pages; both states of the
  consent screen (Get started vs already configured); the exact redirect
  URI field with a filled-in example; the error headline Google actually
  shows and where Request details lives; the encrypted
  KBC::ProjectSecureGKMS:: value after Save; Start App vs Redeploy App;
  test in a private window.
- Admin-rights prerequisite up front; Kai and kbagent cannot do this part.
- "You now have" checkpoints on every provider tab.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Drop the unverified claim that Kai preserves the OIDC settings; only the
  MCP server's default path is known to.
- Show the Overview-tab screenshot that actually has the tab bar and the
  App URL block in view.
- Publishing gates the app name as well as the logo.
- The propagation note covers audience changes again, not only the
  redirect URI.
- The fresh-window advice names the real reason: the proxy's own session
  cookie, not a skipped Google sign-in (the proxy sends prompt=select_account).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 22, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Keboola Engineering Team on Vercel.

A member of the Team first needs to authorize it.

Nikita and others added 2 commits September 22, 2026 21:38
Walked the whole Google tab against a real Google Cloud project
(keboola-docs-test) and a real app in project 264. What the run changed:

- The central claim is now proven, not inferred: the sign-in request the
  proxy sends carries scope=openid+email+profile, and an External app in
  Testing status with an empty test-user list let the account straight in.
  Google's own Audience page says the opposite, so the guide now names that
  text and says it does not apply here.
- Authorized domains are no longer a prerequisite: the client form states
  that domains from the redirect URI are added to the consent screen
  automatically. That step is now optional.
- The Get started branch was wrong: Branding, Audience and Clients are in
  the left menu even on an unconfigured project, so they cannot be the
  signal. The content area is.
- The Audience page shows publishing status, user cap and test users only
  for an External app.
- The secret field is masked after saving; the encrypted
  KBC::ProjectSecureGKMS:: value appears only behind the eye icon.
- The deploy wizard asks for three things, not two.
- The consent screen appears on first sign-in for Internal apps too, and
  the app page can still read stopped until reloaded.
- Added /_proxy/sign_out as the way to end the app session between tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Google tab said the revealed secret starts with
KBC::ProjectSecureGKMS::. That prefix is GCP-only: extend/encryption
documents KBC::ProjectSecureKV:: on Azure and KBC::ProjectSecure:: on
AWS, and the three are not interchangeable. A reader on an AWS stack who
didn't see the documented string had no way to tell whether the save had
worked. Name the common stem and link the encryption page instead.

Found by the fact-checker agent while reviewing the wave-2 Apps pages,
which carried the same sentence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
These three were written from vendor documentation in September and have
never been run against a live tenant. A documentation pass found one
critical gap and several things that would cost a reader time.

Okta, the critical one: on an Integrator Free Plan org the `default`
authorization server ships without an access policy, so every token
request fails until you add one, and nothing in our troubleshooting list
matched that symptom. Also, the menu parenthetical was backwards
(Applications and Resources is the Identity Engine label, Applications >
Applications is Classic), the wizard may ask which experience to use,
and `/login/signout` is not an endpoint Okta documents anywhere. The
logout guidance now uses the end_session_endpoint from discovery, and
step 4 no longer tells readers to delete the Sign-out redirect URI that
the logout flow needs. The org authorization server is presented as
Okta's own recommendation for plain SSO rather than as a fallback,
because custom authorization servers need a paid add-on.

Entra: the assignment flow stopped one click short of Assign, so nothing
was saved. And testing the restriction as a Global Administrator gives a
false pass, because the requirement does not apply to them, which is
exactly the account a reader is likely signed in as. The role sentence
named a floor where Microsoft documents alternatives. The claim most
suspected of being stale, P1 or P2 for group assignment, turned out to
be current and is unchanged.

Auth0: a post-logout redirect has to be registered under Allowed Logout
URLs or Auth0 refuses it, which we never mentioned. And the instruction
to copy the issuer from discovery broke for custom-domain tenants, who
have two domains and would have copied the wrong one. Discovery is now
the primary instruction rather than the hedge; the trailing slash was
confirmed against two real discovery documents.

Still unverified and waiting on live runs: Okta's two error strings,
which Okta does not publish, and whether either redirect-URI field
arrives prefilled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Iamfle4ka pushed a commit that referenced this pull request Sep 23, 2026
#1138 kept moving after this branch forked from it: 0addba2 carries
corrections from a live Google run, and 3d97aec stops naming a GCP-only
cipher prefix as the one every reader sees.

One conflict, in the consent-screen steps, resolved toward #1138 because its
side came from the live run and settles the question this branch was carrying
as a TODO: Authorized domains is optional, since Google adds the domain itself
when you save the redirect URI. The TODO(human-review) is dropped with it.
Their side also names the exact empty-state string ("Google Auth Platform not
configured yet") and what Internal vs External actually shows on the Audience
page.

Everything this branch adds survived: the "Do you actually need OIDC?" note,
the per-tab verification dates, the copy-button fix in Step 1, the missing
group-filter caveat for Google, the expected-rejection signature, and the
single placeholder vocabulary (dataAppId is gone from the page).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Iamfle4ka Iamfle4ka added the apps-ga Apps GA on 1 Oct 2026 — docs work tracked under AJDA-3380 label Sep 23, 2026
@Iamfle4ka

Copy link
Copy Markdown
Collaborator Author

Superseded by #1139, which now carries every commit from this branch.

Verified rather than assumed: this branch's tip 21ecda74 is an ancestor of #1139's head de406ab7, checked with git merge-base --is-ancestor. The live-run evidence and the vendor-documentation check that lived in this description have been carried into #1139's, so the reviewer sees what the claims rest on.

Branch AJDA-3380-oidc-google-tab is left in place; nothing here is lost.

@Iamfle4ka Iamfle4ka closed this Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps-ga Apps GA on 1 Oct 2026 — docs work tracked under AJDA-3380

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant