Add auth to qbittorent middleware
This commit is contained in:
@@ -5,8 +5,10 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/sirrobot01/decypharr/internal/config"
|
||||||
"github.com/sirrobot01/decypharr/pkg/arr"
|
"github.com/sirrobot01/decypharr/pkg/arr"
|
||||||
"github.com/sirrobot01/decypharr/pkg/store"
|
"github.com/sirrobot01/decypharr/pkg/store"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -125,6 +127,7 @@ func (q *QBit) categoryContext(next http.Handler) http.Handler {
|
|||||||
// Only a valid host and token will be added to the context/config. The rest are manual
|
// Only a valid host and token will be added to the context/config. The rest are manual
|
||||||
func (q *QBit) authContext(next http.Handler) http.Handler {
|
func (q *QBit) authContext(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cfg := config.Get()
|
||||||
host, token, err := decodeAuthHeader(r.Header.Get("Authorization"))
|
host, token, err := decodeAuthHeader(r.Header.Get("Authorization"))
|
||||||
category := getCategory(r.Context())
|
category := getCategory(r.Context())
|
||||||
arrs := store.Get().Arr()
|
arrs := store.Get().Arr()
|
||||||
@@ -145,12 +148,22 @@ func (q *QBit) authContext(next http.Handler) http.Handler {
|
|||||||
a.Token = token
|
a.Token = token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.Source = "auto"
|
if cfg.NeedsAuth() {
|
||||||
if err := validateServiceURL(a.Host); err != nil {
|
if a.Host == "" || a.Token == "" {
|
||||||
// Return silently, no need to raise a problem. Just do not add the Arr to the context/config.json
|
http.Error(w, "Unauthorized: Host and token are required for authentication", http.StatusUnauthorized)
|
||||||
next.ServeHTTP(w, r)
|
return
|
||||||
return
|
}
|
||||||
|
// try to use either Arr validate, or user auth validation
|
||||||
|
if err := a.Validate(); err != nil {
|
||||||
|
// If this failed, try to use user auth validation
|
||||||
|
if !verifyAuth(host, token) {
|
||||||
|
http.Error(w, "Unauthorized: Invalid host or token", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.Source = "auto"
|
||||||
arrs.AddOrUpdate(a)
|
arrs.AddOrUpdate(a)
|
||||||
ctx := context.WithValue(r.Context(), arrKey, a)
|
ctx := context.WithValue(r.Context(), arrKey, a)
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
@@ -176,3 +189,19 @@ func hashesContext(next http.Handler) http.Handler {
|
|||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func verifyAuth(username, password string) bool {
|
||||||
|
// If you're storing hashed password, use bcrypt to compare
|
||||||
|
if username == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
auth := config.Get().GetAuth()
|
||||||
|
if auth == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if username != auth.Username {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(auth.Password), []byte(password))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user