mirror of
https://github.com/ChuckNorrison/LightningTipBot.git
synced 2026-08-13 12:33:14 +02:00
add auth middleware
This commit is contained in:
parent
a669ea86ac
commit
4bcbd2fefe
3 changed files with 92 additions and 6 deletions
|
|
@ -1,8 +1,15 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/lnbits"
|
||||
"github.com/LightningTipBot/LightningTipBot/internal/telegram"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
|
@ -16,6 +23,74 @@ func LoggingMiddleware(prefix string, next http.HandlerFunc) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
type AuthType string
|
||||
|
||||
const (
|
||||
AuthTypeBasic AuthType = "Basic"
|
||||
AuthTypeBearer AuthType = "Bearer"
|
||||
)
|
||||
|
||||
func AuthorizationMiddleware(database *gorm.DB, authType AuthType, next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
auth := r.Header.Get("Authorization")
|
||||
// check if the user is banned
|
||||
if auth != "" {
|
||||
_, password, ok := parseAuth(authType, auth)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
// first we make sure that the password is not already "banned_"
|
||||
if strings.Contains(password, "_") || strings.HasPrefix(password, "banned_") {
|
||||
log.Warnf("[AuthorizationMiddleware] Banned user %s. Not forwarding request", password)
|
||||
return
|
||||
}
|
||||
// then we check whether the "normal" password provided is in the database (it should be not if the user is banned)
|
||||
user := &lnbits.User{}
|
||||
tx := database.Where("wallet_adminkey = ? COLLATE NOCASE", password).First(user)
|
||||
if tx.Error != nil {
|
||||
tx = database.Where("wallet_inkey = ? COLLATE NOCASE", password).First(user)
|
||||
log.Warnf("[AuthorizationMiddleware] Could not get wallet admin key %s: %v", password, tx.Error)
|
||||
if tx.Error != nil {
|
||||
log.Warnf("[AuthorizationMiddleware] need admin key to pay invoice %s: %v", password, tx.Error)
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/api/v1/payinvoice" {
|
||||
log.Warnf("[AuthorizationMiddleware] need admin key to pay invoice %s: %v", password, tx.Error)
|
||||
return
|
||||
}
|
||||
}
|
||||
r.Context()
|
||||
log.Debugf("[AuthorizationMiddleware] User: %s", telegram.GetUserStr(user.Telegram))
|
||||
r = r.WithContext(context.WithValue(r.Context(), "user", user))
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// parseAuth parses an HTTP Basic Authentication string.
|
||||
// "Bearer QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
|
||||
func parseAuth(authType AuthType, auth string) (username, password string, ok bool) {
|
||||
parse := func(prefix string) (username, password string, ok bool) {
|
||||
// Case insensitive prefix match. See Issue 22736.
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
return parse(fmt.Sprintf("%s ", authType))
|
||||
|
||||
}
|
||||
|
||||
func dump(r *http.Request) string {
|
||||
x, err := httputil.DumpRequest(r, true)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
|
|
@ -42,6 +43,12 @@ func (w *Server) ListenAndServe() {
|
|||
func (w *Server) PathPrefix(path string, handler http.Handler) {
|
||||
w.router.PathPrefix(path).Handler(handler)
|
||||
}
|
||||
func (w *Server) AppendAuthorizedRoute(path string, authType AuthType, database *gorm.DB, handler func(http.ResponseWriter, *http.Request), methods ...string) {
|
||||
r := w.router.HandleFunc(path, LoggingMiddleware("API", AuthorizationMiddleware(database, authType, handler)))
|
||||
if len(methods) > 0 {
|
||||
r.Methods(methods...)
|
||||
}
|
||||
}
|
||||
func (w *Server) AppendRoute(path string, handler func(http.ResponseWriter, *http.Request), methods ...string) {
|
||||
r := w.router.HandleFunc(path, LoggingMiddleware("API", handler))
|
||||
if len(methods) > 0 {
|
||||
|
|
|
|||
16
main.go
16
main.go
|
|
@ -54,7 +54,6 @@ func startApiServer(bot *telegram.TipBot) {
|
|||
// append lnurl ctx functions
|
||||
lnUrl := lnurl.New(bot)
|
||||
s.AppendRoute("/.well-known/lnurlp/{username}", lnUrl.Handle, http.MethodGet)
|
||||
|
||||
// userpage server
|
||||
userpage := userpage.New(bot)
|
||||
s.AppendRoute("/@{username}", userpage.UserPageHandler, http.MethodGet)
|
||||
|
|
@ -63,14 +62,16 @@ func startApiServer(bot *telegram.TipBot) {
|
|||
hub := lndhub.New(bot)
|
||||
s.AppendRoute(`/lndhub/ext/{.*}`, hub.Handle)
|
||||
s.AppendRoute(`/lndhub/ext`, hub.Handle)
|
||||
//s.AppendAuthorizedRoute(`/lndhub/ext/{.*}`, api.AuthTypeBearer, bot.DB.Users, hub.Handle)
|
||||
//s.AppendAuthorizedRoute(`/lndhub/ext`, api.AuthTypeBearer, bot.DB.Users, hub.Handle)
|
||||
|
||||
// starting api service
|
||||
apiService := api.Service{}
|
||||
s.AppendRoute(`/api/v1/paymentstatus/{payment_hash}`, apiService.PaymentStatus, http.MethodPost)
|
||||
s.AppendRoute(`/api/v1/invoicestatus/{payment_hash}`, apiService.InvoiceStatus, http.MethodPost)
|
||||
s.AppendRoute(`/api/v1/payinvoice`, apiService.PayInvoice, http.MethodPost)
|
||||
s.AppendRoute(`/api/v1/createinvoice`, apiService.CreateInvoice, http.MethodPost)
|
||||
s.AppendRoute(`/api/v1/balance`, apiService.Balance, http.MethodGet)
|
||||
s.AppendAuthorizedRoute(`/api/v1/paymentstatus/{payment_hash}`, api.AuthTypeBasic, bot.DB.Users, apiService.PaymentStatus, http.MethodPost)
|
||||
s.AppendAuthorizedRoute(`/api/v1/invoicestatus/{payment_hash}`, api.AuthTypeBasic, bot.DB.Users, apiService.InvoiceStatus, http.MethodPost)
|
||||
s.AppendAuthorizedRoute(`/api/v1/payinvoice`, api.AuthTypeBasic, bot.DB.Users, apiService.PayInvoice, http.MethodPost)
|
||||
s.AppendAuthorizedRoute(`/api/v1/createinvoice`, api.AuthTypeBasic, bot.DB.Users, apiService.CreateInvoice, http.MethodPost)
|
||||
s.AppendAuthorizedRoute(`/api/v1/balance`, api.AuthTypeBasic, bot.DB.Users, apiService.Balance, http.MethodGet)
|
||||
|
||||
// start internal admin server
|
||||
adminService := admin.New(bot)
|
||||
|
|
@ -83,6 +84,9 @@ func startApiServer(bot *telegram.TipBot) {
|
|||
|
||||
}
|
||||
|
||||
func withMiddleware(mw func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
|
||||
return mw
|
||||
}
|
||||
func withRecovery() {
|
||||
if r := recover(); r != nil {
|
||||
log.Errorln("Recovered panic: ", r)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue