mgoapi/login.go

130 lines
2.9 KiB
Go

package mgoapi
import (
"errors"
"reflect"
"time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
mgo "gopkg.in/mgo.v2"
)
// LoginModel is interface for modules which can be used for the login route
type LoginModel interface {
LoginCheck(db *mgo.Database) (tokenData interface{}, err error)
LoginResponse(token string) (interface{}, error)
}
func (api *API) loginPostHandler(m LoginModel) func(c *gin.Context) {
return func(c *gin.Context) {
lM := newModelOf(m).(LoginModel)
if err := c.Bind(lM); err != nil {
c.JSON(500, gin.H{
"error": err.Error(),
})
return
}
session := api.DBSession.Copy()
defer session.Close()
db := session.DB(api.DBName)
tokenData, err := lM.LoginCheck(db)
if err != nil {
c.JSON(500, gin.H{
"error": err.Error(),
})
return
}
if tokenData == nil {
c.JSON(403, gin.H{
"error": "login failed",
})
return
}
// build jwt
jwtToken := jwt.New(jwt.GetSigningMethod("HS256"))
oType := reflect.TypeOf(tokenData)
var objectType string
if oType.Kind() == reflect.Ptr {
objectType = oType.Elem().Name()
} else {
objectType = oType.Name()
}
if objectType == "" {
objectType = oType.String()
}
jwtToken.Claims = jwt.MapClaims{
"object": tokenData,
"type": objectType,
"exp": time.Now().Add(time.Minute * 60).Unix(),
}
token, err := jwtToken.SignedString(api.jwtSecret)
if err != nil {
c.JSON(500, gin.H{
"error": err.Error(),
})
return
}
response, err := lM.LoginResponse(token)
if err != nil {
c.JSON(500, gin.H{
"error": err.Error(),
})
return
}
c.JSON(200, response)
}
}
// ValidateAuthToken checks if token is valid and returns its data
func (c *Context) ValidateAuthToken() (tokenObject map[string]interface{}, tokenType string, err error) {
tokenObject = c.GetStringMap("validate-auth-token-object")
if tokenObject != nil {
tokenType = c.GetString("validate-auth-token-type")
_err, _ := c.Get("validate-auth-token-err")
if _err != nil {
err = _err.(error)
}
return // return cached data
}
token := c.Request.Header.Get(c.API.authenticationHeader)
if token == "" {
return nil, "", errors.New("empty token")
}
jwtToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
return []byte(c.API.jwtSecret), nil
})
if jwtToken == nil || jwtToken.Claims == nil {
return nil, "", err
}
if err := jwtToken.Claims.Valid(); err != nil {
return nil, "", err
}
claims := jwtToken.Claims.(jwt.MapClaims)
_object, ok := claims["object"].(map[string]interface{})
if !ok {
return nil, "", errors.New("token object data is invalid")
}
_type, ok := claims["type"].(string)
if !ok {
return nil, "", errors.New("token object type is invalid")
}
c.Set("validate-auth-token-object", _object)
c.Set("validate-auth-token-type", _type)
c.Set("validate-auth-token-err", err)
return _object, _type, err
}