149 lines
3.8 KiB
Go
149 lines
3.8 KiB
Go
package http
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
request "github.com/golang-jwt/jwt/v4/request"
|
|
"github.com/keel-hq/keel/pkg/auth"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func authHeadersMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
|
|
rw.Header().Set("Access-Control-Allow-Headers",
|
|
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
|
|
|
rw.Header().Set("Access-Control-Expose-Headers", "Authorization")
|
|
rw.Header().Set("Access-Control-Request-Headers", "Authorization")
|
|
|
|
next(rw, r)
|
|
}
|
|
|
|
func (s *TriggerServer) requireAdminAuthorization(next http.HandlerFunc) http.HandlerFunc {
|
|
return func(rw http.ResponseWriter, r *http.Request) {
|
|
|
|
// rw.Header().Set("Access-Control-Expose-Headers", "Authorization")
|
|
// rw.Header().Set("Access-Control-Request-Headers", "Authorization")
|
|
//
|
|
if r.Method == "OPTIONS" {
|
|
rw.WriteHeader(200)
|
|
return
|
|
}
|
|
|
|
username, password, ok := r.BasicAuth()
|
|
if ok {
|
|
resp, err := s.authenticator.Authenticate(&auth.AuthRequest{
|
|
Username: username,
|
|
Password: password,
|
|
AuthType: auth.AuthTypeBasic,
|
|
})
|
|
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"user": username,
|
|
"pas": password,
|
|
}).Error("failed uath")
|
|
// rw.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
|
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
r = auth.SetAuthenticationDetails(r, &resp.User)
|
|
|
|
next(rw, r)
|
|
return
|
|
}
|
|
|
|
// authenticating via token
|
|
|
|
resp, err := s.authenticator.Authenticate(&auth.AuthRequest{
|
|
Token: extractToken(r),
|
|
AuthType: auth.AuthTypeToken,
|
|
})
|
|
|
|
if err != nil {
|
|
// rw.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
|
|
|
log.Warnf("authentication by token failed, token: %s, err: %s", extractToken(r), err)
|
|
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
r = auth.SetAuthenticationDetails(r, &resp.User)
|
|
|
|
next(rw, r)
|
|
}
|
|
}
|
|
|
|
func extractToken(req *http.Request) string {
|
|
ex := request.AuthorizationHeaderExtractor
|
|
token, err := ex.ExtractToken(req)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return token
|
|
}
|
|
|
|
func (s *TriggerServer) logoutHandler(resp http.ResponseWriter, req *http.Request) {
|
|
|
|
resp.WriteHeader(200)
|
|
resp.Write([]byte(`{}`))
|
|
}
|
|
|
|
type loginRequest struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
func (s *TriggerServer) loginHandler(resp http.ResponseWriter, req *http.Request) {
|
|
|
|
var lr loginRequest
|
|
dec := json.NewDecoder(req.Body)
|
|
defer req.Body.Close()
|
|
|
|
err := dec.Decode(&lr)
|
|
if err != nil {
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
fmt.Fprintf(resp, "%s", err)
|
|
return
|
|
}
|
|
|
|
authResp, err := s.authenticator.Authenticate(&auth.AuthRequest{
|
|
Username: lr.Username,
|
|
Password: lr.Password,
|
|
AuthType: auth.AuthTypeBasic,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Warnf("auth failed for user '%s', error: %s", lr.Username, err)
|
|
http.Error(resp, "username or password incorrect", 401)
|
|
return
|
|
}
|
|
|
|
log.Infof("auth successful for user %s", lr.Username)
|
|
|
|
resp.Header().Add("Access-Control-Expose-Headers", "Authorization")
|
|
resp.Header().Add("Authorization", fmt.Sprintf("Bearer %s", authResp.Token))
|
|
|
|
response(authResp, 200, nil, resp, req)
|
|
}
|
|
|
|
func (s *TriggerServer) refreshHandler(resp http.ResponseWriter, req *http.Request) {
|
|
user := auth.GetAccountFromCtx(req.Context())
|
|
|
|
authResp, err := s.authenticator.GenerateToken(*user)
|
|
if err != nil {
|
|
response(nil, http.StatusOK, err, resp, req)
|
|
return
|
|
}
|
|
|
|
// adding token to header
|
|
resp.Header().Add("Access-Control-Expose-Headers", "Authorization")
|
|
resp.Header().Add("Authorization", fmt.Sprintf("Bearer %s", authResp.Token))
|
|
|
|
response(authResp, http.StatusOK, err, resp, req)
|
|
}
|