mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: publish RBAC scopes in OAuth2 metadata endpoints (#19942)
<!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> Publish supported OAuth2 scopes from RBAC external scope names This PR updates the OAuth2 metadata endpoints to publish the supported scopes from the RBAC external scope names. Previously, the `ScopesSupported` field was empty with a TODO to implement a scope system. Now, both the authorization server metadata and protected resource metadata endpoints return the list of scopes from `rbac.ExternalScopeNames()`. The tests have been updated to verify that the correct scopes are being returned in the metadata responses.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
@@ -46,6 +47,8 @@ func TestOAuth2AuthorizationServerMetadata(t *testing.T) {
|
||||
require.Contains(t, metadata.GrantTypesSupported, "authorization_code")
|
||||
require.Contains(t, metadata.GrantTypesSupported, "refresh_token")
|
||||
require.Contains(t, metadata.CodeChallengeMethodsSupported, "S256")
|
||||
// Supported scopes are published from the curated catalog
|
||||
require.Equal(t, rbac.ExternalScopeNames(), metadata.ScopesSupported)
|
||||
}
|
||||
|
||||
func TestOAuth2ProtectedResourceMetadata(t *testing.T) {
|
||||
@@ -80,7 +83,6 @@ func TestOAuth2ProtectedResourceMetadata(t *testing.T) {
|
||||
// RFC 6750 bearer tokens are now supported as fallback methods
|
||||
require.Contains(t, metadata.BearerMethodsSupported, "header")
|
||||
require.Contains(t, metadata.BearerMethodsSupported, "query")
|
||||
// ScopesSupported can be empty until scope system is implemented
|
||||
// Empty slice is marshaled as empty array, but can be nil when unmarshaled
|
||||
require.True(t, len(metadata.ScopesSupported) == 0)
|
||||
// Supported scopes are published from the curated catalog
|
||||
require.Equal(t, rbac.ExternalScopeNames(), metadata.ScopesSupported)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@@ -13,15 +14,14 @@ func GetAuthorizationServerMetadata(accessURL *url.URL) http.HandlerFunc {
|
||||
return func(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
metadata := codersdk.OAuth2AuthorizationServerMetadata{
|
||||
Issuer: accessURL.String(),
|
||||
AuthorizationEndpoint: accessURL.JoinPath("/oauth2/authorize").String(),
|
||||
TokenEndpoint: accessURL.JoinPath("/oauth2/tokens").String(),
|
||||
RegistrationEndpoint: accessURL.JoinPath("/oauth2/register").String(), // RFC 7591
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||
CodeChallengeMethodsSupported: []string{"S256"},
|
||||
// TODO: Implement scope system
|
||||
ScopesSupported: []string{},
|
||||
Issuer: accessURL.String(),
|
||||
AuthorizationEndpoint: accessURL.JoinPath("/oauth2/authorize").String(),
|
||||
TokenEndpoint: accessURL.JoinPath("/oauth2/tokens").String(),
|
||||
RegistrationEndpoint: accessURL.JoinPath("/oauth2/register").String(), // RFC 7591
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||
CodeChallengeMethodsSupported: []string{"S256"},
|
||||
ScopesSupported: rbac.ExternalScopeNames(),
|
||||
TokenEndpointAuthMethodsSupported: []string{"client_secret_post"},
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusOK, metadata)
|
||||
@@ -35,8 +35,7 @@ func GetProtectedResourceMetadata(accessURL *url.URL) http.HandlerFunc {
|
||||
metadata := codersdk.OAuth2ProtectedResourceMetadata{
|
||||
Resource: accessURL.String(),
|
||||
AuthorizationServers: []string{accessURL.String()},
|
||||
// TODO: Implement scope system based on RBAC permissions
|
||||
ScopesSupported: []string{},
|
||||
ScopesSupported: rbac.ExternalScopeNames(),
|
||||
// RFC 6750 Bearer Token methods supported as fallback methods in api key middleware
|
||||
BearerMethodsSupported: []string{"header", "query"},
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
@@ -35,6 +36,8 @@ func TestOAuth2AuthorizationServerMetadata(t *testing.T) {
|
||||
require.Contains(t, metadata.GrantTypesSupported, "authorization_code")
|
||||
require.Contains(t, metadata.GrantTypesSupported, "refresh_token")
|
||||
require.Contains(t, metadata.CodeChallengeMethodsSupported, "S256")
|
||||
// Supported scopes are published from the curated catalog
|
||||
require.Equal(t, rbac.ExternalScopeNames(), metadata.ScopesSupported)
|
||||
}
|
||||
|
||||
func TestOAuth2ProtectedResourceMetadata(t *testing.T) {
|
||||
@@ -60,7 +63,6 @@ func TestOAuth2ProtectedResourceMetadata(t *testing.T) {
|
||||
// RFC 6750 bearer tokens are now supported as fallback methods
|
||||
require.Contains(t, metadata.BearerMethodsSupported, "header")
|
||||
require.Contains(t, metadata.BearerMethodsSupported, "query")
|
||||
// ScopesSupported can be empty until scope system is implemented
|
||||
// Empty slice is marshaled as empty array, but can be nil when unmarshaled
|
||||
require.True(t, len(metadata.ScopesSupported) == 0)
|
||||
// Supported scopes are published from the curated catalog
|
||||
require.Equal(t, rbac.ExternalScopeNames(), metadata.ScopesSupported)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user