Skip to content

Instantly share code, notes, and snippets.

@JohnProg
Forked from thealexcons/jwt_golang_example.go
Created December 30, 2016 17:17
Show Gist options
  • Select an option

  • Save JohnProg/887d5e6c99eaf0b11c2a596ef74d9b99 to your computer and use it in GitHub Desktop.

Select an option

Save JohnProg/887d5e6c99eaf0b11c2a596ef74d9b99 to your computer and use it in GitHub Desktop.

Revisions

  1. @thealexcons thealexcons created this gist Apr 9, 2016.
    205 changes: 205 additions & 0 deletions jwt_golang_example.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,205 @@
    package main

    import (
    "io/ioutil"
    "log"
    "strings"
    "net/http"
    "encoding/json"
    "fmt"
    "time"

    "github.com/codegangsta/negroni"
    "github.com/dgrijalva/jwt-go"
    "os"
    )


    //RSA KEYS AND INITIALISATION


    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
    }
    }



    //STRUCT DEFINITIONS


    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"`
    }



    //SERVER ENTRY POINT


    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()
    }


    //////////////////////////////////////////


    /////////////ENDPOINT HANDLERS////////////


    /////////////////////////////////////////


    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)

    }



    //AUTH TOKEN VALIDATION


    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")
    }

    }



    //HELPER FUNCTIONS


    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)
    }