feat: Add RFC 8414 OAuth 2.0 Authorization Server Metadata endpoint#1665
feat: Add RFC 8414 OAuth 2.0 Authorization Server Metadata endpoint#1665zacharypodbela wants to merge 2 commits intodjango-oauth:masterfrom
Conversation
|
@dopry could I get a review on this? |
b6b1c88 to
d5108c7
Compare
There was a problem hiding this comment.
Pull request overview
Adds an RFC 8414-compliant OAuth 2.0 Authorization Server Metadata discovery endpoint and refactors existing OIDC discovery code to reuse shared URL-building logic.
Changes:
- Added
/.well-known/oauth-authorization-serverendpoint with RFC 8414 metadata response and CORS header. - Introduced
ServerMetadataViewMixinand refactoredConnectDiscoveryInfoViewto remove duplicated endpoint URL-building logic. - Added new settings defaults + documentation, and tests for endpoint behavior (issuer derivation, JWKS conditional, CORS, OIDC disabled).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_oidc_views.py | Adds tests validating RFC 8414 metadata response shape and key conditionals. |
| oauth2_provider/views/oidc.py | Refactors OIDC discovery to reuse shared endpoint URL builder. |
| oauth2_provider/views/metadata.py | Implements the RFC 8414 metadata endpoint + shared URL-building mixin. |
| oauth2_provider/views/init.py | Exposes the new metadata view for URL registration. |
| oauth2_provider/urls.py | Registers the /.well-known/oauth-authorization-server route. |
| oauth2_provider/settings.py | Adds OAuth2 metadata settings and an issuer helper method. |
| docs/settings.rst | Documents new settings related to the metadata endpoint. |
| docs/oauth2_server_metadata.rst | Adds user-facing docs for the RFC 8414 endpoint. |
| docs/index.rst | Adds the new docs page to the documentation index. |
| CHANGELOG.md | Notes the new endpoint in the unreleased changelog. |
| abs_url = request.build_absolute_uri(reverse("oauth2_provider:oauth-server-metadata")) | ||
| return abs_url[: -len("/.well-known/oauth-authorization-server")] |
There was a problem hiding this comment.
The issuer calculation relies on a hard-coded path suffix (\"/.well-known/oauth-authorization-server\"). This will silently break if the URL pattern changes. Prefer deriving the suffix from reverse(\"oauth2_provider:oauth-server-metadata\") (or using a removesuffix()-style approach with the reversed path) so this stays correct if the route is modified.
| abs_url = request.build_absolute_uri(reverse("oauth2_provider:oauth-server-metadata")) | |
| return abs_url[: -len("/.well-known/oauth-authorization-server")] | |
| metadata_path = reverse("oauth2_provider:oauth-server-metadata") | |
| abs_url = request.build_absolute_uri(metadata_path) | |
| if abs_url.endswith(metadata_path): | |
| return abs_url[: -len(metadata_path)] | |
| return abs_url |
| "introspection_endpoint": self._get_endpoint_url(request, "introspect"), | ||
| "response_types_supported": oauth2_settings.OAUTH2_RESPONSE_TYPES_SUPPORTED, | ||
| "grant_types_supported": oauth2_settings.OAUTH2_GRANT_TYPES_SUPPORTED, | ||
| "scopes_supported": list(scopes.get_available_scopes()), |
There was a problem hiding this comment.
For metadata documents, producing deterministic output is useful (and avoids flaky tests/clients doing strict comparisons). scopes_supported currently preserves whatever ordering the scopes backend returns, which may vary by backend implementation. Consider normalizing to a stable order (e.g., sorting) before returning.
| "scopes_supported": list(scopes.get_available_scopes()), | |
| "scopes_supported": sorted(scopes.get_available_scopes()), |
| response = self.client.get(reverse("oauth2_provider:oauth-server-metadata")) | ||
| self.assertEqual(response.status_code, 200) | ||
| assert response.json() == expected_response |
There was a problem hiding this comment.
This test asserts full JSON equality, which can become brittle if any list fields are legitimately reordered (e.g., scopes_supported, code_challenge_methods_supported). If ordering is not part of the contract, consider asserting per-field presence/values (order-insensitive where appropriate), or sorting the corresponding fields in the response before comparing.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Implements the /.well-known/oauth-authorization-server discovery endpoint per RFC 8414. Unlike the existing OIDC discovery endpoint, this is available regardless of whether OIDC is enabled. - Add OAuthServerMetadataView and ServerMetadataViewMixin in new metadata.py - Refactor ConnectDiscoveryInfoView to use ServerMetadataViewMixin, removing duplicated URL-building logic - Add OAUTH2_RESPONSE_TYPES_SUPPORTED, OAUTH2_GRANT_TYPES_SUPPORTED, and OAUTH2_TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED settings with defaults - Add oauth2_metadata_issuer() helper to OAuth2ProviderSettings - Register endpoint in base_urlpatterns as oauth-server-metadata Closes django-oauth#1099 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add oauth2_server_metadata.rst with endpoint description and example response - Link from index.rst toctree after oidc - Document OAUTH2_RESPONSE_TYPES_SUPPORTED, OAUTH2_GRANT_TYPES_SUPPORTED, and OAUTH2_TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED in settings.rst Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
d5108c7 to
2a42baa
Compare
|
@zacharypodbela can you review the copilot comments and address them? |
Summary
Implements the
/.well-known/oauth-authorization-serverdiscovery endpoint per RFC 8414 — OAuth 2.0 Authorization Server Metadata.Closes #1099
Changes
oauth2_provider/views/metadata.py— containsServerMetadataViewMixin(shared URL-building logic for discovery views) andOAuthServerMetadataView(the RFC 8414 endpoint). The view is available regardless of whether OIDC is enabled and has noOIDCOnlyMixindependency.ConnectDiscoveryInfoView— now inheritsServerMetadataViewMixin, eliminating the duplicated if/else URL-building logic that previously existed for the request-relative vsOIDC_ISS_ENDPOINT-anchored cases.OAUTH2_RESPONSE_TYPES_SUPPORTEDOAUTH2_GRANT_TYPES_SUPPORTEDOAUTH2_TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTEDoauth2_metadata_issuer()helper onOAuth2ProviderSettings, mirroring the existingoidc_issuer().oauth-server-metadataregistered inbase_urlpatterns.OIDC_ISS_ENDPOINT),jwks_uriconditional on RSA key presence, CORS header, and availability when OIDC is disabled.Relationship to OIDC discovery
RFC 8414 is the OAuth 2.0 equivalent of OpenID Connect discovery. The key differences from
ConnectDiscoveryInfoView:/.well-known/openid-configuration/.well-known/oauth-authorization-serveruserinfo_endpointjwks_urigrant_types_supportedrevocation_endpointintrospection_endpoint