mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-03 08:19:04 +02:00
feat: serve RFC 8414 authorization server metadata (#1685)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
co-authored by
Claude Opus 5
Elias Schneider
parent
86cf73b86c
commit
46b8d54e15
@@ -2,8 +2,11 @@ package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/lestrrat-go/jwx/v3/jwa"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -42,7 +45,7 @@ func TestClientIDMetadataDocumentDiscoveryFollowsAllowlist(t *testing.T) {
|
||||
|
||||
parse := func(t *testing.T) map[string]any {
|
||||
t.Helper()
|
||||
raw, err := wkc.computeOIDCConfiguration()
|
||||
raw, err := wkc.computeServerMetadata()
|
||||
require.NoError(t, err)
|
||||
var cfg map[string]any
|
||||
require.NoError(t, json.Unmarshal(raw, &cfg))
|
||||
@@ -55,3 +58,55 @@ func TestClientIDMetadataDocumentDiscoveryFollowsAllowlist(t *testing.T) {
|
||||
cimdURLAllowlist = nil
|
||||
assert.Equal(t, false, parse(t)["client_id_metadata_document_supported"])
|
||||
}
|
||||
|
||||
func TestOAuthAuthorizationServerMetadata(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
origAppURL := common.EnvConfig.AppURL
|
||||
origInternalAppURL := common.EnvConfig.InternalAppURL
|
||||
t.Cleanup(func() {
|
||||
common.EnvConfig.AppURL = origAppURL
|
||||
common.EnvConfig.InternalAppURL = origInternalAppURL
|
||||
})
|
||||
common.EnvConfig.AppURL = "https://test.example.com"
|
||||
common.EnvConfig.InternalAppURL = "https://test.example.com"
|
||||
|
||||
router := gin.New()
|
||||
NewWellKnownController(router.Group("/"), newMinimalJwtService(t), func() []string { return nil })
|
||||
|
||||
get := func(t *testing.T, path string) *httptest.ResponseRecorder {
|
||||
t.Helper()
|
||||
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, path, http.NoBody)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
return w
|
||||
}
|
||||
|
||||
w := get(t, "/.well-known/oauth-authorization-server")
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
require.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
|
||||
var doc map[string]any
|
||||
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &doc))
|
||||
|
||||
assert.Equal(t, common.EnvConfig.AppURL, doc["issuer"])
|
||||
assert.Equal(t, common.EnvConfig.AppURL+"/authorize", doc["authorization_endpoint"])
|
||||
assert.Equal(t, common.EnvConfig.InternalAppURL+"/api/oidc/token", doc["token_endpoint"])
|
||||
assert.Contains(t, doc["response_types_supported"], "code")
|
||||
assert.NotEmpty(t, doc["jwks_uri"])
|
||||
assert.Contains(t, doc["scopes_supported"], "openid")
|
||||
assert.Contains(t, doc["grant_types_supported"], "authorization_code")
|
||||
assert.Contains(t, doc["code_challenge_methods_supported"], "S256")
|
||||
assert.Equal(t, "https://pocket-id.org/docs", doc["service_documentation"])
|
||||
assert.ElementsMatch(t, []any{"query", "fragment", "form_post"}, doc["response_modes_supported"])
|
||||
assert.NotContains(t, doc, "revocation_endpoint")
|
||||
assert.NotContains(t, doc, "registration_endpoint")
|
||||
|
||||
for name, value := range doc {
|
||||
if arr, ok := value.([]any); ok {
|
||||
assert.NotEmpty(t, arr, "metadata member %q must be omitted when it has no values", name)
|
||||
}
|
||||
}
|
||||
|
||||
assert.JSONEq(t, get(t, "/.well-known/openid-configuration").Body.String(), w.Body.String())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user