diff options
| -rwxr-xr-x | bin/ui | 75 | ||||
| -rw-r--r-- | test/e2e_test.go | 17 |
2 files changed, 69 insertions, 23 deletions
@@ -69,18 +69,32 @@ module OAuth ].join("?") end - def exchange(grant_type:, code:, code_verifier: "not_implemented") + def exchange(grant_type, params = {}) with_http do |client| - client.post(self[:token_endpoint], body: { - grant_type: grant_type, - code: code, - code_verifier: code_verifier, - }) + client.post(self[:token_endpoint], body: body_for(grant_type, params)) end end private + def body_for(grant_type, params) + case grant_type + when "authorization_code" + { + grant_type: grant_type, + code: params.fetch(:code), + code_verifier: params.fetch(:code_verifier, "not_implemented"), + } + when "urn:ietf:params:oauth:grant-type:saml2-bearer" + { + grant_type: grant_type, + assertion: params.fetch(:assertion), + } + else + raise NotImplementedError.new(grant_type) + end + end + def to_query(params = {}) params.map do |(key, value)| [key, value].join("=") @@ -221,7 +235,7 @@ class UI end def oauth_callback(request) - response = oauth_client.exchange(grant_type: "authorization_code", code: request.params['code']) + response = oauth_client.exchange("authorization_code", code: request.params['code']) if response.code == "200" tokens = JSON.parse(response.body, symbolize_names: true) request.session[:access_token] = tokens[:access_token] @@ -379,21 +393,38 @@ class UI saml_response = saml_binding.deserialize(request.params) raise saml_response.errors unless saml_response.valid? - template = <<~ERB - <!doctype html> - <html> - <head> - <title></title> - </head> - <body style="background-color: pink;"> - <h2>Received SAML Response</h2> - <textarea readonly="readonly" disabled="disabled" cols=220 rows=40><%=- saml_response.to_xml(pretty: true) -%></textarea> - <pre id="saml-response"><%= request.params["SAMLResponse"] %></pre> - </body> - </html> - ERB - html = ERB.new(template, trim_mode: '-').result(binding) - [200, { 'Content-Type' => "text/html" }, [html]] + response = oauth_client.exchange( + "urn:ietf:params:oauth:grant-type:saml2-bearer", + assertion: request.params["SAMLResponse"], + ) + if response.code == "200" + tokens = JSON.parse(response.body, symbolize_names: true) + request.session[:access_token] = tokens[:access_token] + request.session[:id_token] = tokens[:id_token] + request.session[:refresh_token] = tokens[:access_token] + + template = <<~ERB + <!doctype html> + <html> + <head> + <title></title> + </head> + <body style="background-color: pink;"> + <h2>Received SAML Response</h2> + <textarea readonly="readonly" disabled="disabled" cols=220 rows=40><%=- saml_response.to_xml(pretty: true) -%></textarea> + <pre id="raw-saml-response"><%= request.params["SAMLResponse"] %></pre> + <pre id="access-token"><%= JSON.pretty_generate(request.session[:access_token]) %></pre> + + <a href="/index.html">Home</a> + <a href="/groups.html">Groups</a> + </body> + </html> + ERB + html = ERB.new(template, trim_mode: '-').result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + else + [response.code, response.header, [response.body]] + end end end diff --git a/test/e2e_test.go b/test/e2e_test.go index 19c09af7..218b395d 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -60,8 +60,23 @@ func TestAuthx(t *testing.T) { assert.NoError(t, page.Locator("#submit-button").Click()) assert.Contains(t, x.Must(page.Content()), "Received SAML Response") + t.Run("generates a usable access token", func(t *testing.T) { + rawToken := x.Must(page.Locator("#access-token").TextContent()) + accessToken := strings.Replace(rawToken, "\"", "", -1) + assert.NotEmpty(t, accessToken) + + t.Run("GET http://api.example.com:8080/projects.json", func(t *testing.T) { + request := x.Must(http.NewRequestWithContext(t.Context(), "GET", "http://api.example.com:8080/projects.json", nil)) + request.Header.Add("Authorization", "Bearer "+accessToken) + response := x.Must(client.Do(request)) + require.Equal(t, http.StatusOK, response.StatusCode) + projects := x.Must(serde.FromJSON[[]map[string]string](response.Body)) + assert.NotNil(t, projects) + }) + }) + t.Run("exchange SAML assertion for access token", func(t *testing.T) { - samlAssertion := x.Must(page.Locator("#saml-response").TextContent()) + samlAssertion := x.Must(page.Locator("#raw-saml-response").TextContent()) io := bytes.NewBuffer(nil) assert.NoError(t, serde.ToJSON(io, map[string]string{ "assertion": samlAssertion, |
