I'm using JWT. This is how I create the token.
func createToken(user User) (string, error) {
token := jwt.New(jwt.GetSigningMethod("RS256"))
token.Claims["Name"] = user.Name
token.Claims["Email"] = user.Email
//token.Claims["ExpDate"] = time.Now().Add(time.Hour * 1).Unix()
tokenString, err := token.SignedString([]byte(config.PrivateKey))
if err != nil {
return "", err
}
return tokenString, nil
}
This is how I verify the token.
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(config.PublicKey), nil
})
I generated my public and private keys with this python code
from Crypto.PublicKey import RSA
private = RSA.generate(1024)
public = private.publickey()
priv = private.exportKey()
pub = public.exportKey()
I get crypto/rsa: verification error
. When I print the parsed token everything looks fine except token.Valid
which is false and token.Signature
is empty.
type Token struct {
Raw string // The raw token. Populated when you Parse a token
Method SigningMethod // The signing method used or to be used
Header map[string]interface{} // The first segment of the token
Claims map[string]interface{} // The second segment of the token
Signature string // The third segment of the token. Populated when you Parse a token
Valid bool // Is the token valid? Populated when you Parse/Verify a token
}
tokenString--> eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InRlc3RAaG90bWFpbC5jb20iLCJOYW1lIjoidGVzdE5hbWUifQ.fgd1h4LB1zzAiPFLKMOJrQu12rTLeXBDKHdnqiNc04NRn-1v7cHEQpDNawvScMIGrcQLbZo6WrldZQT9ImYWpUyy3CcD2uMO95I5PN6aXOSPb26nNGQpmIi1HNZrq5359hKZ6BWEJnW9iTg7RgmMvZGmIqlGLsOY2a6UiiwBsI0
token.Raw--> eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InRlc3RAaG90bWFpbC5jb20iLCJOYW1lIjoidGVzdE5hbWUifQ.fgd1h4LB1zzAiPFLKMOJrQu12rTLeXBDKHdnqiNc04NRn-1v7cHEQpDNawvScMIGrcQLbZo6WrldZQT9ImYWpUyy3CcD2uMO95I5PN6aXOSPb26nNGQpmIi1HNZrq5359hKZ6BWEJnW9iTg7RgmMvZGmIqlGLsOY2a6UiiwBsI0
token.Header--> map[alg:RS256 typ:JWT]
token.Claims--> map[Email:test@hotmail.com Name:testName]
token.Signature-->
token.Valid--> false
PS: I don't have any SSL-Certificates.
This worked for me. I generated the private.pem and public.pem using these commands.
openssl genrsa -des3 -out private.pem 1024
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
Code:
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"io/ioutil"
"log"
"time"
)
//Claims can have user id.. etc for Identification purpose
type AppClaims struct {
UserId string `json:"userId"`
jwt.StandardClaims
}
var (
privateKey []byte
publicKey []byte
err error
)
const (
longForm = "Jan 2, 2006 at 3:04pm (MST)"
)
func errLog(err error) {
if err != nil {
log.Fatal("Error:", err.Error())
}
}
func init() {
privateKey, err = ioutil.ReadFile("../private.pem")
errLog(err)
publicKey, err = ioutil.ReadFile("../public.pem")
errLog(err)
}
func jwtTokenGen() (interface{}, error) {
privateRSA, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
if err != nil {
return nil, err
}
claims := AppClaims{
"RAJINIS*",
jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Minute * 15).Unix(),
Issuer: "test",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
ss, err := token.SignedString(privateRSA)
return ss, err
}
func jwtTokenRead(inToken interface{}) (interface{}, error) {
publicRSA, err := jwt.ParseRSAPublicKeyFromPEM(publicKey)
if err != nil {
return nil, err
}
token, err := jwt.Parse(inToken.(string), 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 publicRSA, err
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
} else {
return nil, err
}
}
func getTokenRemainingValidity(timestamp interface{}) int {
expireOffset := 0
if validity, ok := timestamp.(float64); ok {
tm := time.Unix(int64(validity), 0)
remainder := tm.Sub(time.Now())
if remainder > 0 {
fmt.Println(remainder)
return int(remainder.Seconds()) + expireOffset
}
}
return expireOffset
}
func main() {
signedString, err := jwtTokenGen()
fmt.Println(signedString, err)
claims, err := jwtTokenRead(signedString)
if err != nil {
errLog(err)
}
claimValue := claims.(jwt.MapClaims)
fmt.Println(claimValue["iss"], claimValue["exp"], claimValue["userId"])
// t, _ := time.Parse(longForm, string(claimValue["exp"].(float64)))
fmt.Println(getTokenRemainingValidity(claimValue["exp"]))
}