diff --git a/driver/config/provider.go b/driver/config/provider.go index 22db1582344..5b90700bb2e 100644 --- a/driver/config/provider.go +++ b/driver/config/provider.go @@ -5,6 +5,7 @@ package config import ( "context" + "encoding/json" "fmt" "net/http" "net/url" @@ -102,8 +103,8 @@ const ( KeyOAuth2GrantJWTIDOptional = "oauth2.grant.jwt.jti_optional" KeyOAuth2GrantJWTIssuedDateOptional = "oauth2.grant.jwt.iat_optional" KeyOAuth2GrantJWTMaxDuration = "oauth2.grant.jwt.max_ttl" - KeyRefreshTokenHookURL = "oauth2.refresh_token_hook" // #nosec G101 - KeyTokenHookURL = "oauth2.token_hook" // #nosec G101 + KeyRefreshTokenHook = "oauth2.refresh_token_hook" // #nosec G101 + KeyTokenHook = "oauth2.token_hook" // #nosec G101 KeyDevelopmentMode = "dev" ) @@ -467,12 +468,52 @@ func (p *DefaultProvider) AccessTokenStrategy(ctx context.Context, additionalSou return s } -func (p *DefaultProvider) TokenHookURL(ctx context.Context) *url.URL { - return p.getProvider(ctx).RequestURIF(KeyTokenHookURL, nil) +type ( + Auth struct { + Type string `json:"type"` + Config json.RawMessage `json:"config"` + } + HookConfig struct { + URL string `json:"url"` + Auth *Auth `json:"auth"` + } +) + +func (p *DefaultProvider) getHookConfig(ctx context.Context, key string) *HookConfig { + if hookURL := p.getProvider(ctx).RequestURIF(key, nil); hookURL != nil { + return &HookConfig{ + URL: hookURL.String(), + } + } + + var hookConfig *HookConfig + if err := p.getProvider(ctx).Unmarshal(key, &hookConfig); err != nil { + p.l.WithError(errors.WithStack(err)). + Errorf("Configuration value from key %s could not be decoded.", key) + return nil + } + if hookConfig == nil { + return nil + } + + // validate URL by parsing it + u, err := url.ParseRequestURI(hookConfig.URL) + if err != nil { + p.l.WithError(errors.WithStack(err)). + Errorf("Configuration value from key %s could not be decoded.", key) + return nil + } + hookConfig.URL = u.String() + + return hookConfig +} + +func (p *DefaultProvider) TokenHookConfig(ctx context.Context) *HookConfig { + return p.getHookConfig(ctx, KeyTokenHook) } -func (p *DefaultProvider) TokenRefreshHookURL(ctx context.Context) *url.URL { - return p.getProvider(ctx).RequestURIF(KeyRefreshTokenHookURL, nil) +func (p *DefaultProvider) TokenRefreshHookConfig(ctx context.Context) *HookConfig { + return p.getHookConfig(ctx, KeyRefreshTokenHook) } func (p *DefaultProvider) DbIgnoreUnknownTableColumns() bool { diff --git a/driver/config/provider_test.go b/driver/config/provider_test.go index b4b42c33dd3..1b175aa919b 100644 --- a/driver/config/provider_test.go +++ b/driver/config/provider_test.go @@ -5,10 +5,10 @@ package config import ( "context" + "encoding/json" "fmt" "io" "net/http" - "net/url" "os" "strings" "testing" @@ -425,17 +425,37 @@ func TestCookieSecure(t *testing.T) { assert.True(t, c.CookieSecure(ctx)) } -func TestTokenRefreshHookURL(t *testing.T) { +func TestHookConfigs(t *testing.T) { ctx := context.Background() l := logrusx.New("", "") l.Logrus().SetOutput(io.Discard) c := MustNew(context.Background(), l, configx.SkipValidation()) - assert.EqualValues(t, (*url.URL)(nil), c.TokenRefreshHookURL(ctx)) - c.MustSet(ctx, KeyRefreshTokenHookURL, "") - assert.EqualValues(t, (*url.URL)(nil), c.TokenRefreshHookURL(ctx)) - c.MustSet(ctx, KeyRefreshTokenHookURL, "http://localhost:8080/oauth/token_refresh") - assert.EqualValues(t, "http://localhost:8080/oauth/token_refresh", c.TokenRefreshHookURL(ctx).String()) + for key, getFunc := range map[string]func(context.Context) *HookConfig{ + KeyRefreshTokenHook: c.TokenRefreshHookConfig, + KeyTokenHook: c.TokenHookConfig, + } { + assert.Nil(t, getFunc(ctx)) + c.MustSet(ctx, key, "") + assert.Nil(t, getFunc(ctx)) + c.MustSet(ctx, key, "http://localhost:8080/hook") + hc := getFunc(ctx) + require.NotNil(t, hc) + assert.EqualValues(t, "http://localhost:8080/hook", hc.URL) + + c.MustSet(ctx, key, map[string]any{ + "url": "http://localhost:8080/hook2", + "auth": map[string]any{ + "type": "api_key", + "config": json.RawMessage(`{"in":"header","name":"my-header","value":"my-value"}`), + }, + }) + hc = getFunc(ctx) + require.NotNil(t, hc) + assert.EqualValues(t, "http://localhost:8080/hook2", hc.URL) + assert.EqualValues(t, "api_key", hc.Auth.Type) + assert.JSONEq(t, `{"in":"header","name":"my-header","value":"my-value"}`, string(hc.Auth.Config)) + } } func TestJWTBearer(t *testing.T) { diff --git a/go.sum b/go.sum index 8240f627bd6..166bbf5a98c 100644 --- a/go.sum +++ b/go.sum @@ -62,7 +62,6 @@ github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WV github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -84,11 +83,9 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -97,12 +94,9 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.3.5 h1:Khtm8K6fTTz/ZCWPzU9Ne3aOW9VyAnj4qIPCJgKtwK0= github.com/cockroachdb/cockroach-go/v2 v2.3.5/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -110,7 +104,6 @@ github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdB github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/cristalhq/jwt/v4 v4.0.2 h1:g/AD3h0VicDamtlM70GWGElp8kssQEv+5wYd7L9WOhU= github.com/cristalhq/jwt/v4 v4.0.2/go.mod h1:HnYraSNKDRag1DZP92rYHyrjyQHnVEHPNqesmzs+miQ= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE= github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -163,7 +156,6 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-faker/faker/v4 v4.1.1 h1:zkxj/JH/aezB4R6cTEMKU7qcVScGhlB3qRtF3D7K+rI= github.com/go-faker/faker/v4 v4.1.1/go.mod h1:uuNc0PSRxF8nMgjGrrrU4Nw5cF30Jc6Kd0/FUTTYbhg= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -173,7 +165,6 @@ github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyM github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -221,11 +212,8 @@ github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= @@ -295,7 +283,6 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54= github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -454,8 +441,6 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= @@ -464,8 +449,6 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= @@ -504,7 +487,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/laher/mergefs v0.1.1 h1:nV2bTS57vrmbMxeR6uvJpI8LyGl3QHj4bLBZO3aUV58= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -549,7 +531,6 @@ github.com/mikefarah/yq/v4 v4.34.2/go.mod h1:EsGfyWg6sNpnva274ASzb54TJrCBAOKsBgJ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -557,17 +538,12 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nyaruka/phonenumbers v1.1.7 h1:5UUI9hE79Kk0dymSquXbMYB7IlNDNhvu2aNlJpm9et8= github.com/nyaruka/phonenumbers v1.1.7/go.mod h1:DC7jZd321FqUe+qWSNcHi10tyIyGNXGcNbfkPvdp1Vs= @@ -581,9 +557,6 @@ github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYB github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.8 h1:zICRlc+C1XzivLc3nzE+cbJV4LIi8tib6YG0MqC6OqA= github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A= github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM= github.com/ory/analytics-go/v5 v5.0.1 h1:LX8T5B9FN8KZXOtxgN+R3I4THRRVB6+28IKgKBpXmAM= @@ -635,7 +608,6 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -652,7 +624,6 @@ github.com/sawadashota/encrypta v0.0.3 h1:NWo2S6oBzZmD/tlm6iH1eYLZA99NsFPvc33Mhk github.com/sawadashota/encrypta v0.0.3/go.mod h1:W3Nja83iH22fOS8sGgKCf4rCehZqLrca1+oQbtFUFck= github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 h1:0b8DF5kR0PhRoRXDiEEdzrgBc8UqVY4JWLkQJCRsLME= github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761/go.mod h1:/THDZYi7F/BsVEcYzYPqdcWFQ+1C2InkawTKfLOAnzg= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/segmentio/analytics-go v3.1.0+incompatible/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48= github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4= @@ -666,14 +637,12 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= @@ -712,7 +681,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -732,11 +700,8 @@ github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9r github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= @@ -1227,8 +1192,6 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.3.5/go.mod h1:EGCWefLFQSVFrHGy4J8EtiHCWX5Q8t0yz2Jt9aKkGzU= -gorm.io/gorm v1.23.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/httpclient/model_token_pagination_response_headers.go b/internal/httpclient/model_token_pagination_response_headers.go index 26722925de6..ffa20eb2ef4 100644 --- a/internal/httpclient/model_token_pagination_response_headers.go +++ b/internal/httpclient/model_token_pagination_response_headers.go @@ -17,9 +17,9 @@ import ( // TokenPaginationResponseHeaders The `Link` HTTP header contains multiple links (`first`, `next`, `last`, `previous`) formatted as: `; rel=\"{page}\"` For details on pagination please head over to the [pagination documentation](https://www.ory.sh/docs/ecosystem/api-design#pagination). type TokenPaginationResponseHeaders struct { - // The Link HTTP Header The `Link` header contains a comma-delimited list of links to the following pages: first: The first page of results. next: The next page of results. prev: The previous page of results. last: The last page of results. Pages are omitted if they do not exist. For example, if there is no next page, the `next` link is omitted. Examples: ; rel=\"first\",; rel=\"next\",; rel=\"prev\",; rel=\"last\" + // The Link HTTP Headers The `Link` header contains a comma-delimited list of links to the following pages: first: The first page of results. next: The next page of results. prev: The previous page of results. last: The last page of results. Pages are omitted if they do not exist. For example, if there is no next page, the `next` link is omitted. Examples: ; rel=\"first\",; rel=\"next\",; rel=\"prev\",; rel=\"last\" Link *string `json:"link,omitempty"` - // The X-Total-Count HTTP Header The `X-Total-Count` header contains the total number of items in the collection. + // The X-Total-Count HTTP Headers The `X-Total-Count` header contains the total number of items in the collection. XTotalCount *int64 `json:"x-total-count,omitempty"` } diff --git a/oauth2/oauth2_auth_code_bench_test.go b/oauth2/oauth2_auth_code_bench_test.go index 3afab2eb0b2..254b9cce8f9 100644 --- a/oauth2/oauth2_auth_code_bench_test.go +++ b/oauth2/oauth2_auth_code_bench_test.go @@ -82,7 +82,7 @@ func BenchmarkAuthCode(b *testing.B) { reg := internal.NewRegistrySQLFromURL(b, dsn, true, new(contextx.Default)).WithTracer(tracer) reg.Config().MustSet(ctx, config.KeyLogLevel, "error") reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, "opaque") - reg.Config().MustSet(ctx, config.KeyRefreshTokenHookURL, "") + reg.Config().MustSet(ctx, config.KeyRefreshTokenHook, "") oauth2Keys, err := jwk.GenerateJWK(ctx, jose.ES256, x.OAuth2JWTKeyName, "sig") require.NoError(b, err) oidcKeys, err := jwk.GenerateJWK(ctx, jose.ES256, x.OpenIDConnectKeyName, "sig") diff --git a/oauth2/oauth2_auth_code_test.go b/oauth2/oauth2_auth_code_test.go index b2bf4897295..bcc7f3ccc66 100644 --- a/oauth2/oauth2_auth_code_test.go +++ b/oauth2/oauth2_auth_code_test.go @@ -79,7 +79,7 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { ctx := context.Background() reg := internal.NewMockedRegistry(t, &contextx.Default{}) reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, "opaque") - reg.Config().MustSet(ctx, config.KeyRefreshTokenHookURL, "") + reg.Config().MustSet(ctx, config.KeyRefreshTokenHook, "") publicTS, adminTS := testhelpers.NewOAuth2Server(ctx, t, reg) publicClient := hydra.NewAPIClient(hydra.NewConfiguration()) @@ -955,6 +955,7 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { return func(t *testing.T) { hs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, r.Header.Get("Content-Type"), "application/json; charset=UTF-8") + assert.Equal(t, r.Header.Get("Authorization"), "Bearer secret value") var hookReq hydraoauth2.TokenHookRequest require.NoError(t, json.NewDecoder(r.Body).Decode(&hookReq)) @@ -981,9 +982,15 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, &config.HookConfig{ + URL: hs.URL, + Auth: &config.Auth{ + Type: "api_key", + Config: json.RawMessage(`{"in": "header", "name": "Authorization", "value": "Bearer secret value"}`), + }, + }) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) expectAud := "https://api.ory.sh/" c, conf := newOAuth2Client(t, reg, testhelpers.NewCallbackURL(t, "callback", testhelpers.HTTPServerNotImplementedHandler)) @@ -1030,9 +1037,9 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) expectAud := "https://api.ory.sh/" c, conf := newOAuth2Client(t, reg, testhelpers.NewCallbackURL(t, "callback", testhelpers.HTTPServerNotImplementedHandler)) @@ -1070,9 +1077,9 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) expectAud := "https://api.ory.sh/" c, conf := newOAuth2Client(t, reg, testhelpers.NewCallbackURL(t, "callback", testhelpers.HTTPServerNotImplementedHandler)) @@ -1110,9 +1117,9 @@ func TestAuthCodeWithDefaultStrategy(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) expectAud := "https://api.ory.sh/" c, conf := newOAuth2Client(t, reg, testhelpers.NewCallbackURL(t, "callback", testhelpers.HTTPServerNotImplementedHandler)) @@ -1657,11 +1664,11 @@ func TestAuthCodeWithMockStrategy(t *testing.T) { defer hs.Close() if hookType == "legacy" { - conf.MustSet(ctx, config.KeyRefreshTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyRefreshTokenHookURL, nil) + conf.MustSet(ctx, config.KeyRefreshTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyRefreshTokenHook, nil) } else { - conf.MustSet(ctx, config.KeyTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyTokenHookURL, nil) + conf.MustSet(ctx, config.KeyTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyTokenHook, nil) } res, err := testRefresh(t, &refreshedToken, ts.URL, false) @@ -1699,11 +1706,11 @@ func TestAuthCodeWithMockStrategy(t *testing.T) { defer hs.Close() if hookType == "legacy" { - conf.MustSet(ctx, config.KeyRefreshTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyRefreshTokenHookURL, nil) + conf.MustSet(ctx, config.KeyRefreshTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyRefreshTokenHook, nil) } else { - conf.MustSet(ctx, config.KeyTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyTokenHookURL, nil) + conf.MustSet(ctx, config.KeyTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyTokenHook, nil) } origAccessTokenClaims := testhelpers.IntrospectToken(t, oauthConfig, refreshedToken.AccessToken, ts) @@ -1734,11 +1741,11 @@ func TestAuthCodeWithMockStrategy(t *testing.T) { defer hs.Close() if hookType == "legacy" { - conf.MustSet(ctx, config.KeyRefreshTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyRefreshTokenHookURL, nil) + conf.MustSet(ctx, config.KeyRefreshTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyRefreshTokenHook, nil) } else { - conf.MustSet(ctx, config.KeyTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyTokenHookURL, nil) + conf.MustSet(ctx, config.KeyTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyTokenHook, nil) } res, err := testRefresh(t, &refreshedToken, ts.URL, false) @@ -1764,11 +1771,11 @@ func TestAuthCodeWithMockStrategy(t *testing.T) { defer hs.Close() if hookType == "legacy" { - conf.MustSet(ctx, config.KeyRefreshTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyRefreshTokenHookURL, nil) + conf.MustSet(ctx, config.KeyRefreshTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyRefreshTokenHook, nil) } else { - conf.MustSet(ctx, config.KeyTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyTokenHookURL, nil) + conf.MustSet(ctx, config.KeyTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyTokenHook, nil) } res, err := testRefresh(t, &refreshedToken, ts.URL, false) @@ -1794,11 +1801,11 @@ func TestAuthCodeWithMockStrategy(t *testing.T) { defer hs.Close() if hookType == "legacy" { - conf.MustSet(ctx, config.KeyRefreshTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyRefreshTokenHookURL, nil) + conf.MustSet(ctx, config.KeyRefreshTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyRefreshTokenHook, nil) } else { - conf.MustSet(ctx, config.KeyTokenHookURL, hs.URL) - defer conf.MustSet(ctx, config.KeyTokenHookURL, nil) + conf.MustSet(ctx, config.KeyTokenHook, hs.URL) + defer conf.MustSet(ctx, config.KeyTokenHook, nil) } res, err := testRefresh(t, &refreshedToken, ts.URL, false) diff --git a/oauth2/oauth2_client_credentials_test.go b/oauth2/oauth2_client_credentials_test.go index 43f96cbaf68..34b260dc2b6 100644 --- a/oauth2/oauth2_client_credentials_test.go +++ b/oauth2/oauth2_client_credentials_test.go @@ -256,6 +256,7 @@ func TestClientCredentials(t *testing.T) { hs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, r.Header.Get("Content-Type"), "application/json; charset=UTF-8") + assert.Equal(t, r.Header.Get("Authorization"), "Bearer secret value") expectedGrantedScopes := []string{"foobar"} expectedGrantedAudience := []string{"https://api.ory.sh/"} @@ -286,9 +287,15 @@ func TestClientCredentials(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, &config.HookConfig{ + URL: hs.URL, + Auth: &config.Auth{ + Type: "api_key", + Config: json.RawMessage(`{"in": "header", "name": "Authorization", "value": "Bearer secret value"}`), + }, + }) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) secret := uuid.New().String() cl, conf := newCustomClient(t, &hc.Client{ @@ -316,9 +323,9 @@ func TestClientCredentials(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) _, conf := newClient(t) @@ -340,9 +347,9 @@ func TestClientCredentials(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) _, conf := newClient(t) @@ -364,9 +371,9 @@ func TestClientCredentials(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) _, conf := newClient(t) diff --git a/oauth2/oauth2_jwt_bearer_test.go b/oauth2/oauth2_jwt_bearer_test.go index 2053fe0f307..3931b72ac2b 100644 --- a/oauth2/oauth2_jwt_bearer_test.go +++ b/oauth2/oauth2_jwt_bearer_test.go @@ -354,9 +354,9 @@ func TestJWTBearer(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) conf := newConf(client) conf.EndpointParams = url.Values{"grant_type": {grantType}, "assertion": {token}} @@ -429,9 +429,9 @@ func TestJWTBearer(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) conf := newConf(client) conf.AuthStyle = goauth2.AuthStyleInParams @@ -457,9 +457,9 @@ func TestJWTBearer(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) token, _, err := signer.Generate(ctx, jwt.MapClaims{ "jti": uuid.NewString(), @@ -492,9 +492,9 @@ func TestJWTBearer(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) token, _, err := signer.Generate(ctx, jwt.MapClaims{ "jti": uuid.NewString(), @@ -527,9 +527,9 @@ func TestJWTBearer(t *testing.T) { defer hs.Close() reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, strategy) - reg.Config().MustSet(ctx, config.KeyTokenHookURL, hs.URL) + reg.Config().MustSet(ctx, config.KeyTokenHook, hs.URL) - defer reg.Config().MustSet(ctx, config.KeyTokenHookURL, nil) + defer reg.Config().MustSet(ctx, config.KeyTokenHook, nil) token, _, err := signer.Generate(ctx, jwt.MapClaims{ "jti": uuid.NewString(), diff --git a/oauth2/refresh_hook.go b/oauth2/refresh_hook.go index 62997a2f0f5..c1087655d71 100644 --- a/oauth2/refresh_hook.go +++ b/oauth2/refresh_hook.go @@ -52,8 +52,8 @@ func RefreshTokenHook(reg interface { x.HTTPClientProvider }) AccessRequestHook { return func(ctx context.Context, requester fosite.AccessRequester) error { - hookURL := reg.Config().TokenRefreshHookURL(ctx) - if hookURL == nil { + hookConfig := reg.Config().TokenRefreshHookConfig(ctx) + if hookConfig == nil { return nil } @@ -92,7 +92,7 @@ func RefreshTokenHook(reg interface { ) } - err = executeHookAndUpdateSession(ctx, reg, hookURL, reqBodyBytes, session) + err = executeHookAndUpdateSession(ctx, reg, hookConfig, reqBodyBytes, session) if err != nil { return err } diff --git a/oauth2/token_hook.go b/oauth2/token_hook.go index fc33fe3813d..377d15d0004 100644 --- a/oauth2/token_hook.go +++ b/oauth2/token_hook.go @@ -8,7 +8,8 @@ import ( "context" "encoding/json" "net/http" - "net/url" + + "github.com/pkg/errors" "github.com/hashicorp/go-retryablehttp" @@ -57,8 +58,42 @@ type TokenHookResponse struct { Session flow.AcceptOAuth2ConsentRequestSession `json:"session"` } -func executeHookAndUpdateSession(ctx context.Context, reg x.HTTPClientProvider, hookURL *url.URL, reqBodyBytes []byte, session *Session) error { - req, err := retryablehttp.NewRequestWithContext(ctx, http.MethodPost, hookURL.String(), bytes.NewReader(reqBodyBytes)) +type APIKeyAuthConfig struct { + In string `json:"in"` + Name string `json:"name"` + Value string `json:"value"` +} + +func applyAuth(req *retryablehttp.Request, auth *config.Auth) error { + if auth == nil { + return nil + } + + switch auth.Type { + case "api_key": + c := struct { + In string `json:"in"` + Name string `json:"name"` + Value string `json:"value"` + }{} + if err := json.Unmarshal(auth.Config, &c); err != nil { + return err + } + + switch c.In { + case "header": + req.Header.Set(c.Name, c.Value) + case "cookie": + req.AddCookie(&http.Cookie{Name: c.Name, Value: c.Value}) + } + default: + return errors.Errorf("unsupported auth type %q", auth.Type) + } + return nil +} + +func executeHookAndUpdateSession(ctx context.Context, reg x.HTTPClientProvider, hookConfig *config.HookConfig, reqBodyBytes []byte, session *Session) error { + req, err := retryablehttp.NewRequestWithContext(ctx, http.MethodPost, hookConfig.URL, bytes.NewReader(reqBodyBytes)) if err != nil { return errorsx.WithStack( fosite.ErrServerError. @@ -67,6 +102,13 @@ func executeHookAndUpdateSession(ctx context.Context, reg x.HTTPClientProvider, WithDebugf("Unable to prepare the HTTP Request: %s", err), ) } + if err := applyAuth(req, hookConfig.Auth); err != nil { + return errorsx.WithStack( + fosite.ErrServerError. + WithWrap(err). + WithDescription("An error occurred while applying the token hook authentication."). + WithDebugf("Unable to apply the token hook authentication: %s", err)) + } req.Header.Set("Content-Type", "application/json; charset=UTF-8") resp, err := reg.HTTPClient(ctx).Do(req) @@ -123,8 +165,8 @@ func TokenHook(reg interface { x.HTTPClientProvider }) AccessRequestHook { return func(ctx context.Context, requester fosite.AccessRequester) error { - hookURL := reg.Config().TokenHookURL(ctx) - if hookURL == nil { + hookConfig := reg.Config().TokenHookConfig(ctx) + if hookConfig == nil { return nil } @@ -156,7 +198,7 @@ func TokenHook(reg interface { ) } - err = executeHookAndUpdateSession(ctx, reg, hookURL, reqBodyBytes, session) + err = executeHookAndUpdateSession(ctx, reg, hookConfig, reqBodyBytes, session) if err != nil { return err } diff --git a/spec/config.json b/spec/config.json index 571758939a2..fd989886bec 100644 --- a/spec/config.json +++ b/spec/config.json @@ -248,6 +248,47 @@ } } } + }, + "webhook_config": { + "type": "object", + "additionalProperties": false, + "description": "Configures a webhook.", + "required": ["url"], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The URL to send the webhook to." + }, + "auth": { + "type": "object", + "additionalProperties": false, + "required": ["type", "config"], + "properties": { + "type": { + "const": "api_key" + }, + "config": { + "type": "object", + "additionalProperties": false, + "required": ["name", "value"], + "properties": { + "in": { + "enum": ["header", "cookie"] + }, + "name": { + "description": "The header or cookie name.", + "type": "string" + }, + "value": { + "description": "The header or cookie value.", + "type": "string" + } + } + } + } + } + } } }, "properties": { @@ -1039,16 +1080,30 @@ } }, "refresh_token_hook": { - "type": "string", "description": "Sets the refresh token hook endpoint. If set it will be called during token refresh to receive updated token claims.", - "format": "uri", - "examples": ["https://my-example.app/token-refresh-hook"] + "examples": ["https://my-example.app/token-refresh-hook"], + "oneOf": [ + { + "type": "string", + "format": "uri" + }, + { + "$ref": "#/definitions/webhook_config" + } + ] }, "token_hook": { - "type": "string", "description": "Sets the token hook endpoint for all grant types. If set it will be called while providing token to customize claims.", - "format": "uri", - "examples": ["https://my-example.app/token-hook"] + "examples": ["https://my-example.app/token-hook"], + "oneOf": [ + { + "type": "string", + "format": "uri" + }, + { + "$ref": "#/definitions/webhook_config" + } + ] } } },