Fix bug in handling response content-type in oidcclient.

Before this, we weren't properly parsing the `Content-Type` header. This breaks in integration with the Supervisor since it sends an extra encoding parameter like `application/json;charset=UTF-8`.

This change switches to properly parsing with the `mime.ParseMediaType` function, and adds test cases to match the supervisor behavior.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
Matt Moyer 2020-12-10 10:09:42 -06:00
parent 5a0918afde
commit 9d3c98232b
No known key found for this signature in database
GPG Key ID: EAE88AD172C5AE2D
2 changed files with 34 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import (
"context"
"encoding/json"
"fmt"
"mime"
"net"
"net/http"
"net/url"
@ -364,8 +365,12 @@ func (h *handlerState) tokenExchangeRFC8693(baseToken *oidctypes.Token) (*oidcty
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected HTTP response status %d", resp.StatusCode)
}
if contentType := resp.Header.Get("content-type"); contentType != "application/json" {
return nil, fmt.Errorf("unexpected HTTP response content type %q", contentType)
mediaType, _, err := mime.ParseMediaType(resp.Header.Get("content-type"))
if err != nil {
return nil, fmt.Errorf("failed to decode content-type header: %w", err)
}
if mediaType != "application/json" {
return nil, fmt.Errorf("unexpected HTTP response content type %q", mediaType)
}
// Decode the JSON response body.

View File

@ -164,11 +164,14 @@ func TestLogin(t *testing.T) {
case "test-audience-produce-http-400":
http.Error(w, "some server error", http.StatusBadRequest)
return
case "test-audience-produce-invalid-content-type":
w.Header().Set("content-type", "invalid/invalid;=")
return
case "test-audience-produce-wrong-content-type":
w.Header().Set("content-type", "invalid")
return
case "test-audience-produce-invalid-json":
w.Header().Set("content-type", "application/json")
w.Header().Set("content-type", "application/json;charset=UTF-8")
_, _ = w.Write([]byte(`{`))
return
case "test-audience-produce-invalid-tokentype":
@ -601,6 +604,29 @@ func TestLogin(t *testing.T) {
},
wantErr: `failed to exchange token: unexpected HTTP response status 400`,
},
{
name: "with requested audience, session cache hit with valid token, but token exchange request returns invalid content-type header",
issuer: successServer.URL,
clientID: "test-client-id",
opt: func(t *testing.T) Option {
return func(h *handlerState) error {
cache := &mockSessionCache{t: t, getReturnsToken: &testToken}
t.Cleanup(func() {
require.Equal(t, []SessionCacheKey{{
Issuer: successServer.URL,
ClientID: "test-client-id",
Scopes: []string{"test-scope"},
RedirectURI: "http://localhost:0/callback",
}}, cache.sawGetKeys)
require.Empty(t, cache.sawPutTokens)
})
require.NoError(t, WithSessionCache(cache)(h))
require.NoError(t, WithRequestAudience("test-audience-produce-invalid-content-type")(h))
return nil
}
},
wantErr: `failed to exchange token: failed to decode content-type header: mime: invalid media parameter`,
},
{
name: "with requested audience, session cache hit with valid token, but token exchange request returns wrong content-type",
issuer: successServer.URL,