Skip to content

[WPB-28193] Disentangle oauth scopes (write access should not imply read access). - #5542

Merged
blackheaven merged 36 commits into
developfrom
WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_
Oct 20, 2026
Merged

blackheaven merged 36 commits into
developfrom
WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_

Conversation

@fisx

@fisx fisx commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

https://wearezeta.atlassian.net/browse/WPB-28193

The problem

We need to express the following oauth access policy: we want to grant oauth access to {PUT,DELETE} /meetings/<domain>/<id>, but not to GET on the same route.

The current implementation of oauth scopes is cumulative: write:conversations implies read:conversations, admin:bla implies write:bla, read:bla. This language cannot express the above policy.

Here is what works: we want to grant write:conversations, so we issue write:conversations tokens and add oauth_scope: conversation to the nginz route, and on PUT,POST requests, the write: is attached to it before checking against the token. We don't want to grant read:conversations, though, but that's ok, because there is no route GET /conversations, and nginz will never construct one.

Now we want to grant write-only and delete-only to /meetings/<id>, which does have a GET route, so this trick does not work any more.

Existing oauth apps and tokens must keep working without interruption.

The solution

Deprecate the oauth_scope nginx directive and introduce a new oauth_scopes directive that supports tiers read, write-only, delete-only instead of read, write, admin.

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Sep 16, 2026
@fisx
fisx force-pushed the WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ branch 6 times, most recently from 5d10243 to aa33c72 Compare September 23, 2026 11:11
Comment thread charts/nginz/values.yaml
Comment thread libs/cassandra-util/src/Cassandra/CQL.hs
Comment thread services/nginz/third_party/nginx-zauth-module/zauth_module.c
Comment thread libs/wire-api/src/Wire/API/OAuth.hs
Comment thread libs/wire-api/src/Wire/API/OAuth.hs
@fisx
fisx marked this pull request as ready for review September 23, 2026 13:19
@fisx
fisx requested review from a team as code owners September 23, 2026 13:19
@fisx
fisx requested a lite review from Copilot September 24, 2026 07:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved backward-compatibility issues affect legacy scope parsing, refresh-token permissions, empty scopes, and directive validation.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

This PR introduces independent OAuth read, write-only, and delete-only scopes while retaining legacy configuration support.

Changes:

  • Adds oauth_scopes support across nginx, libzauth, OAuth APIs, and charts.
  • Updates persistence, route documentation, tests, and deployment configurations.
  • Documents migration from the deprecated oauth_scope directive.
File Summary
services/​nginz/​third_party/​nginx-zauth-module/​zauth_module.c Adds nginx scope-list handling.
services/​nginz/​integration-test/​conf/​nginz/​nginx.conf Tests new scope configuration.
services/​brig/​test/​integration/​API/​OAuth.hs Updates OAuth integration tests.
services/​brig/​src/​Brig/​API/​OAuth.hs Persists typed scope sets.
libs/​wire-api/​test/​unit/​Test/​Wire/​API/​Routes/​OAuthScopes.hs Validates route scope declarations.
libs/​wire-api/​test/​unit/​Test/​Wire/​API/​OAuth.hs Tests scope parsing and migration.
libs/​wire-api/​src/​Wire/​API/​Routes/​Public/​Galley/​Meetings.hs Updates meeting route scopes.
libs/​wire-api/​src/​Wire/​API/​Routes/​Public/​Galley/​Conversation.hs Updates conversation route scopes.
libs/​wire-api/​src/​Wire/​API/​Routes/​Public.hs Updates scope documentation rendering.
libs/​wire-api/​src/​Wire/​API/​OAuth.hs Defines scopes and legacy conversion.
libs/​libzauth/​libzauth/​src/​oauth.rs Implements tier-aware verification.
libs/​libzauth/​libzauth/​src/​lib.rs Exports verification support.
libs/​libzauth/​libzauth-c/​src/​zauth.h Declares the C API.
libs/​libzauth/​libzauth-c/​src/​lib.rs Exposes the C wrapper.
libs/​cassandra-util/​src/​Cassandra/​CQL.hs Exports Cassandra set support.
libs/​cassandra-util/​src/​Cassandra.hs Re-exports Cassandra support.
integration/​test/​Testlib/​HTTP.hs Adds Host-aware request support.
integration/​test/​Test/​OAuth.hs Adds OAuth integration coverage.
integration/​test/​API/​Nginz.hs Adds nginx OAuth helpers.
docs/​src/​developer/​reference/​config-options.md Documents scope configuration.
deploy/​dockerephemeral/​federation-v2/​nginz/​conf/​nginx.conf Migrates nginx configuration.
deploy/​dockerephemeral/​federation-v1/​nginz/​conf/​nginx.conf Migrates nginx configuration.
deploy/​dockerephemeral/​federation-v0/​nginz/​conf/​nginx.conf Migrates nginx configuration.
charts/​nginz/​values.yaml Defines new route scopes.
charts/​nginz/​templates/​conf/​_nginx.conf.tpl Renders new scope directives.
changelog.d/​1-api-changes/​WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ Adds API changelog entry.
changelog.d/​0-release-notes/​WPB-28193-nginx-conf-syntax-changed Documents configuration migration.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread libs/wire-api/src/Wire/API/OAuth.hs
Comment thread charts/nginz/values.yaml Outdated

