Skip to content

Instantly share code, notes, and snippets.

@scottjbarr
Forked from thealexcons/jwt_golang_example.go
Last active April 10, 2016 23:34
Show Gist options
  • Save scottjbarr/2b5cf4f9010dee3f97d42dc2583ef04a to your computer and use it in GitHub Desktop.
Save scottjbarr/2b5cf4f9010dee3f97d42dc2583ef04a to your computer and use it in GitHub Desktop.
JSON Web Token example
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
"github.com/codegangsta/negroni"
"github.com/dgrijalva/jwt-go"
"os"
)
const (
privKeyPath = "path/to/keys/app.rsa"
pubKeyPath = "path/to/keys/app.rsa.pub"
)
var VerifyKey, SignKey []byte
func initKeys() {
var err error
SignKey, err = ioutil.ReadFile(privKeyPath)
if err != nil {
log.Fatal("Error reading private key")
return
}
VerifyKey, err = ioutil.ReadFile(pubKeyPath)
if err != nil {
log.Fatal("Error reading public key")
return
}
}
type UserCredentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
Password string `json:"password"`
}
type Response struct {
Data string `json:"data"`
}
type Token struct {
Token string `json:"token"`
}
func StartServer() {
// public endpoints
http.HandleFunc("/login", LoginHandler)
// protected endpoints
http.Handle("/resource/", negroni.New(
negroni.HandlerFunc(ValidateTokenMiddleware),
negroni.Wrap(http.HandlerFunc(ProtectedHandler)),
))
log.Println("Now listening...")
http.ListenAndServe(":8000", nil)
}
func main() {
initKeys()
StartServer()
}
func ProtectedHandler(w http.ResponseWriter, r *http.Request) {
response := Response{"Gained access to protected resource"}
JsonResponse(response, w)
}
func LoginHandler(w http.ResponseWriter, r *http.Request) {
var user UserCredentials
// decode request into UserCredentials struct
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "Error in request")
return
}
fmt.Println(user.Username, user.Password)
// validate user credentials
if strings.ToLower(user.Username) != "alexcons" {
if user.Password != "kappa123" {
w.WriteHeader(http.StatusForbidden)
fmt.Println("Error logging in")
fmt.Fprint(w, "Invalid credentials")
return
}
}
// create a rsa 256 signer
signer := jwt.New(jwt.GetSigningMethod("RS256"))
// set claims
signer.Claims["iss"] = "admin"
signer.Claims["exp"] = time.Now().Add(time.Minute * 20).Unix()
signer.Claims["CustomUserInfo"] = struct {
Name string
Role string
}{user.Username, "Member"}
tokenString, err := signer.SignedString(SignKey)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Error while signing the token")
log.Printf("Error signing token: %v\n", err)
}
// create a token instance using the token string
response := Token{tokenString}
JsonResponse(response, w)
}
func ValidateTokenMiddleware(w http.ResponseWriter,
r *http.Request,
next http.HandlerFunc) {
// validate token
token, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
return VerifyKey, nil
})
if err == nil {
if token.Valid {
next(w, r)
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Token is not valid")
}
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Unauthorised access to this resource")
}
}
func JsonResponse(response interface{}, w http.ResponseWriter) {
json, err := json.Marshal(response)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write(json)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment