diff --git a/docs/README.md b/docs/README.md index ff6204b5c..7c9191999 100644 --- a/docs/README.md +++ b/docs/README.md @@ -666,7 +666,9 @@ The CORS block configures the CORS (Cross-Origin Resource Sharing) behavior in C | `token_endpoint` | | | `client_id` | | | `client_secret` | | -| `retries` | | +| `retries` | | +| `token_endpoint_auth_method` | | +| `scope` | | ### Modifier diff --git a/server/http_oauth2_test.go b/server/http_oauth2_test.go index d54ae9b0f..cf73f178b 100644 --- a/server/http_oauth2_test.go +++ b/server/http_oauth2_test.go @@ -21,29 +21,6 @@ func TestEndpoints_OAuth2(t *testing.T) { oauthOrigin := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/oauth2" { - reqBody, _ := ioutil.ReadAll(req.Body) - authorization := req.Header.Get("Authorization") - - if i == 0 { - exp := `client_id=user&client_secret=pass+word&grant_type=client_credentials&scope=scope1+scope2` - if exp != string(reqBody) { - t.Errorf("want\n%s\ngot\n%s", exp, reqBody) - } - exp = "" - if exp != authorization { - t.Errorf("want\n%s\ngot\n%s", exp, authorization) - } - } else { - exp := `grant_type=client_credentials` - if exp != string(reqBody) { - t.Errorf("want\n%s\ngot\n%s", exp, reqBody) - } - exp = "Basic dXNlcjpwYXNz" - if exp != authorization { - t.Errorf("want\n%s\ngot\n%s", exp, authorization) - } - } - rw.Header().Set("Content-Type", "application/json") rw.WriteHeader(http.StatusOK) @@ -131,3 +108,88 @@ func TestEndpoints_OAuth2(t *testing.T) { shutdown() } } + +func TestEndpoints_OAuth2_Options(t *testing.T) { + helper := test.New(t) + + type testCase struct { + configFile string + expBody string + expAuth string + } + + for _, tc := range []testCase{ + { + "01_couper.hcl", + `client_id=user&client_secret=pass+word&grant_type=client_credentials&scope=scope1+scope2`, + "", + }, + { + "02_couper.hcl", + `grant_type=client_credentials`, + "Basic dXNlcjpwYXNz", + }, + { + "03_couper.hcl", + `grant_type=client_credentials`, + "Basic dXNlcjpwYXNz", + }, + } { + var tokenSeenCh chan struct{} + + oauthOrigin := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.URL.Path == "/options" { + reqBody, _ := ioutil.ReadAll(req.Body) + authorization := req.Header.Get("Authorization") + + if tc.expBody != string(reqBody) { + t.Errorf("want\n%s\ngot\n%s", tc.expBody, reqBody) + } + if tc.expAuth != authorization { + t.Errorf("want\n%s\ngot\n%s", tc.expAuth, authorization) + } + + rw.WriteHeader(http.StatusNoContent) + + close(tokenSeenCh) + return + } + rw.WriteHeader(http.StatusBadRequest) + })) + defer oauthOrigin.Close() + + confPath := fmt.Sprintf("testdata/oauth2/%s", tc.configFile) + shutdown, hook := newCouper(confPath, test.New(t)) + defer func() { + if t.Failed() { + for _, e := range hook.Entries { + println(e.String()) + } + } + shutdown() + }() + + req, err := http.NewRequest(http.MethodGet, "http://anyserver:8080/", nil) + helper.Must(err) + + req.Header.Set("X-Token-Endpoint", oauthOrigin.URL) + + hook.Reset() + + tokenSeenCh = make(chan struct{}) + + req.URL.Path = "/" + _, err = newClient().Do(req) + helper.Must(err) + + timer := time.NewTimer(time.Second * 2) + select { + case <-timer.C: + t.Error("OAuth2 request failed") + case <-tokenSeenCh: + } + + oauthOrigin.Close() + shutdown() + } +} diff --git a/server/testdata/oauth2/01_couper.hcl b/server/testdata/oauth2/01_couper.hcl new file mode 100644 index 000000000..7bc2d4e69 --- /dev/null +++ b/server/testdata/oauth2/01_couper.hcl @@ -0,0 +1,25 @@ +server "oauth2-options" { + error_file = "./../integration/server_error.html" + + api { + error_file = "./../integration/api_error.json" + + endpoint "/" { + proxy { + backend { + url = "https://example.com/" + + oauth2 { + token_endpoint = "${request.headers.x-token-endpoint}/options" + retries = 0 + client_id = "user" + client_secret = "pass word" + grant_type = "client_credentials" + scope = "scope1 scope2" + token_endpoint_auth_method = "client_secret_post" + } + } + } + } + } +} diff --git a/server/testdata/oauth2/02_couper.hcl b/server/testdata/oauth2/02_couper.hcl new file mode 100644 index 000000000..1f4cbcc24 --- /dev/null +++ b/server/testdata/oauth2/02_couper.hcl @@ -0,0 +1,24 @@ +server "oauth2-options" { + error_file = "./../integration/server_error.html" + + api { + error_file = "./../integration/api_error.json" + + endpoint "/" { + proxy { + backend { + url = "https://example.com/" + + oauth2 { + token_endpoint = "${request.headers.x-token-endpoint}/options" + retries = 0 + client_id = "user" + client_secret = "pass" + grant_type = "client_credentials" + token_endpoint_auth_method = "client_secret_basic" + } + } + } + } + } +} diff --git a/server/testdata/oauth2/03_couper.hcl b/server/testdata/oauth2/03_couper.hcl new file mode 100644 index 000000000..6d31920d8 --- /dev/null +++ b/server/testdata/oauth2/03_couper.hcl @@ -0,0 +1,23 @@ +server "oauth2-options" { + error_file = "./../integration/server_error.html" + + api { + error_file = "./../integration/api_error.json" + + endpoint "/" { + proxy { + backend { + url = "https://example.com/" + + oauth2 { + token_endpoint = "${request.headers.x-token-endpoint}/options" + retries = 0 + client_id = "user" + client_secret = "pass" + grant_type = "client_credentials" + } + } + } + } + } +} diff --git a/server/testdata/oauth2/0_retries_couper.hcl b/server/testdata/oauth2/0_retries_couper.hcl index 9e8ec49e8..ee0df23a3 100644 --- a/server/testdata/oauth2/0_retries_couper.hcl +++ b/server/testdata/oauth2/0_retries_couper.hcl @@ -16,8 +16,6 @@ server "api" { client_secret = "pass word" grant_type = "client_credentials" retries = 0 - scope = "scope1 scope2" - token_endpoint_auth_method = "client_secret_post" } } } @@ -34,8 +32,6 @@ server "api" { client_secret = "pass word" grant_type = "client_credentials" retries = 0 - scope = "scope1 scope2" - token_endpoint_auth_method = "client_secret_post" backend { origin = "${request.headers.x-token-endpoint}" path = "/oauth2" diff --git a/server/testdata/oauth2/1_retries_couper.hcl b/server/testdata/oauth2/1_retries_couper.hcl index 630b96a06..1a229b100 100644 --- a/server/testdata/oauth2/1_retries_couper.hcl +++ b/server/testdata/oauth2/1_retries_couper.hcl @@ -15,7 +15,6 @@ server "api" { client_id = "user" client_secret = "pass" grant_type = "client_credentials" - token_endpoint_auth_method = "client_secret_basic" } } } @@ -31,7 +30,6 @@ server "api" { client_id = "user" client_secret = "pass" grant_type = "client_credentials" - token_endpoint_auth_method = "client_secret_basic" backend { origin = "${request.headers.x-token-endpoint}" path = "/oauth2"