jwt

package module
v0.0.0-...-2176fe9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2016 License: MIT Imports: 9 Imported by: 0

README

jwt

GoDoc

A simple (bring your own logic), opinionated Go net/http middleware for integrating JSON Web Tokens into your application:

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"time"

	"github.com/thermokarst/jwt"
)

func protectMe(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "secured")
}

func dontProtectMe(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "not secured")
}

func auth(email string, password string) error {
	// Hard-code a user
	if email != "test" || password != "test" {
		return errors.New("invalid credentials")
	}
	return nil
}

func setClaims(id string) (map[string]interface{}, error) {
	currentTime := time.Now()
	return map[string]interface{}{
		"iat": currentTime.Unix(),
		"exp": currentTime.Add(time.Minute * 60 * 24).Unix(),
	}, nil
}

func verifyClaims(claims []byte, r *http.Request) error {
	currentTime := time.Now()
	var c struct {
		Iat int64
		Exp int64
	}
	_ = json.Unmarshal(claims, &c)
	if currentTime.After(time.Unix(c.Exp, 0)) {
		return errors.New("this token has expired")
	}
	return nil
}

func main() {
	config := &jwt.Config{
		Secret: "password",
		Auth:   auth,
		Claims: setClaims,
	}

	j, err := jwt.New(config)
	if err != nil {
		panic(err)
	}

	protect := http.HandlerFunc(protectMe)
	dontProtect := http.HandlerFunc(dontProtectMe)

	http.Handle("/authenticate", j.Authenticate())
	http.Handle("/secure", j.Secure(protect, verifyClaims))
	http.Handle("/insecure", dontProtect)
	http.ListenAndServe(":8080", nil)
}
$ http GET :8080/secure

    HTTP/1.1 401 Unauthorized
    Content-Length: 23
    Content-Type: text/plain; charset=utf-8
    Date: Fri, 08 May 2015 06:43:35 GMT

    please provide a token

$ http POST :8080/authenticate email=test password=test

    HTTP/1.1 200 OK
    Content-Length: 130
    Content-Type: text/plain; charset=utf-8
    Date: Fri, 08 May 2015 06:31:42 GMT

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzExNTI0ODAsImlhdCI6MTQzMTA2NjA4MH0=.UbJmLqOF4bTH/8+o6CrZfoi1Fu7zTDfCV0kwMQyzmos=

$ http GET :8080/secure Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzExNTI0ODAsImlhdCI6MTQzMTA2NjA4MH0=.UbJmLqOF4bTH/8+o6CrZfoi1Fu7zTDfCV0kwMQyzmos="

    HTTP/1.1 200 OK
    Content-Length: 7
    Content-Type: text/plain; charset=utf-8
    Date: Fri, 08 May 2015 06:38:30 GMT

    secured

Installation

$ go get github.com/thermokarst/jwt

Usage

This is a work in progress

Create a new instance of the middleware by passing in a configuration for your app. The config includes a shared secret (this middleware only builds HS256 tokens), a function for authenticating user, and a function for generating a user's claims. The idea here is to be dead-simple for someone to drop this into a project and hit the ground running.

config := &jwt.Config{
    Secret: "password",
    Auth:   authFunc, // func(string, string) error
    Claims: claimsFunc, // func(string) (map[string]interface{})
}
j, err := jwt.New(config)

You can also customize the field names by specifying IdentityField and VerifyField in the Config struct, if you want the credentials to be something other than "email" and "password".

Once the middleware is instantiated, create a route for users to generate a JWT at.

http.Handle("/authenticate", j.Authenticate())

The auth function takes two arguments (the identity, and the authorization key), POSTed as a JSON-encoded body:

{"email":"user@example.com","password":"mypassword"}

These fields are static for now, but will be customizable in a later release. The claims are generated using the claims function provided in the configuration. This function is only run if the auth function verifies the user's identity, then the user's unique identifier (primary key id, UUID, email, whatever you want) is passed as a string to the claims function. Your function should return a map[string]interface{} with the desired claimset.

Routes are "secured" by calling the Secure(http.Handler, jwt.VerifyClaimsFunc) handler:

http.Handle("/secureendpoint", j.Secure(someHandler, verifyClaimsFunc))

The claims verification function is called after the token has been parsed and validated: this is where you control how your application handles the claims contained within the JWT.

Motivation

This work was prepared for a crypto/security class at the University of Alaska Fairbanks. I hope to use this in some of my projects, but please proceed with caution if you adopt this for your own work. As well, the API is still quite unstable, so be prepared for handling any changes.

Tests

$ go test

Contributors

Matthew Ryan Dillon (matthewrdillon@gmail.com)

Documentation

Overview

Package jwt implements a simple, opinionated net/http-compatible middleware for integrating JSON Web Tokens (JWT).

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMissingConfig      = errors.New("missing configuration")
	ErrMissingSecret      = errors.New("please provide a shared secret")
	ErrMissingAuthFunc    = errors.New("please provide an auth function")
	ErrMissingClaimsFunc  = errors.New("please provide a claims function")
	ErrEncoding           = errors.New("error encoding value")
	ErrDecoding           = errors.New("error decoding value")
	ErrMissingToken       = errors.New("please provide a token")
	ErrMalformedToken     = errors.New("please provide a valid token")
	ErrInvalidSignature   = errors.New("signature could not be verified")
	ErrParsingCredentials = errors.New("error parsing credentials")
	ErrInvalidMethod      = errors.New("invalid request method")
)

Errors introduced by this package.

Functions

This section is empty.

Types

type AuthFunc

type AuthFunc func(string, string) error

AuthFunc is a type for delegating user authentication to the client-code.

type ClaimsFunc

type ClaimsFunc func(string) (map[string]interface{}, error)

ClaimsFunc is a type for delegating claims generation to the client-code.

type Config

type Config struct {
	Secret        string
	Auth          AuthFunc
	Claims        ClaimsFunc
	IdentityField string
	VerifyField   string
}

Config is a container for setting up the JWT middleware.

type Middleware

type Middleware struct {
	// contains filtered or unexported fields
}

Middleware is where we store all the specifics related to the client's JWT needs.

func New

func New(c *Config) (*Middleware, error)

New creates a new Middleware from a user-specified configuration.

func (*Middleware) Authenticate

func (m *Middleware) Authenticate() http.Handler

Authenticate returns a middleware that parsing an incoming request for a JWT, calls the client-supplied auth function, and if successful, returns a JWT to the requester.

func (*Middleware) CreateToken

func (m *Middleware) CreateToken(identity string) (string, error)

CreateToken generates a token from a user's identity

func (*Middleware) Secure

Secure wraps a client-specified http.Handler with a verification function, as well as-built in parsing of the request's JWT. This allows each handler to have it's own verification/validation protocol.

func (*Middleware) VerifyToken

func (m *Middleware) VerifyToken(token string, v VerifyClaimsFunc, r *http.Request) (int, string, error)

VerifyToken verifies a token

type VerifyClaimsFunc

type VerifyClaimsFunc func([]byte, *http.Request) error

VerifyClaimsFunc is a type for processing and validating JWT claims on one or more routes in the client-code.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL