Created
July 24, 2022 15:33
-
-
Save Goodnessuc/c92210cab062c541109e4fcf78bdfbe6 to your computer and use it in GitHub Desktop.
JWT tutorial in Go using the golang-jwt package
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
You can do that @Arthurgroll997 if you need it in your use case
Thanks!! Awesome gist, helped me a lot!!
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
Shouldn't you also verify wether the token is expired? I'm not entirely sure if
token.Valid
considers the token expiration time...