Skip to content

feat(auth): request the api scope for backend access#647

Merged
jorgeparavicini merged 1 commit into
mainfrom
feat(auth)/request-api-scope
Jul 3, 2026
Merged

feat(auth): request the api scope for backend access#647
jorgeparavicini merged 1 commit into
mainfrom
feat(auth)/request-api-scope

Conversation

@jorgeparavicini

Copy link
Copy Markdown
Contributor

What & why

Part of moving the platform to standard OAuth audience validation. The backend will start validating that access tokens carry its audience (aud=https://api.rapidata.ai). A token only gets that audience if the client requests the api scope, so the SDK needs to request it.

Adds api to the requested scopes on both auth paths:

  • client-credentials — the oauth_scope default ("openid roles email""openid roles email api").
  • interactive browser/bridge login — the rapidata-cli authorize URL.

With the existing scope→resource mapping on the identity server, requesting api makes the issued access token carry aud=https://api.rapidata.ai (+ scp:api).

Why now / safety

This is the migration driver: backend audience enforcement will be turned on only after enough customers have upgraded to an SDK version that requests api (a 1–2 month window, watched via token telemetry). Shipping this early is safe — the api scope is already granted to these clients, so it only adds the audience to tokens; nothing changes until enforcement flips.

Tests / checks

pyright src/rapidata/rapidata_client clean; black formatted. No auto-generated client files touched (no mustache-template changes needed).

🔗 Session: https://session-d22747c4.poseidon.rapidata.internal/

Add `api` to the scopes the SDK requests, on both auth paths:
- client-credentials (`oauth_scope` default)
- interactive browser/bridge login (`rapidata-cli`)

With the standard scope→resource mapping, this makes the SDK's access tokens
carry the backend api audience (aud=https://api.rapidata.ai) so they keep working
once the backend enforces audience validation. Safe before enforcement — the api
scope is already granted to these clients, so this only adds the audience.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: RapidPoseidon <poseidon@rapidata.ai>
@claude

claude Bot commented Jul 3, 2026

Copy link
Copy Markdown

Reviewed this PR. It's a small, well-scoped change and the rationale in the PR description (adding the migration driver ahead of backend audience enforcement) is clear.

Correctness

  • The oauth_scope default change in rapidata_client.py:70 is correctly threaded through — openapi_service.py uses this same value on both the initial setup_oauth_client_credentials call and the retry-after-reset path (lines 109/130), so client-credential auth is consistently updated.
  • The credential_manager.py:271 bridge/browser authorize URL is the only other place a scope string is hardcoded (confirmed via grep across src/rapidata — no other scope=/oauth_scope usage was missed).
  • The setup_oauth_with_token path (used when a caller passes a pre-fetched token dict directly) doesn't go through oauth_scope at all, which is expected — that's out of scope for this change since the token's audience is whatever was requested when it was issued.

Documentation gap

docs/authentication.md:62 still says "The SDK requests openid roles email by default" — this is now stale since the default is "openid roles email api". Per the project's own CLAUDE.md guidance ("when updating any interfaces make sure you update the docs and examples"), this line (and possibly the scopes table below it) should be updated to mention api and what it grants (audience https://api.rapidata.ai), so users reading the docs aren't confused about the actual default.

Minor / non-blocking

  • credential_manager.py:271 builds the authorize URL with unencoded spaces in the scope query parameter (scope=openid profile email roles api). This is a pre-existing pattern (not introduced by this PR) and browsers/servers generally tolerate raw spaces in a location bar, but it might be worth a follow-up to properly URL-encode this query string (e.g. via urllib.parse.urlencode) for robustness.
  • No test coverage was added or previously existed for the scope defaults in rapidata_client.py or the authorize URL construction in credential_manager.py. Given this is a security/auth-relevant change, a simple unit test asserting the default oauth_scope value and/or the constructed auth_url would guard against accidental regressions (e.g., someone later dropping api while touching this code).

Style

Diff is black-formatted and consistent with the rest of the file (the incidental reformat of the RapidataSignalManager line onto one line is a harmless side effect of running black).

Overall: safe, low-risk, well-justified change. Recommend updating docs/authentication.md before merging, and optionally adding a small regression test.

@jorgeparavicini jorgeparavicini marked this pull request as ready for review July 3, 2026 09:06
@jorgeparavicini jorgeparavicini merged commit 920ae45 into main Jul 3, 2026
3 checks passed
@jorgeparavicini jorgeparavicini deleted the feat(auth)/request-api-scope branch July 3, 2026 09:28
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.

2 participants