From 1897f318c522ce3d5698e5cca234ab170bf10596 Mon Sep 17 00:00:00 2001 From: Mihai Plasoianu Date: Wed, 29 Sep 2021 12:11:07 +0200 Subject: [PATCH] feat: allow both string and []string in aud field (#822) Closes #491 Closes #601 Closes #792 Closes #810 --- .../authenticator_oauth2_introspection.go | 33 ++++++++++++++++++- ...authenticator_oauth2_introspection_test.go | 18 ++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/pipeline/authn/authenticator_oauth2_introspection.go b/pipeline/authn/authenticator_oauth2_introspection.go index f7eb763fa2..1d823e35dc 100644 --- a/pipeline/authn/authenticator_oauth2_introspection.go +++ b/pipeline/authn/authenticator_oauth2_introspection.go @@ -82,12 +82,14 @@ func (a *AuthenticatorOAuth2Introspection) GetID() string { return "oauth2_introspection" } +type Audience []string + type AuthenticatorOAuth2IntrospectionResult struct { Active bool `json:"active"` Extra map[string]interface{} `json:"ext"` Subject string `json:"sub,omitempty"` Username string `json:"username"` - Audience []string `json:"aud"` + Audience Audience `json:"aud,omitempty"` TokenType string `json:"token_type"` Issuer string `json:"iss"` ClientID string `json:"client_id,omitempty"` @@ -96,6 +98,35 @@ type AuthenticatorOAuth2IntrospectionResult struct { TokenUse string `json:"token_use"` } +func (a *Audience) UnmarshalJSON(b []byte) error { + var errUnsupportedType = errors.New("Unsupported aud type, only string or []string are allowed") + + var jsonObject interface{} + err := json.Unmarshal(b, &jsonObject) + if err != nil { + return err + } + + switch o := jsonObject.(type) { + case string: + *a = Audience{o} + return nil + case []interface{}: + s := make(Audience, 0, len(o)) + for _, v := range o { + value, ok := v.(string) + if !ok { + return errUnsupportedType + } + s = append(s, value) + } + *a = s + return nil + } + + return errUnsupportedType +} + func (a *AuthenticatorOAuth2Introspection) tokenFromCache(config *AuthenticatorOAuth2IntrospectionConfiguration, token string, ss fosite.ScopeStrategy) *AuthenticatorOAuth2IntrospectionResult { if !config.Cache.Enabled { return nil diff --git a/pipeline/authn/authenticator_oauth2_introspection_test.go b/pipeline/authn/authenticator_oauth2_introspection_test.go index 1ff3df1ea9..01ed11668c 100644 --- a/pipeline/authn/authenticator_oauth2_introspection_test.go +++ b/pipeline/authn/authenticator_oauth2_introspection_test.go @@ -840,4 +840,22 @@ func TestAuthenticatorOAuth2Introspection(t *testing.T) { require.NotEqual(t, noPreauthClient3, noPreauthClient) }) }) + + t.Run("unmarshal-audience", func(t *testing.T) { + t.Run("Should pass because audience is a valid string", func(t *testing.T) { + var aud Audience + data := `"audience"` + json.Unmarshal([]byte(data), &aud) + require.NoError(t, err) + require.Equal(t, Audience{"audience"}, aud) + }) + + t.Run("Should pass because audience is a valid string array", func(t *testing.T) { + var aud Audience + data := `["audience1","audience2"]` + json.Unmarshal([]byte(data), &aud) + require.NoError(t, err) + require.Equal(t, Audience{"audience1", "audience2"}, aud) + }) + }) }