Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions client/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,10 @@ func (h *Handler) patchOAuth2Client(w http.ResponseWriter, r *http.Request) {

oldSecret := client.Secret

// RegistrationAccessTokenSignature is lost when the client is marshalled to JSON
// Store it prior to the patch and re-add it later
oldRegistrationAccessTokenSig := client.RegistrationAccessTokenSignature

client, err = jsonx.ApplyJSONPatch(patchJSON, client, "/id")
if err != nil {
h.r.Writer().WriteError(w, r, err)
Expand All @@ -462,6 +466,9 @@ func (h *Handler) patchOAuth2Client(w http.ResponseWriter, r *http.Request) {
client.Secret = ""
}

// Re-add the registration access token signature before updating the client in DB
client.RegistrationAccessTokenSignature = oldRegistrationAccessTokenSig

if err := h.updateClient(r.Context(), client, h.r.ClientValidator().Validate); err != nil {
h.r.Writer().WriteError(w, r, err)
return
Expand Down
21 changes: 21 additions & 0 deletions client/sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,27 @@ func TestClientSDK(t *testing.T) {
assertx.EqualAsJSONExcept(t, expected, result, nil)
})

t.Run("case=patch preserves registration access token", func(t *testing.T) {
created, _, err := c.OAuth2API.CreateOAuth2Client(context.Background()).OAuth2Client(createTestClient("")).Execute()
require.NoError(t, err)
require.NotNil(t, created.RegistrationAccessToken)
originalRAT := *created.RegistrationAccessToken

_, _, err = c.OAuth2API.PatchOAuth2Client(context.Background(), *created.ClientId).
JsonPatch([]hydra.JsonPatch{{Op: "replace", Path: "/client_uri", Value: "http://foo.bar"}}).Execute()
require.NoError(t, err)

dynURL := publicServer.URL + client.DynClientsHandlerPath + "/" + *created.ClientId

req, err := http.NewRequest(http.MethodGet, dynURL, nil)
require.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+originalRAT)
res, err := http.DefaultClient.Do(req)
require.NoError(t, err)
_ = res.Body.Close()
assert.Equal(t, http.StatusOK, res.StatusCode, "registration access token must still be valid after admin PATCH")
})

t.Run("case=patch client illegally", func(t *testing.T) {
op := "replace"
path := "/id"
Expand Down
Loading