Skip to content

Instantly share code, notes, and snippets.

@Goodnessuc
Created July 24, 2022 15:33
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save Goodnessuc/c92210cab062c541109e4fcf78bdfbe6 to your computer and use it in GitHub Desktop.
Save Goodnessuc/c92210cab062c541109e4fcf78bdfbe6 to your computer and use it in GitHub Desktop.
JWT tutorial in Go using the golang-jwt package
package main
import (
"encoding/json"
"fmt"
"github.com/golang-jwt/jwt"
"log"
"net/http"
"time"
)
type Message struct {
Status string `json:"status"`
Info string `json:"info"`
}
var sampleSecretKey = []byte("SecretYouShouldHide")
func handlePage(writer http.ResponseWriter, request *http.Request) {
_, err := generateJWT()
if err != nil {
log.Fatalln("Error generating JWT", err)
}
writer.Header().Set("Token", "%v")
type_ := "application/json"
writer.Header().Set("Content-Type", type_)
var message Message
err = json.NewDecoder(request.Body).Decode(&message)
if err != nil {
return
}
err = json.NewEncoder(writer).Encode(message)
if err != nil {
return
}
}
func generateJWT() (string, error) {
token := jwt.New(jwt.SigningMethodEdDSA)
claims := token.Claims.(jwt.MapClaims)
claims["exp"] = time.Now().Add(10 * time.Minute)
claims["authorized"] = true
claims["user"] = "username"
tokenString, err := token.SignedString(sampleSecretKey)
if err != nil {
return "Signing Error", err
}
return tokenString, nil
}
// comment these
func verifyJWT(endpointHandler func(writer http.ResponseWriter, request *http.Request)) http.HandlerFunc {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.Header["Token"] != nil {
token, err := jwt.Parse(request.Header["Token"][0], func(token *jwt.Token) (interface{}, error) {
_, ok := token.Method.(*jwt.SigningMethodECDSA)
if !ok {
writer.WriteHeader(http.StatusUnauthorized)
_, err := writer.Write([]byte("You're Unauthorized"))
if err != nil {
return nil, err
}
}
return "", nil
})
// parsing errors result
if err != nil {
writer.WriteHeader(http.StatusUnauthorized)
_, err2 := writer.Write([]byte("You're Unauthorized due to error parsing the JWT"))
if err2 != nil {
return
}
}
// if there's a token
if token.Valid {
endpointHandler(writer, request)
} else {
writer.WriteHeader(http.StatusUnauthorized)
_, err := writer.Write([]byte("You're Unauthorized due to invalid token"))
if err != nil {
return
}
}
} else {
writer.WriteHeader(http.StatusUnauthorized)
_, err := writer.Write([]byte("You're Unauthorized due to No token in the header"))
if err != nil {
return
}
}
// response for if there's no token header
})
}
func extractClaims(_ http.ResponseWriter, request *http.Request) (string, error) {
if request.Header["Token"] != nil {
tokenString := request.Header["Token"][0]
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
return nil, fmt.Errorf("there's an error with the signing method")
}
return sampleSecretKey, nil
})
if err != nil {
return "Error Parsing Token: ", err
}
claims, ok := token.Claims.(jwt.MapClaims)
if ok && token.Valid {
username := claims["username"].(string)
return username, nil
}
}
return "unable to extract claims", nil
}
func authPage() {
token, _ := generateJWT()
client := &http.Client{}
req, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
req.Header.Set("Token", token)
_, _ = client.Do(req)
}
func main() {
http.HandleFunc("/home", verifyJWT(handlePage))
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Println("There was an error listening on port :8080", err)
}
}
@Arthurgroll997
Copy link

Shouldn't you also verify wether the token is expired? I'm not entirely sure if token.Valid considers the token expiration time...

@Goodnessuc
Copy link
Author

You can do that @Arthurgroll997 if you need it in your use case

@Arthurgroll997
Copy link

Thanks!! Awesome gist, helped me a lot!!

@AuroraTea
Copy link

Why is []byte used as the key for signing with SigningMethodEdDSA?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment