I'm currently making an API (with go) and I'm working on the session part. After research about what to use for session, I found JWT really interesting.
However I'm not really sure to understand how to use it after some tutorials. So this is my idea:
func main() { router := mux.NewRouter().StrictSlash(true) router.HandleFunc("/login", login) router.HandleFunc("/logout", logout) router.HandleFunc("/register", register) http.ListenAndServe(":8080", router) }
After those requests handled, I create the differents functions.
func login(w http.ResponseWriter, r *http.Request) { /* Here I just have to search in my database (SQL, I know how to do it). If the user is registered, I create a token and give it to him, but how can I do it? */ } func logout(w http.ResponseWriter, r *http.Request) { /* I get a token and stop/delete it? */ } func register(w http.ResponseWriter, r *http.Request) { /* I search if the user isn't register and then, if it isn't, I create a user in the database (I know how to do it). I connect him but again, how to make a new token? */ }
Lot of tutorials on the web seems really hard but I just want something simple. I just want an handle package (code above) which work with a service package to have something like an engine token authentication.
A second point I'm not sure to understand is the saving of the token. If a user connects himself, then what would be best? Each time the user runs their app, the app connects itself and get a new token from saved information (user/password) or the app just save the token forever? And what about the server, is the token managed and saved automatically with JWT or do I have to put it in my sql database?
Thank for your help !
EDIT 1
Thank you ! So after I read your answer, I encapsulated my code (token.go) like it
package services import ( "fmt" "github.com/dgrijalva/jwt-go" "time" "../models" ) var tokenEncodeString string = "something" func createToken(user models.User) (string, error) { // create the token token := jwt.New(jwt.SigningMethodHS256) // set some claims token.Claims["username"] = user.Username; token.Claims["password"] = user.Password; token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() //Sign and get the complete encoded token as string return (token.SignedString(tokenEncodeString)) } func parseToken(unparsedToken string) (bool, string) { token, err := jwt.Parse(unparsedToken, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } return myLookupKey(token.Header["kid"]), nil }) if err == nil && token.Valid { return true, unparsedToken } else { return false, "" } }
However, I got the following error: "token.go: undefined: myLookupKey" I looked on internet and I found an encapsulated function which have this prototype:
func ExampleParse(myToken string, myLookupKey func(interface{}) (interface{}, error)) { /* same code in my func parseToken() */ }
So what are the difference between my function and this one? How can I use this one?
Thanks !
To start, you need to import a JWT library in Golang (go get github.com/dgrijalva/jwt-go). You can find that library documentation in below link.
https://github.com/dgrijalva/jwt-go
Firstly, you need to create a token
// Create the token token := jwt.New(jwt.SigningMethodHS256) // Set some claims token.Claims["foo"] = "bar" token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() // Sign and get the complete encoded token as a string tokenString, err := token.SignedString(mySigningKey)
Secondly, parse that token
token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } return myLookupKey(token.Header["kid"]), nil }) if err == nil && token.Valid { deliverGoodness("!") } else { deliverUtterRejection(":(") }
Also, there are some examples for use JWT in GOlang like this https://github.com/slok/go-jwt-example
EDIT-1
package main import ( "fmt" "time" "github.com/dgrijalva/jwt-go" ) const ( mySigningKey = "WOW,MuchShibe,ToDogge" ) func main() { createdToken, err := ExampleNew([]byte(mySigningKey)) if err != nil { fmt.Println("Creating token failed") } ExampleParse(createdToken, mySigningKey) } func ExampleNew(mySigningKey []byte) (string, error) { // Create the token token := jwt.New(jwt.SigningMethodHS256) // Set some claims token.Claims["foo"] = "bar" token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() // Sign and get the complete encoded token as a string tokenString, err := token.SignedString(mySigningKey) return tokenString, err } func ExampleParse(myToken string, myKey string) { token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) { return []byte(myKey), nil }) if err == nil && token.Valid { fmt.Println("Your token is valid. I like your style.") } else { fmt.Println("This token is terrible! I cannot accept this.") } }
Just to make update of @massoud-afrashteh answer. In version 3 of jwt-go setting clams should be
// Set some claims claims := make(jwt.MapClaims) claims["foo"] = "bar" claims["exp"] = time.Now().Add(time.Hour * 72).Unix() token.Claims = claims
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With