echo
echo copied to clipboard
Is there a way to use JWT with asymmetric cyphers in Echo v4?
Issue Description
I am trying to use Echo framework to create an API that is protected by JWT. I'm issuing JWT's using ithub.com/dgrijalva/jwt-go with jwt.SigningMethodES512 however in echo v4 middleware I only see middleware.AlgorithmHS256 available for signing method configuration.
A while back I saw a PR introducing RS256, but that doesn't seem to be available anymore.
Is there any way to use asymmetric cyphers for JWT ? I've tried simply passing "ES512" and the public key as SigningKey (which is confusing since for asymmetric cyphers the JWT is signed with private key but verified by public key).
Expected behaviour
Echo middleware is able to validate JWT's signed with asymmetric cyphers (such as RSxxx and ESxxx).
You can create your own middleware and validate using jwt-go and reproduce the same exact behavior of the middleware provided by the echo-contrib package.
This is what I did (still using symmetric keys) but I think this is a good starting point, take a look to the validateJwtToken function
func ValidateAuth(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
authorizationHeader := c.Request().Header.Get("authorization")
if len(authorizationHeader) == 0 {
return &echo.HTTPError{
Code: http.StatusUnauthorized,
Message: "missing Authentication header",
Internal: errors.New("missing Authentication header"),
}
}
log.Debug("parsing authentication header")
authPair := strings.SplitN(authorizationHeader, " ", 2)
if len(authPair) != 2 {
return &echo.HTTPError{
Code: http.StatusUnauthorized,
Message: "wrong Authentication header definiton",
Internal: errors.New("wrong Authentication header definiton"),
}
}
headerAuthScheme := authPair[0]
headerAuthToken := authPair[1]
if headerAuthScheme != "Bearer" {
return &echo.HTTPError{
Code: http.StatusUnauthorized,
Message: "wrong Authentication header definiton",
Internal: errors.New("wrong Authentication header definiton. Neither Basic or Bearer Scheme sent"),
}
}
log.Debug("validating JWT token")
token, err := validateJwtToken(headerAuthToken)
if err == nil && token.Valid {
log.Debug("JWT token is valid")
c.Set("User", token)
return next(c)
}
// stop the flow
return &echo.HTTPError{
Code: http.StatusUnauthorized,
Message: "invalid or expired jwt",
Internal: err,
}
}
}
// you can add your implementation here.
func validateJwtToken(tokenString string) (*jwt.Token, error) {
JWTSecret := os.Getenv("JWT_SECRET")
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(JWTSecret), nil
})
if err != nil || !token.Valid {
return nil, err
}
return token, nil
}
// method.go
func (m *Routes) Account(c echo.Context) error {
user := c.Get("User").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
email := claims["email"].(string)
}
// routes.go
e.GET("/user/account", method.Account, middleware.ValidateAuth)
I hope this helps
As the asymmetric cipher methods require a private and public key the configuration would need to be changed to allow to provide both SigningPrivateKey and SigningPublicKey. Using a custom validator function is the best way currently.
Our used JWT library jwt-go is preparing a v4 release that we should target, so this may make sense to keep an eye on.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@andrei-dascalu Hi, I just come across this discussion. I have a project example implementing echo with RSA as the signing method in here.
Here is how I signed the JWT with the private key. https://github.com/Keda87/golang-echo-jwt-rsa/blob/main/helpers.go#L61-L79
And how I validate the JWT with the public key. https://github.com/Keda87/golang-echo-jwt-rsa/blob/main/main.go#L17-L23
I'm not sure if this is what you need or not, but from my understanding of @lammel's comments, it is quite similar to my RSA implementation.