package controller import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "strings" "testing" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestAuthenticationHandler(t *testing.T) { c := NewTestController(t, &TestControllerOpts{ DisableAuthorizationFailures: true, DefaultAuthMethodId: "ampw_1234567890", DefaultLoginName: "admin", DefaultPassword: "password123", }) defer c.Shutdown() request := map[string]interface{}{ "credentials": map[string]interface{}{ "login_name": "admin", "password": "password123", }, } // No token_type defined means "token" type b, err := json.Marshal(request) require.NoError(t, err) resp, err := http.Post(fmt.Sprintf("%s/v1/auth-methods/ampw_1234567890:authenticate", c.ApiAddrs()[0]), "application/json", bytes.NewReader(b)) require.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode, "Got response: %v", resp) b, err = ioutil.ReadAll(resp.Body) require.NoError(t, err) body := make(map[string]interface{}) require.NoError(t, json.Unmarshal(b, &body)) require.Contains(t, body, "id") require.Contains(t, body, "token") pubId, tok := body["id"].(string), body["token"].(string) assert.NotEmpty(t, pubId) assert.NotEmpty(t, tok) assert.Truef(t, strings.HasPrefix(tok, pubId), "Token: %q, Id: %q", tok, pubId) // Set the token type to cookie and make sure the body does not contain the token anymore. request["token_type"] = "cookie" b, err = json.Marshal(request) resp, err = http.Post(fmt.Sprintf("%s/v1/auth-methods/ampw_1234567890:authenticate", c.ApiAddrs()[0]), "application/json", bytes.NewReader(b)) require.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode, "Got response: %v", resp) b, err = ioutil.ReadAll(resp.Body) require.NoError(t, err) body = make(map[string]interface{}) require.NoError(t, json.Unmarshal(b, &body)) require.Contains(t, body, "id") require.Contains(t, body, "auth_method_id") require.Contains(t, body, "user_id") require.NotContains(t, body, "token") cookies := make(map[string]*http.Cookie) for _, c := range resp.Cookies() { cookies[c.Name] = c } require.Contains(t, cookies, handlers.HttpOnlyCookieName) require.Contains(t, cookies, handlers.JsVisibleCookieName) assert.NotEmpty(t, cookies[handlers.HttpOnlyCookieName].Value) assert.NotEmpty(t, cookies[handlers.JsVisibleCookieName].Value) assert.True(t, cookies[handlers.HttpOnlyCookieName].HttpOnly) assert.False(t, cookies[handlers.JsVisibleCookieName].HttpOnly) tok = cookies[handlers.JsVisibleCookieName].Value pubId = body["id"].(string) assert.NotEmpty(t, pubId) assert.Truef(t, strings.HasPrefix(tok, pubId), "Token: %q, Id: %q", tok, pubId) } func TestHandleImplementedPaths(t *testing.T) { c := NewTestController(t, &TestControllerOpts{ DisableAuthorizationFailures: true, }) defer c.Shutdown() for verb, paths := range map[string][]string{ "GET": { "v1/sessions/", "v1/sessions/someid", "v1/scopes", "v1/scopes/someid", "v1/auth-tokens", "v1/auth-tokens/someid", "v1/auth-methods", "v1/auth-methods/someid", "v1/accounts", "v1/accounts/someid", "v1/groups", "v1/groups/someid", "v1/host-catalogs", "v1/host-catalogs/someid", "v1/host-sets", "v1/host-sets/someid", "v1/hosts", "v1/hosts/someid", "v1/roles", "v1/roles/someid", "v1/users", "v1/users/someid", "v1/targets", "v1/targets/someid", }, "POST": { // Creation end points "v1/scopes", "v1/groups", "v1/roles", "v1/users", "v1/auth-methods", "v1/accounts", "v1/host-catalogs", "v1/host-sets", "v1/hosts", "v1/targets", // custom methods "v1/sessions/someid:cancel", "v1/auth-methods/someid:authenticate", "v1/accounts/someid:set-password", "v1/accounts/someid:change-password", "v1/roles/someid:add-principals", "v1/roles/someid:set-principals", "v1/roles/someid:remove-principals", "v1/roles/someid:add-grants", "v1/roles/someid:set-grants", "v1/roles/someid:remove-grants", "v1/groups/someid:add-members", "v1/groups/someid:set-members", "v1/groups/someid:remove-members", }, "DELETE": { "v1/scopes/someid", "v1/users/someid", "v1/roles/someid", "v1/groups/someid", "v1/auth-tokens/someid", "v1/auth-methods/someid", "v1/accounts/someid", "v1/host-catalogs/someid", "v1/host-sets/someid", "v1/hosts/someid", "v1/targets/someid", }, "PATCH": { "v1/scopes/someid", "v1/users/someid", "v1/roles/someid", "v1/groups/someid", "v1/auth-methods/someid", "v1/host-catalogs/someid", "v1/host-sets/someid", "v1/hosts/someid", "v1/targets/someid", }, } { for _, p := range paths { t.Run(fmt.Sprintf("%s/%s", verb, p), func(t *testing.T) { url := fmt.Sprintf("%s/%s", c.ApiAddrs()[0], p) req, err := http.NewRequest(verb, url, nil) require.NoError(t, err) resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.NotEqualf(t, resp.StatusCode, http.StatusNotFound, "Got response %v, wanted not 404", resp.StatusCode) }) } } }