0

I have a registrer endpoint and a login endpoint that response with a JWT

But when a receive this JWT this process throws INVALID TOKEN

func ValidarToken(w http.ResponseWriter, r *http.Request) bool {

token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &models.Claim{}, func(token *jwt.Token) (interface{}, error){
        return VerifyKey, nil
})

if err != nil {
    switch err.(type) {
    case *jwt.ValidationError:
            vErr := err.(*jwt.ValidationError)
            switch vErr.Errors {
                case jwt.ValidationErrorExpired:
                    http.Error(w, "Su token ha expirado "+err.Error(),http.StatusUnauthorized)
                case jwt.ValidationErrorSignatureInvalid:
                    http.Error(w, "La firma del token no coincide "+err.Error(),http.StatusUnauthorized)
                default:
                    http.Error(w, "Su token no es válido "+err.Error(),http.StatusUnauthorized)
            }
    default:
        http.Error(w, "Su token no es válido "+err.Error(),http.StatusUnauthorized)
    }
    return false
}

Postman

I have read a lot of documentation but I cannot understand why the same token that I generate, then it is not recognized by the same App

Thanks

Updated :

This is my Generate JWT code

func GeneroJWT(t models.Usuario) (string, error) {

    leoClaves()

    payload := jwt.MapClaims{
           "email": t.Email,
           "nombre": t.Nombre,
           "apellidos": t.Apellidos,
           "fecha_nacimiento": t.FechaNacimiento,
           "biografia": t.Biografia,
           "ubicacion": t.Ubicacion,
           "sitioweb": t.SitioWeb,
           "exp": time.Now().Add(time.Hour * 24).Unix(),
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, payload)

    tokenStr, err := token.SignedString(SignKey)

    if err != nil {
        return tokenStr, err
    }
    return tokenStr,nil
}
Elba Nanero
  • 507
  • 1
  • 4
  • 10
  • Please provide some more info (from your question it's not clear if the issue is with your validation code or something else altogether; e.g. token creation, the routine adding it to the header etc). A good first step is to manually check the token as it was received. To do this add ```tokStr, err := request.OAuth2Extractor.ExtractToken(r)``` to the top of ```ValidarToken``` (dump the result to your log or console) and check that this succeeds and tokStr is the full token (use something like [this tool](https://jwt.io/#debugger-io) to see if it is, in fact, valid). – Brits Jan 29 '20 at 09:06
  • Hi Brits, the token is fine.. I have the same bytes, but when I process this token using the PrivateKey, the result is ERR, now I use this tkn, err := jwt.ParseWithClaims(reqToken, claims, func(token *jwt.Token) (interface{}, error) { return jwtKey, nil }) and I have the same error – Elba Nanero Feb 02 '20 at 20:15
  • My understanding was that you create the token with the private key and then verify with the public key? (At least that's how it works with JWT). Either way you have not provided enough info for someone to diagnose your issue - putting up code that creates the token and then immediately attempts to validate it would help focus in on your issue (as you are saying it's nothing to do with the way the token is communicated) – Brits Feb 02 '20 at 21:47
  • Hi Brits... please look my edited details THANKS – Elba Nanero Feb 02 '20 at 21:57
  • OK - now I'm really confused. Your GeneroJWT uses ```SigningMethodHS256``` which is a symetric algorithm (only one key) but your code uses ```SignKey``` and ```VerifyKey``` (and you mentioned a "PrivateKey") which sounds like you want to use certificates (asymmetric)? Please post a minimal reproducible example ([for example](https://play.golang.org/p/s3z13ED33E2)) - there are too many unknowns with the info provided so far. – Brits Feb 03 '20 at 00:12
  • Well my friend, I use OpenSSL algoritms to create the Public and Private keys... > openssl genrsa -out twitter.rsa 1024 > openssl rsa -in twitter.rsa -pubout > twitter.rsa.pub , what you use in SigningMethod then ? – Elba Nanero Feb 03 '20 at 00:52
  • 1
    ```token := jwt.NewWithClaims(jwt.SigningMethodHS256, payload)``` creates a token with a HS256 signature (see [this question](https://stackoverflow.com/questions/45878384/jwt-signature-rs256-or-hs256)). If you want to use certificates then you need to use SigningMethodRS256 (or SigningMethodES256) and make a few changes to prepare the certificate for use. [example](https://github.com/dgrijalva/jwt-go/blob/master/http_example_test.go) – Brits Feb 03 '20 at 01:05
  • Yes.. you're right !! THANKS ! – Elba Nanero Feb 03 '20 at 02:21
  • No worries - I have posted an answer in case others have a similar issues (JWT can get a bit confusing) – Brits Feb 03 '20 at 03:39

2 Answers2

0

I sign JWT in Go with this library: github.com/dgrijalva/jwt-go, and I checking it like this:

  reqToken := r.Header.Get("Authorization")

  splitToken := strings.Split(reqToken, "Bearer")
  if len(splitToken) != 2 {
   w.WriteHeader(http.StatusUnauthorized)
   fmt.Fprintln(w, "No se ha proporcionado el token")
   return
  }

  reqToken = strings.TrimSpace(splitToken[1])

  claims := &Claims{}

  tkn, err := jwt.ParseWithClaims(reqToken, claims, func(token *jwt.Token) (interface{}, error) {
   return jwtKey, nil
  })

  if err != nil {
   if err == jwt.ErrSignatureInvalid {
    w.WriteHeader(http.StatusUnauthorized)
    fmt.Fprintln(w, "No autenticado")
    return
   }
   w.WriteHeader(http.StatusBadRequest)
   fmt.Fprintln(w, "No autenticado")
   return
  }
  if !tkn.Valid {
   w.WriteHeader(http.StatusUnauthorized)
   return
  }

  next.ServeHTTP(w, r)

I hope this help you.

Saul Ramirez
  • 426
  • 2
  • 9
  • Hi Fernando, thanks for your Answer, but I still have the same problem.. with your code... look, my Private and Public Key, was generated with OpenSSL libraries.. in base64 enconded. – Elba Nanero Feb 02 '20 at 20:09
0

In this case the issue (as per the comments) was that an HS256 token was being produced using an RSA certificate as the secret. The HSA256 algorithm is symmetric (see this question for more info) so to decode with this you need to pass in the same secret as used to create the token (in this case a certificate was being passed in as a key but the library was treating it as a []byte rather that processing the certificate).

If you want to use asymmetric encryption (encrypt with private key; validate with public key) then another algorithm should be used (e.g. RS256). Example.

Brits
  • 14,829
  • 2
  • 18
  • 31