Skip to content

Make identity-provider sign-in work with the registered client - #220

Closed
rbardaji wants to merge 5 commits into
mainfrom
feature/219-oidc-default-client
Closed

Make identity-provider sign-in work with the registered client#220
rbardaji wants to merge 5 commits into
mainfrom
feature/219-oidc-default-client

Conversation

@rbardaji

@rbardaji rbardaji commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #219.

The installer offered sign-in through the identity provider, then asked for a client id with no default and no way of finding one:

  Offer sign-in through the identity provider? [y/N]: y
  Identity provider realm URL [https://idp.nationaldataplatform.org/realms/NDP]:
  Client id registered for this Endpoint:

A blank answer switched sign-in back off with a warning, so the feature was offered and could not be taken.

What changed

Endpoints in the NDP realm do not each need their own client — the platform's public client serves any of them, in the realm the installer already suggests as the issuer. Both are defaults now:

  Client id [ndp_frontend_prod]:

Answering yes and pressing Enter is enough. A client id registered for this Endpoint specifically — a Federation registration creates one and prints it — can be given instead.

--oidc, --oidc-issuer and --oidc-client-id are new. The identity-provider questions were the only prompts with no flag behind them, so an unattended install could not enable sign-in at all, contrary to what install/README.md claims.

A registration still never switches sign-in on by itself: --config-id skips every prompt, so there is nobody to ask, and enabling a login method for an operator who did not request it is not the installer's call. It now says how to enable it instead of only saying it is off.

Verified

  • Interactive run driven through a pty: Client id [ndp_frontend_prod]: accepted with Enter, .env gets OIDC_ENABLED=True with both defaults.
  • --oidc alone, and --oidc-client-id <other>, render the expected values; without any of them OIDC_ENABLED=False, unchanged.
  • The container started with that .env serves the UI a config.js carrying oidcEnabled, oidcIssuer and oidcClientId, and the realm's discovery document advertises S256, which is what the UI's PKCE flow needs.
  • 1204 tests pass, black --check . and flake8 clean.

While wiring the defaults, an unguarded reference to a variable that does not exist yet at the prompt would have aborted the script under set -u the moment anyone answered yes; it is not in the branch.

Raul Bardaji added 2 commits August 3, 2026 15:22
…e enabled

The installer offered sign-in through the identity provider and then asked
for a client id with no default and no way of finding one. A blank answer
switched it back off, so the feature was offered and could not be taken.

Endpoints in the NDP realm do not each need their own client: the platform's
public client serves any of them, in the realm the installer already suggests
as the issuer. Both are defaults now, so answering yes and pressing Enter is
enough, and a client registered for this Endpoint specifically can be given
instead.

Adds --oidc, --oidc-issuer and --oidc-client-id. These were the only prompts
with no flag behind them, which left unattended installs unable to enable
sign-in at all.
…in the browser

The client an Endpoint gets is confidential: a Federation registration creates
one per Endpoint and returns its id and secret. A secret cannot live in a
page, so the browser exchange could only ever answer 'Invalid client or
Invalid client credentials'.

The exchange moves to POST /user/oidc/exchange. The browser starts the flow
and brings back the code and its PKCE verifier; the API completes it, sending
the client secret from .env, which is never returned by any route and never
reaches the UI. A public client uses the same path with no secret configured.

The installer follows: the client id prompt can be left blank and the
registration's client, with its secret, is what gets written. There is no
default client id any more — the platform's own client is confidential and its
secret is not ours to have, so offering it would produce a sign-in that starts
and cannot finish.
@rbardaji rbardaji changed the title Make identity-provider sign-in enableable at install time Make identity-provider sign-in work with the registered client Aug 3, 2026
…lient

Without a registration there is no client in the provider's realm, so the
question could only be answered and then overruled — the installer would ask,
record a yes, and print that sign-in stays off anyway.

It is now asked only after registering. Otherwise the installer says what
sign-in needs and which flags enable it for an operator who already has a
client of their own, which the flags still support.
@rbardaji
rbardaji force-pushed the feature/219-oidc-default-client branch from f31b659 to 93c1596 Compare August 3, 2026 21:54
Raul Bardaji added 2 commits August 4, 2026 02:33
Asking for the realm URL and the client id was asking the operator to retype
what the installer already had: the registration names the realm and creates
the client with its secret, and the identity provider's host is the one
AUTH_API_URL validates tokens against — they have to be the same provider or
sign-in fails at the last step, so the host is a requirement rather than a
guess.

The realm URL is now derived from those two and checked against its discovery
document before anything is written. A realm that does not answer leaves
sign-in off and says so, instead of producing a login that starts and cannot
finish. The flags still cover a client or realm the registration did not
provide.
The stack was started with 'compose up -d', which builds only when no image
exists. On a machine that had run an Endpoint before, the container came back
from the image built the first time and the checkout was never compiled in:
the install reported success while running old code, a route added since
answered 404, and the UI served was the one built weeks earlier. Meanwhile
.env, rendered on every run, was current — so the mismatch read as a
configuration problem.

Started with --build now, as the CKAN stack already was. Unchanged sources
come from the layer cache.
@rbardaji

rbardaji commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Parking this. Identity-provider sign-in is not going into the installer until how it is meant to work is settled, so the option should not be offered at all in the meantime.

What this branch established, for whoever picks it up:

  • Every client in the NDP realm is confidential, including the one a Federation registration creates per Endpoint (publicClient: False, client-secret authenticator). A browser-side code exchange can therefore only ever answer unauthorized_client / "Invalid client or Invalid client credentials".
  • Exchanging the code on the Endpoint instead does work: with the registered client and its secret, the token endpoint answers invalid_grant ("Code not valid") for a fake code, i.e. the client authenticates.
  • It still fails one step later. Tokens minted for these clients carry no sub claim, and AUTH_API_URL looks the user up by sub, so it answers 500 {"error":"Failed to retrieve user details","details":"Role query failed"} — surfaced to the user as a 502 from /user/info. A token from the same client's service account does carry sub and validates fine, which is the contrast that isolates it.
  • The cause is the client factory in the AAI: defaultClientScopes: ["profile", "roles", "email"], without basic, which is where sub comes from since Keycloak 24. It cannot be worked around from the Endpoint — requesting the scope answers invalid_scope: basic, since it is assigned to the client neither by default nor optionally.

So this needs basic assigned to those clients (or added to the factory) before any of it can work end to end. The branch feature/219-oidc-default-client is kept.

The one commit here that is independent of all that — the installer reusing a stale image — is now #222.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enabling identity-provider sign-in requires a client id nobody can supply

1 participant