authorizer/server/token/jwt.go
Lakhan Samani 7ac6252aac fix: app login page signup url
add debug logs
2022-06-05 21:44:16 +05:30

217 lines
6.6 KiB
Go

package token
import (
"errors"
"github.com/golang-jwt/jwt"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// SignJWTToken common util to sing jwt token
func SignJWTToken(claims jwt.MapClaims) (string, error) {
jwtType, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
if err != nil {
return "", err
}
signingMethod := jwt.GetSigningMethod(jwtType)
if signingMethod == nil {
return "", errors.New("unsupported signing method")
}
t := jwt.New(signingMethod)
if t == nil {
return "", errors.New("unsupported signing method")
}
t.Claims = claims
switch signingMethod {
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
if err != nil {
return "", err
}
return t.SignedString([]byte(jwtSecret))
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
jwtPrivateKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)
if err != nil {
return "", err
}
key, err := crypto.ParseRsaPrivateKeyFromPemStr(jwtPrivateKey)
if err != nil {
return "", err
}
return t.SignedString(key)
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
jwtPrivateKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)
if err != nil {
return "", err
}
key, err := crypto.ParseEcdsaPrivateKeyFromPemStr(jwtPrivateKey)
if err != nil {
return "", err
}
return t.SignedString(key)
default:
return "", errors.New("unsupported signing method")
}
}
// ParseJWTToken common util to parse jwt token
func ParseJWTToken(token, hostname, nonce, subject string) (jwt.MapClaims, error) {
jwtType, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
if err != nil {
return nil, err
}
signingMethod := jwt.GetSigningMethod(jwtType)
var claims jwt.MapClaims
switch signingMethod {
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
if err != nil {
return nil, err
}
return []byte(jwtSecret), nil
})
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
if err != nil {
return nil, err
}
key, err := crypto.ParseRsaPublicKeyFromPemStr(jwtPublicKey)
if err != nil {
return nil, err
}
return key, nil
})
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
if err != nil {
return nil, err
}
key, err := crypto.ParseEcdsaPublicKeyFromPemStr(jwtPublicKey)
if err != nil {
return nil, err
}
return key, nil
})
default:
err = errors.New("unsupported signing method")
}
if err != nil {
return claims, err
}
// claim parses exp & iat into float 64 with e^10,
// but we expect it to be int64
// hence we need to assert interface and convert to int64
intExp := int64(claims["exp"].(float64))
intIat := int64(claims["iat"].(float64))
claims["exp"] = intExp
claims["iat"] = intIat
log.Debug("claims: ", claims)
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
if err != nil {
return claims, err
}
if claims["aud"] != clientID {
return claims, errors.New("invalid audience")
}
if claims["nonce"] != nonce {
return claims, errors.New("invalid nonce")
}
if claims["iss"] != hostname {
return claims, errors.New("invalid issuer")
}
if claims["sub"] != subject {
return claims, errors.New("invalid subject")
}
return claims, nil
}
// ParseJWTTokenWithoutNonce common util to parse jwt token without nonce
// used to validate ID token as it is not persisted in store
func ParseJWTTokenWithoutNonce(token, hostname string) (jwt.MapClaims, error) {
jwtType, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
if err != nil {
return nil, err
}
signingMethod := jwt.GetSigningMethod(jwtType)
var claims jwt.MapClaims
switch signingMethod {
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
if err != nil {
return nil, err
}
return []byte(jwtSecret), nil
})
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
if err != nil {
return nil, err
}
key, err := crypto.ParseRsaPublicKeyFromPemStr(jwtPublicKey)
if err != nil {
return nil, err
}
return key, nil
})
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
if err != nil {
return nil, err
}
key, err := crypto.ParseEcdsaPublicKeyFromPemStr(jwtPublicKey)
if err != nil {
return nil, err
}
return key, nil
})
default:
err = errors.New("unsupported signing method")
}
if err != nil {
return claims, err
}
// claim parses exp & iat into float 64 with e^10,
// but we expect it to be int64
// hence we need to assert interface and convert to int64
intExp := int64(claims["exp"].(float64))
intIat := int64(claims["iat"].(float64))
claims["exp"] = intExp
claims["iat"] = intIat
log.Debug("claims: ", claims)
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
if err != nil {
return claims, err
}
if claims["aud"] != clientID {
return claims, errors.New("invalid audience")
}
if claims["iss"] != hostname {
return claims, errors.New("invalid issuer")
}
return claims, nil
}