initial commit 2
This commit is contained in:
153
infra/auth/auth.go
Normal file
153
infra/auth/auth.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
const (
|
||||
// AppKeyHeaderName is the header name for application keys
|
||||
AppKeyHeaderName = "App"
|
||||
// AppTokenHeaderName is the header name for application token
|
||||
AppTokenHeaderName = "Token"
|
||||
// TokenExpiration is the auth token default expiration time
|
||||
TokenExpiration = 24 * time.Hour
|
||||
)
|
||||
|
||||
var (
|
||||
// TokenSigningMethod is the auth token signing algorithm
|
||||
TokenSigningMethod = jwt.SigningMethodRS256
|
||||
)
|
||||
|
||||
// GetAppKeyFromContext returns the application key from request header
|
||||
func GetAppKeyFromContext(ctx echo.Context) (appKey string, err error) {
|
||||
appKey = ctx.Request().Header.Get(AppKeyHeaderName)
|
||||
|
||||
if strings.TrimSpace(appKey) == "" {
|
||||
return "", errors.NewNotAuthorizedError("Application key not found")
|
||||
}
|
||||
|
||||
return appKey, nil
|
||||
}
|
||||
|
||||
// ValidateAppKey validates the presence and validity of App key
|
||||
func ValidateAppKey(ctx echo.Context, cfg *config.Config) (err error) {
|
||||
appKey, err := GetAppKeyFromContext(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
|
||||
if appKey != cfg.HTTP.Auth.AppKey {
|
||||
return errors.NewNotAuthorizedError("Invalid API Key")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCertPrivateKey returns the private key for the token authentication certificate
|
||||
func GetCertPrivateKey(path string) (pk *rsa.PrivateKey, err error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
pk, err = jwt.ParseRSAPrivateKeyFromPEM(data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
// GetCertPublicKey returns the public key for the token authentication certificate
|
||||
func GetCertPublicKey(path string) (pk *rsa.PublicKey, err error) {
|
||||
privateKey, err := GetCertPrivateKey(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
return &privateKey.PublicKey, nil
|
||||
}
|
||||
|
||||
// GenerateToken creates a token based on certificate
|
||||
func GenerateToken(cfg *config.Config, data interface{}) (tokenString string, err error) {
|
||||
key, _ := GetCertPrivateKey(cfg.HTTP.Auth.CertificatePath)
|
||||
|
||||
claims := jwt.MapClaims{
|
||||
"iat": time.Now().Unix(),
|
||||
"exp": time.Now().Add(TokenExpiration).Unix(),
|
||||
"iss": "BDC",
|
||||
"sub": "NEMT",
|
||||
"data": data,
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(TokenSigningMethod, claims)
|
||||
tokenString, err = token.SignedString(key)
|
||||
if err != nil {
|
||||
return tokenString, errors.Wrap(err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
func GetTokenDetail(ctx echo.Context, cfg *config.Config) (interface{}, error) {
|
||||
key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
|
||||
|
||||
tokenString := ctx.Request().Header.Get("Token")
|
||||
tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
return claims["data"], nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserDetail(ctx echo.Context, cfg *config.Config) (viewmodel.User, error) {
|
||||
key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
|
||||
|
||||
tokenString := ctx.Request().Header.Get("Token")
|
||||
tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
if err != nil {
|
||||
return viewmodel.User{}, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
byteData, _ := ffjson.Marshal(claims["data"])
|
||||
user := viewmodel.User{}
|
||||
err = ffjson.Unmarshal(byteData, &user)
|
||||
if err != nil {
|
||||
return viewmodel.User{}, err
|
||||
} else {
|
||||
return user, nil
|
||||
}
|
||||
} else {
|
||||
return viewmodel.User{}, err
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user