Add user IP to its token
This commit is contained in:
parent
5e81b17e28
commit
bd20a87548
@ -71,7 +71,7 @@ func (a *Authorizer) GenHash(password string) (string, error) {
|
||||
}
|
||||
|
||||
// Login cheks password and creates a jwt token
|
||||
func (a *Authorizer) Login(username, password string) (*tokens.Token, error) {
|
||||
func (a *Authorizer) Login(r *http.Request, username, password string) (*tokens.Token, error) {
|
||||
u, err := a.Backend.GetUser(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -104,6 +104,7 @@ func (a *Authorizer) Login(username, password string) (*tokens.Token, error) {
|
||||
t := &tokens.Token{
|
||||
Token: ss,
|
||||
Username: u.GetName(),
|
||||
IP: getIPFromRequest(r),
|
||||
}
|
||||
|
||||
if err := t.Add(a.db); err != nil {
|
||||
@ -168,6 +169,7 @@ func (a *Authorizer) CurrentUser(rw http.ResponseWriter, req *http.Request) (Use
|
||||
}
|
||||
|
||||
token.UserAgent = req.UserAgent()
|
||||
token.IP = getIPFromRequest(req)
|
||||
if err := token.Update(a.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,19 +2,21 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ipContextKey string
|
||||
type authContextKey string
|
||||
|
||||
// Middleware get User from session and put it in context
|
||||
type Middleware struct {
|
||||
authorizer *Authorizer
|
||||
log *logrus.Entry
|
||||
}
|
||||
|
||||
type authContextKey string
|
||||
|
||||
// NewMiddleware returns a new authentication middleware
|
||||
func NewMiddleware(authorizer *Authorizer, log *logrus.Entry) *Middleware {
|
||||
return &Middleware{
|
||||
@ -101,3 +103,57 @@ func GetCurrentUser(r *http.Request, log *logrus.Entry) User {
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
// IPMiddleware set the IP in the request context
|
||||
type IPMiddleware struct {
|
||||
log *logrus.Entry
|
||||
}
|
||||
|
||||
// NewIPMiddleware returns a new ip middleware
|
||||
func NewIPMiddleware(log *logrus.Entry) *IPMiddleware {
|
||||
return &IPMiddleware{
|
||||
log: log.WithField("middleware", "ip"),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *IPMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||
ip := getRequestIP(r)
|
||||
|
||||
ctxKey := ipContextKey("ip")
|
||||
ctx := context.WithValue(r.Context(), ctxKey, ip)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
next(w, r)
|
||||
}
|
||||
|
||||
func getRequestIP(req *http.Request) string {
|
||||
// Try to get the IP from this header
|
||||
var ip = req.Header.Get("X-Real-IP")
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
|
||||
// Or from this one
|
||||
ip = req.Header.Get("X-Forwarded-For")
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||
if err != nil {
|
||||
// fake result
|
||||
return "0.0.0.0"
|
||||
}
|
||||
|
||||
hostIP := net.ParseIP(host)
|
||||
if host == "" {
|
||||
return "0.0.0.0"
|
||||
}
|
||||
|
||||
// Default to the IP from the request
|
||||
return hostIP.String()
|
||||
}
|
||||
|
||||
func getIPFromRequest(r *http.Request) string {
|
||||
return r.Context().Value(ipContextKey("ip")).(string)
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ func main() {
|
||||
defer c.Stop()
|
||||
|
||||
n := negroni.Classic()
|
||||
// Middleware for setting ips
|
||||
n.Use(auth.NewIPMiddleware(log))
|
||||
// Middleware for authentication
|
||||
n.Use(authMiddleware)
|
||||
// Serve static files
|
||||
|
@ -4,18 +4,19 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"gitlab.quimbo.fr/odwrtw/canape/backend/sqly"
|
||||
)
|
||||
|
||||
const (
|
||||
addTokenQuery = `INSERT INTO tokens (token, username) VALUES ($1, $2);`
|
||||
addTokenQuery = `INSERT INTO tokens (token, username, ip) VALUES ($1, $2, $3);`
|
||||
getTokenQuery = `SELECT * FROM tokens WHERE token=$1;`
|
||||
getUserTokenQuery = `SELECT * FROM tokens WHERE username=$1 and token=$2;`
|
||||
getUserTokensQuery = `SELECT * FROM tokens WHERE username=$1;`
|
||||
deleteTokenQuery = `DELETE FROM tokens WHERE username=$1 AND token=$2;`
|
||||
updateTokenQuery = `UPDATE tokens SET description=:description, user_agent=:user_agent WHERE token=:token RETURNING *;`
|
||||
updateTokenQuery = `UPDATE tokens SET description=:description, user_agent=:user_agent, ip=:ip, last_used=now() WHERE token=:token RETURNING *;`
|
||||
)
|
||||
|
||||
// Custom errors
|
||||
@ -30,11 +31,13 @@ type Token struct {
|
||||
Token string `db:"token" json:"token"`
|
||||
Description string `db:"description" json:"description"`
|
||||
UserAgent string `db:"user_agent" json:"user_agent"`
|
||||
IP string `db:"ip" json:"ip"`
|
||||
LastUsed time.Time `db:"last_used" json:"last_used"`
|
||||
}
|
||||
|
||||
// Add a token to the database
|
||||
func (t *Token) Add(db *sqlx.DB) error {
|
||||
_, err := db.Queryx(addTokenQuery, t.Token, t.Username)
|
||||
_, err := db.Queryx(addTokenQuery, t.Token, t.Username, t.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func LoginPOSTHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := e.Auth.Login(data.Username, data.Password)
|
||||
token, err := e.Auth.Login(r, data.Username, data.Password)
|
||||
if err != nil {
|
||||
if err == auth.ErrInvalidPassword || err == ErrUnknownUser {
|
||||
return e.RenderError(w, fmt.Errorf("Error invalid user or password"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user