Skip to content

Aurora: the OAuth consent screen, and serving the authorization server (#132, phase 9) - #141

Draft
sneridagh wants to merge 1 commit into
issue-132-phase-8from
issue-132-phase-9
Draft

sneridagh wants to merge 1 commit into
issue-132-phase-8from
issue-132-phase-9

Conversation

@sneridagh

Copy link
Copy Markdown
Member

Ninth and last page phase of #132, stacked on #140. Draft: please don't merge. Each phase gets its own PR, built on the previous one, and none is merged until the whole series has been reviewed.

OAuth consent, from the plan. With it, Aurora can be the frontend of a site that is an OpenID Connect provider. Every page a user meets now exists in both add-ons; the control panels stay Volto-only.

The panel moves to core

ConsentPanel and answerUrl move to identity-core, with their 18 tests (core 356 → 374, Volto 612 → 594), story, CONSENT_REQUEST fixture and 8 translated messages. Volto's Consent keeps its Redux state and renders the panel inside VoltoIdentityUI.

Aurora's /oauth-consent

Under publicui's layout. The loader describes the request through @oauth-consent as the user; a signed-out visitor goes to /login with the request as came_from. The answer is not sent from the page. It is a navigation back to the authorization endpoint (answerUrl), as in Volto, because the endpoint answers with a redirect the browser must follow. noindex in meta.

Aurora serves the authorization server's endpoints

This is the part Volto gets from elsewhere. @@oauth-authorize and its siblings are backend browser views, not REST services. With Volto, a reverse-proxy rule routes them to the backend (concepts/federation.md, and the demo stack's traefik labels). The backend recognises the user at @@oauth-authorize by a Bearer token or Volto's auth_token cookie. Aurora's session is its own signed cookie, which the backend cannot read, so even behind that rule Aurora users would arrive at the authorize endpoint anonymous.

So Aurora passes those requests on itself (lib/oauth.ts, routes/oauth.ts):

Path Passed on with
@@oauth-authorize The session's token as Bearer, and nothing the browser sent as Authorization: a cached Basic credential must not stand in for the user
@@oauth-token, @@oauth-jwks, @@oauth-userinfo The relying party's own Authorization, content type and body
.well-known/openid-configuration As it came. By its full path: a splat would reach Aurora's content middleware as a page to fetch

The details:

  • Backend URL. Each request goes through the virtual-host URL without ++api++ (backendUrl(..., { api: false })), so the backend's answers name Aurora's address.
  • What comes back. Only Location, Content-Type, Cache-Control, Pragma and WWW-Authenticate are passed back. No Set-Cookie, and the browser's cookies are never sent on.

Two smaller pieces close the loop:

  • require_login: a signed-out visitor at the authorize endpoint is sent to Plone's challenge, /acl_users/credentials_cookie_auth/require_login?came_from=…. Aurora answers it with /login?came_from=….
  • redirectDocument: a password sign-in whose came_from is a backend view leaves the app with a full page load, since it is not a route the router can navigate to. Unit test seen failing without it.

One cost. Aurora's own request handling runs first on every passed-on request, and fetches the site root's content for it. Documented in concepts/frontends.md.

Acceptance tests

oauth-consent.spec.ts. The setup installs the [server] layer through @addons, sets server_issuer to Aurora's address and server_consent_url to /oauth-consent, and registers a confidential client, test-app. The cleanup undoes all three.

Test Checks
Agree Signed in with Dex, the authorization request reaches the consent screen, which names the app and the user. Allow sends the browser to the app's redirect URI with a code and the state
The app's side Discovery fetched from Aurora names Aurora as issuer, and the code is exchanged at Aurora's @@oauth-token for an access token and an ID token
The grant Listed on /applications, withdrawn through the dialog. This is the full flow phase 8 left for this phase
Refuse Deny reaches the app as error=access_denied
Signed out The authorize request → Plone's challenge → Aurora's /login → Dex → back to the authorize request → the consent screen

All 14 acceptance tests pass locally, twice in a row. Not run in CI yet.

Checks

Check Result
Tests Core 374, Volto 594, Aurora add-on 53 (+4 lib/oauth, +2 require-login, +2 login, +1 backendUrl)
make -C frontend lint, make aurora-lint, both typechecks Pass
ci-i18n, both harnesses Pass
Storybook; Volto pnpm build; make aurora-build Pass
make docs-build; Vale Pass; 0 errors

Docs

concepts/frontends.md gains "In front of an authorization server", and its "What Aurora does not have yet" is now the control panels alone. concepts/federation.md notes that Aurora needs no OAuth routing rule.

…erver

- ConsentPanel and answerUrl move to identity-core, with their 18 tests,
  story, fixture and translations. Volto's Consent renders the panel.
- Aurora's /oauth-consent: the loader describes the request through
  @oauth-consent as the user; the answer is a navigation back to the
  authorization endpoint.
- Aurora passes the authorization server's endpoints on to the backend
  (@@oauth-authorize, @@oauth-token, @@oauth-jwks, @@oauth-userinfo,
  .well-known/openid-configuration), through the virtual-host URL without
  ++api++. On @@oauth-authorize it sends the session as a bearer token:
  the backend cannot read Aurora's cookie. No reverse-proxy rule needed.
- Plone's require_login challenge is answered with Aurora's /login,
  keeping came_from; a password sign-in returning to a backend view
  leaves the app with redirectDocument.
- Playwright: a signed-in user agrees, the application gets a code and
  exchanges it for tokens at Aurora's address, the grant is listed on
  /applications and withdrawn; a refusal reaches the application as
  access_denied; a signed-out visitor signs in through Dex first.

Refs #132

This branch has not been deployed

No deployments
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.

1 participant