@battermann battermann left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you verify if the docs: https://docs.wire.com/latest/developer/reference/oauth.html are still up to date with this?

Comment thread services/brig/test/integration/API/OAuth.hs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Legacy OAuth scope entries need validation against supported scopes.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)

Comment thread libs/wire-api/test/unit/Test/Wire/API/Routes/OAuthScopes.hs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical OAuth compatibility regressions and a test compilation error remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 6 High severity

Open (6)
Resolved since last review (1)

Comment thread charts/nginz/values.yaml Outdated
Comment thread deploy/dockerephemeral/federation-v0/nginz/conf/nginx.conf Outdated
Comment thread deploy/dockerephemeral/federation-v1/nginz/conf/nginx.conf Outdated
Comment thread deploy/dockerephemeral/federation-v2/nginz/conf/nginx.conf Outdated
Comment thread libs/wire-api/test/unit/Test/Wire/API/Routes/OAuthScopes.hs Outdated
Comment thread services/nginz/integration-test/conf/nginz/nginx.conf Outdated
@battermann
battermann force-pushed the WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ branch from 3a83dbe to 6f238cc Compare September 24, 2026 15:16
@fisx

fisx commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Can you verify if the docs: https://docs.wire.com/latest/developer/reference/oauth.html are still up to date with this?

https://github.com/wireapp/wire-docs/pull/131/changes

it's on my list...

@fisx
fisx force-pushed the WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ branch from 6f238cc to 848afbd Compare September 28, 2026 06:13
fisx and others added 16 commits October 20, 2026 13:26
Restore the ReadConversationsCode constructor dropped by the WIP commit and
give DELETE /conversations/<id>/code its own delete-only:conversations_code
scope, so legacy admin:conversations_code tokens keep working.  Document the
scope in the route annotation and all nginz route tables.
Enforce write-only:meetings on update-meeting and delete-only:meetings on
delete-meeting, document both in nginz route tables, and make old
admin:meetings tokens expand to write+delete so they keep deleting meetings.
Also translate the deprecated write:feature_configs tier to read for old
tokens.
@blackheaven
blackheaven force-pushed the WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ branch from 848afbd to 39fb4af Compare October 20, 2026 13:35
@blackheaven
blackheaven requested a lite review from Copilot October 20, 2026 13:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread libs/wire-api/src/Wire/API/OAuth.hs
Comment thread libs/wire-api/src/Wire/API/Routes/Public/Galley/Meetings.hs
Fix the refresh-meeting-link route annotation that came in from develop
('WriteMeetings -> 'WriteOnlyMeetings) so the branch compiles; record the
meetings scopes in the nginz integration conf for parity with values.yaml;
update the integration test that expected delete-only:conversations_code to
be unparseable; drop the dead allScopes helper, a duplicated test assertion,
a stale scratch block, and a stale haddock example.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved moderate issues affect legacy compatibility, route documentation, and end-to-end meeting authorization coverage.

1 open issue
2 resolved since last review

Review effort: Lite

Comment thread charts/nginz/values.yaml
- path: /meetings/([^/]*)/([^/]*)$
envs:
- all
oauth_scopes: ["write-only:meetings", "delete-only:meetings"]
@blackheaven
blackheaven merged commit 7efe9b4 into develop Oct 20, 2026
10 checks passed
@blackheaven
blackheaven deleted the WPB-28193-disentangle-oauth-scopes-_write-access-should-not-imply-read-access_ branch October 20, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants