revisions

This commit is contained in:
Samir Patel 2022-01-03 22:56:21 -06:00
parent a7fada30dd
commit 414dff1d22
4 changed files with 40 additions and 78 deletions

View file

@ -6,7 +6,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"time"
@ -114,23 +114,24 @@ func (a *Auth) Login(w http.ResponseWriter, r *http.Request) {
}
func (a *Auth) Logout(w http.ResponseWriter, r *http.Request) {
newCookie := a.getEmptyCookie()
http.SetCookie(w, newCookie)
http.SetCookie(w, a.getEmptyCookie())
redirect := fmt.Sprintf("%s?post_logout_redirect_uri=%s/", a.logoutEndpoint, a.fbURL)
http.Redirect(w, r, redirect, http.StatusTemporaryRedirect)
}
// Gets user information from dP and sets a secure cookie
// Gets user information from IdP and sets a secure cookie
func (a *Auth) Redirect(w http.ResponseWriter, r *http.Request) {
code := r.FormValue("code")
token, err := a.getToken(code)
token, err := a.getToken(r, code)
if err != nil {
a.logger.Warnf("getting token from IdP: %+v", err)
http.Error(w, "Bad Request: 400", http.StatusBadRequest)
return
}
cv, err := a.newCookieValue(token)
if err != nil || cv == nil {
a.logger.Warnf("creating cookie: %+v", err)
http.Error(w, "Bad Request: 400", http.StatusBadRequest)
return
}
@ -143,17 +144,18 @@ func (a *Auth) GetUserInfo(w http.ResponseWriter, r *http.Request) *UserInfo {
var resp UserInfo
cookie, err := a.readCookie(w, r)
if err != nil {
//add logging
a.logger.Warnf("was not able to read cookie for req: %+v", r)
return &resp
}
resp.UserID = cookie.UserID
resp.UserName = cookie.UserName
return &resp
return &UserInfo{
UserID: cookie.UserID,
UserName: cookie.UserName,
}
}
func (a *Auth) getToken(code string) (*oauth2.Token, error) {
token, err := a.oAuthConfig.Exchange(context.Background(), code)
func (a *Auth) getToken(r *http.Request, code string) (*oauth2.Token, error) {
token, err := a.oAuthConfig.Exchange(r.Context(), code)
if err != nil {
return nil, errors.Wrap(err, "exchanging auth code for token")
}
@ -189,21 +191,20 @@ func (a *Auth) newCookieValue(token *oauth2.Token) (*CookieValue, error) {
func (a *Auth) getGroupMembership(token *oauth2.Token) (Groups, error) {
var groups Groups
var bearer = fmt.Sprintf("Bearer %s", token.AccessToken)
req, err := http.NewRequest("GET", a.groupEndpoint, nil)
if err != nil {
return groups, errors.Wrap(err, "creating new request to group endpoint")
}
req.Header.Add("Authorization", bearer)
client := &http.Client{}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))
client := http.DefaultClient
response, err := client.Do(req)
if err != nil {
return groups, errors.Wrap(err, "getting group membership info")
}
defer response.Body.Close()
rawGroups, err := ioutil.ReadAll(response.Body)
rawGroups, err := io.ReadAll(response.Body)
if err != nil {
return groups, errors.Wrap(err, "failed reading group membership response")
}
@ -224,8 +225,7 @@ func (a *Auth) readCookie(w http.ResponseWriter, r *http.Request) (*CookieValue,
var value CookieValue
err = a.secure.Decode(a.cookieName, cookie.Value, &value)
if err != nil {
newCookie := a.getEmptyCookie()
http.SetCookie(w, newCookie)
http.SetCookie(w, a.getEmptyCookie())
return nil, errors.Wrap(err, "decoding cookie")
}
@ -238,7 +238,7 @@ func (a *Auth) setCookie(w http.ResponseWriter, cookie *CookieValue) error {
return errors.Wrap(err, "encoding CookieValue")
}
newCookie := &http.Cookie{
http.SetCookie(w, &http.Cookie{
Name: a.cookieName,
Value: encoded,
Path: "/",
@ -246,8 +246,7 @@ func (a *Auth) setCookie(w http.ResponseWriter, cookie *CookieValue) error {
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: cookie.Token.Expiry,
}
http.SetCookie(w, newCookie)
})
return nil
}
@ -264,7 +263,7 @@ func (a *Auth) refreshToken(w http.ResponseWriter, cookie *CookieValue) error {
if newToken.Expiry != cookie.Token.Expiry {
cv, err := a.newCookieValue(newToken)
if err != nil {
errors.Wrap(err, "setting cookie")
return errors.Wrap(err, "setting cookie")
}
a.setCookie(w, cv)

View file

@ -67,20 +67,20 @@ func TestAuth(t *testing.T) {
w := httptest.NewRecorder()
err := a.setCookie(w, &validCV)
if err != nil {
t.Errorf("expected no errors, got: %v", err)
t.Fatalf("expected no errors, got: %v", err)
}
if w.Result().Cookies()[0].Value == "" {
t.Errorf("expected some value, got: %+v", w.Result().Cookies()[0].Value)
t.Fatalf("expected some value, got: %+v", w.Result().Cookies()[0].Value)
}
if w.Result().Cookies()[0].Path != "/" {
t.Errorf("expected path to be /, got: %+v", w.Result().Cookies()[0].Path)
t.Fatalf("expected path to be /, got: %+v", w.Result().Cookies()[0].Path)
}
})
t.Run("GetEmptyCookie", func(t *testing.T) {
c := a.getEmptyCookie()
if c.Value != "" {
t.Errorf("expected empty cookie, got: %+v", c.Value)
t.Fatalf("expected empty cookie, got: %+v", c.Value)
}
})
t.Run("KeyLength", func(t *testing.T) {
@ -98,20 +98,20 @@ func TestAuth(t *testing.T) {
ShortKey,
)
if err == nil || !strings.Contains(err.Error(), "decoding block key") {
t.Errorf("expected error decoding block key got: %v", err)
t.Fatalf("expected error decoding block key got: %v", err)
}
})
t.Run("NewCookieValue-BadAccessToken", func(t *testing.T) {
_, err := a.newCookieValue(&tokenAT)
if err == nil || !strings.Contains(err.Error(), "jwt claims") {
t.Errorf("expected failure regarding jwt claims, got: %v", err)
t.Fatalf("expected failure regarding jwt claims, got: %v", err)
}
})
t.Run("CookieValue-NoAccessToken", func(t *testing.T) {
_, err := a.newCookieValue(&tokenNoAT)
if err == nil || !strings.Contains(err.Error(), "access token") {
t.Errorf("expected failure regarding access token, got: %v", err)
t.Fatalf("expected failure regarding access token, got: %v", err)
}
})

View file

@ -38,7 +38,6 @@ import (
"github.com/molecula/featurebase/v2/rbf"
"github.com/molecula/featurebase/v2/topology"
"github.com/molecula/featurebase/v2/tracing"
"github.com/molecula/featurebase/v2/vprint"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus/promhttp"
dto "github.com/prometheus/client_model/go"
@ -541,15 +540,12 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (h *Handler) chkAuthN(handler http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if h.auth != nil {
_, err := h.auth.Authenticate(w, r)
if err != nil {
if _, err := h.auth.Authenticate(w, r); err != nil {
http.Error(w, errors.Wrap(err, "authenticating").Error(), http.StatusBadRequest)
return
}
} else {
handler.ServeHTTP(w, r)
}
handler.ServeHTTP(w, r)
}
}
@ -564,13 +560,12 @@ func (h *Handler) chkAuthZ(handler http.HandlerFunc, perm authz.Permission) http
}
if h.permissions == nil {
panic("authentication is turned on without authorization permissions set")
h.logger.Errorf("authentication is turned on without authorization permissions set")
http.Error(w, errors.New("authorizing").Error(), http.StatusInternalServerError)
}
uinfo := h.auth.GetUserInfo(w, r)
//get query string if applicable
var queryString string
queryRequest := r.Context().Value(contextKeyQueryRequest)
if req, ok := queryRequest.(*pilosa.QueryRequest); ok {
@ -596,7 +591,6 @@ func (h *Handler) chkAuthZ(handler http.HandlerFunc, perm authz.Permission) http
indexName, ok := mux.Vars(r)["index"]
if ok {
p, err := h.permissions.GetPermissions(groups, indexName)
vprint.VV("p: %+v,perm: %+v,indexName: %+v", p, lperm, indexName)
ctx = context.WithValue(r.Context(), contextKeyPermission, p)
if err != nil || !p.Satisfies(lperm) {
w.Header().Add("Content-Type", "text/plain")
@ -785,8 +779,7 @@ func (h *Handler) filterResponse(w http.ResponseWriter, r *http.Request, schema
if h.auth != nil {
g := r.Context().Value(contextKeyGroupMembership)
if g == nil {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusForbidden)
http.Error(w, "not authorized", http.StatusForbidden)
return nil
}
indexes := h.permissions.GetAuthorizedIndexList(g.([]authn.Group), authz.Read)
@ -971,10 +964,6 @@ func (h *Handler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
qerr := r.Context().Value(contextKeyQueryError)
req, ok := qreq.(*pilosa.QueryRequest)
// if !h.isAuthorized(w, r, req, req.Index, authz.Admin.String(), r.URL.Path) {
// return
// }
if DoPerQueryProfiling {
backend := pilosa.CurrentBackend()
reqHash := hash(req.Query)
@ -3514,9 +3503,7 @@ func (h *Handler) handlePostRestore(w http.ResponseWriter, r *http.Request) {
func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
if h.auth == nil {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusNoContent)
w.Write([]byte("Auth Off")) //nolint:errcheck
http.Error(w, "Auth Off", http.StatusNoContent)
return
}
@ -3539,9 +3526,7 @@ func (h *Handler) handleCheckAuthentication(w http.ResponseWriter, r *http.Reque
return
}
if h.auth == nil {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusNoContent)
w.Write([]byte("Auth Off")) //nolint:errcheck
http.Error(w, "Auth Off", http.StatusNoContent)
return
}
groups, err := h.auth.Authenticate(w, r)
@ -3562,9 +3547,7 @@ func (h *Handler) handleUserInfo(w http.ResponseWriter, r *http.Request) {
return
}
if h.auth == nil {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusNoContent)
w.Write([]byte("Auth Off")) //nolint:errcheck
http.Error(w, "Auth Off", http.StatusNoContent)
return
}
if err := json.NewEncoder(w).Encode(h.auth.GetUserInfo(w, r)); err != nil {
@ -3574,9 +3557,7 @@ func (h *Handler) handleUserInfo(w http.ResponseWriter, r *http.Request) {
func (h *Handler) handleLogout(w http.ResponseWriter, r *http.Request) {
if h.auth == nil {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusNoContent)
w.Write([]byte("Auth Off")) //nolint:errcheck
http.Error(w, "Auth Off", http.StatusNoContent)
return
}
h.auth.Logout(w, r)

View file

@ -312,29 +312,11 @@ func TestAuthentication(t *testing.T) {
Expires: token.Expiry,
}
// permissions1 := `"user-groups":
// "dca35310-ecda-4f23-86cd-876aee55906b":
// "test": "read"
// admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
permissions2 := `"user-groups":
permissions1 := `"user-groups":
"dca35310-ecda-4f23-86cd-876aee559900":
"test": "write"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
// permissions3 := `"user-groups":
// "dca35310-ecda-4f23-86cd-876aee55906b":
// "test": "write"
// "test2": "read"
// "dca35310-ecda-4f23-86cd-876aee559900":
// "test": "read"
// admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
// permissions4 := `"user-groups":
// "dca35310-ecda-4f23-86cd-876aee559900":
// "test": ""
// admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
tests := []struct {
name string
path string
@ -631,7 +613,7 @@ admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
cookie: validCookie,
handler: func(w gohttp.ResponseWriter, r *gohttp.Request) {
h := h
permFile := strings.NewReader(permissions2)
permFile := strings.NewReader(permissions1)
var p authz.GroupPermissions
if err := p.ReadPermissionsFile(permFile); err != nil {
t.Errorf("Error: %s", err)
@ -641,8 +623,8 @@ admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
f(w, r)
},
fn: func(w *httptest.ResponseRecorder, data []byte) {
if w.Result().StatusCode != 403 {
t.Errorf("expected http code 403, got: %+v", w.Result().StatusCode)
if w.Result().StatusCode != 400 {
t.Errorf("expected http code 400, got: %+v", w.Result().StatusCode)
}
},