[feat] Add header authentication support
In some cases there are needs to authenticate user not in Taskcafe itself. For this reason option server.remote_user_header was added. ```toml [server] remote_user_header = "X-Remote-User" ``` With turned on Taskcafe listens X-Remote-User http header and skip password checking. But still check user existence and activity flag.
This commit is contained in:
@ -102,6 +102,15 @@ func (h *TaskcafeHandler) LogoutHandler(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// LoginHandler creates a new refresh & access token for the user if given the correct credentials
|
||||
func (h *TaskcafeHandler) LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if h.SecurityConfig.IsRemoteAuth() {
|
||||
h.headerAuthenticate(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
h.credentialsHandler(w, r)
|
||||
}
|
||||
|
||||
func (h *TaskcafeHandler) credentialsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var requestData LoginRequestData
|
||||
err := json.NewDecoder(r.Body).Decode(&requestData)
|
||||
if err != nil {
|
||||
@ -139,9 +148,47 @@ func (h *TaskcafeHandler) LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
authCreatedAt := time.Now().UTC()
|
||||
authExpiresAt := authCreatedAt.AddDate(0, 0, 1)
|
||||
authToken, err := h.repo.CreateAuthToken(r.Context(), db.CreateAuthTokenParams{user.UserID, authCreatedAt, authExpiresAt})
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
// TODO: should we return here?
|
||||
}
|
||||
|
||||
w.Header().Set("Content-type", "application/json")
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "authToken",
|
||||
Value: authToken.TokenID.String(),
|
||||
Expires: authExpiresAt,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
})
|
||||
json.NewEncoder(w).Encode(LoginResponseData{Complete: true, UserID: authToken.UserID.String()})
|
||||
}
|
||||
|
||||
func (h *TaskcafeHandler) headerAuthenticate(w http.ResponseWriter, r *http.Request) {
|
||||
xRemoteUser := r.Header.Get(h.SecurityConfig.UserAuthHeader)
|
||||
user, err := h.repo.GetUserAccountByUsername(r.Context(), xRemoteUser)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"username": xRemoteUser,
|
||||
}).Warn("user account not found")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if !user.Active {
|
||||
log.WithFields(log.Fields{
|
||||
"username": user.Username,
|
||||
}).Warn("attempt to login with inactive user")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
authCreatedAt := time.Now().UTC()
|
||||
authExpiresAt := authCreatedAt.AddDate(0, 0, 1)
|
||||
authToken, err := h.repo.CreateAuthToken(r.Context(), db.CreateAuthTokenParams{user.UserID, authCreatedAt, authExpiresAt})
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-type", "application/json")
|
||||
|
@ -65,8 +65,13 @@ type TaskcafeHandler struct {
|
||||
SecurityConfig utils.SecurityConfig
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Email utils.EmailConfig
|
||||
Security utils.SecurityConfig
|
||||
}
|
||||
|
||||
// NewRouter creates a new router for chi
|
||||
func NewRouter(dbConnection *sqlx.DB, emailConfig utils.EmailConfig, securityConfig utils.SecurityConfig) (chi.Router, error) {
|
||||
func NewRouter(dbConnection *sqlx.DB, cfg Config) (chi.Router, error) {
|
||||
formatter := new(log.TextFormatter)
|
||||
formatter.TimestampFormat = "02-01-2006 15:04:05"
|
||||
formatter.FullTimestamp = true
|
||||
@ -93,7 +98,7 @@ func NewRouter(dbConnection *sqlx.DB, emailConfig utils.EmailConfig, securityCon
|
||||
}))
|
||||
|
||||
repository := db.NewRepository(dbConnection)
|
||||
taskcafeHandler := TaskcafeHandler{*repository, securityConfig}
|
||||
taskcafeHandler := TaskcafeHandler{*repository, cfg.Security}
|
||||
|
||||
var imgServer = http.FileServer(http.Dir("./uploads/"))
|
||||
r.Group(func(mux chi.Router) {
|
||||
@ -108,7 +113,7 @@ func NewRouter(dbConnection *sqlx.DB, emailConfig utils.EmailConfig, securityCon
|
||||
r.Group(func(mux chi.Router) {
|
||||
mux.Use(auth.Middleware)
|
||||
mux.Post("/users/me/avatar", taskcafeHandler.ProfileImageUpload)
|
||||
mux.Handle("/graphql", graph.NewHandler(*repository, emailConfig))
|
||||
mux.Handle("/graphql", graph.NewHandler(*repository, cfg.Email))
|
||||
})
|
||||
|
||||
frontend := FrontendHandler{staticPath: "build", indexPath: "index.html"}
|
||||
|
Reference in New Issue
Block a user