authmid

package module
v0.0.0-...-1cc8435 Latest Latest
Warning

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

Go to latest
Published: Dec 28, 2017 License: Apache-2.0 Imports: 8 Imported by: 3

README

authmid

Authentication middleware for signed requests, useful for webhook authentication verifying identities

Usage

Create your custom authenticator that conforms to interface Authenticator so that you can custom lookup the secret, and headers and pass that into Middleware to wrap the next handler. For example, simply:

func main() {
	http.Handle("/", authmid.Middleware(&sampleAuthChecker{}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Authenticated pong!")
	})))

	// Then run the server to receive traffic.
}

Or for a more comprehensive end to end working example:

func main() {
	srv := httptest.NewServer(authmid.Middleware(&sampleAuthChecker{}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, _ := ioutil.ReadAll(r.Body)
		fmt.Fprintf(w, "Well authenticated, and here is your body: %s", body)
	})))
	defer srv.Close()

	// The client will then authenticate like this
	req := makeReq("POST", []byte(`{"name": "foo", "age": 99}`), authKey1)
	req.URL, _ = url.Parse(srv.URL)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	blob, _ := ioutil.ReadAll(res.Body)
	fmt.Printf("response: %s\n", blob)
}

Documentation

Overview

Example (BackendForAuthentication)
package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/orijtech/authmid"
	"github.com/orijtech/authmid/backend/redis"
)

func main() {
	backend, err := redis.New("keys", "redis://localhost:6379")
	if err != nil {
		log.Fatal(err)
	}

	ac := &apiChecker{
		backend: backend,
		next: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprintf(w, "Authenticated pong!")
		}),
		hdrKey: "DEMO-ACCESS-APIKEY",
	}
	http.Handle("/ping", ac)

	http.HandleFunc("/reg", func(w http.ResponseWriter, r *http.Request) {
		qv := r.URL.Query()
		key, secret := qv.Get("key"), qv.Get("secret")
		if err := backend.UpsertSecret(key, secret); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	})

	addr := ":8777"
	log.Printf("Serving on: %s", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatal(err)
	}
}

type apiChecker struct {
	backend authmid.Backend
	next    http.Handler
	hdrKey  string
}

func (ac *apiChecker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	apiKey := r.Header.Get(ac.hdrKey)
	if strings.TrimSpace(apiKey) == "" {
		http.Error(w, "expecting a non-blank API Key", http.StatusBadRequest)
		return
	}
	secret, err := ac.backend.LookupSecret(apiKey)
	if err != nil {
		log.Printf("looking up secret: err: %v", err)
		http.Error(w, "failed to lookup the secret", http.StatusBadRequest)
		return
	}
	log.Printf("secret: %s\n", secret)
	ac.next.ServeHTTP(w, r)
}
Example (InPlainServer)
http.Handle("/", authmid.Middleware(&sampleAuthChecker{}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Authenticated pong!")
})))
Example (Middleware)
srv := httptest.NewServer(authmid.Middleware(&sampleAuthChecker{}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	fmt.Fprintf(w, "Well authenticated, and here is your body: %s", body)
})))
defer srv.Close()

// The client will then authenticate like this
req := makeReq("POST", []byte(`{"name": "foo", "age": 99}`), authKey1)
req.URL, _ = url.Parse(srv.URL)
res, err := http.DefaultClient.Do(req)
if err != nil {
	log.Fatal(err)
}
defer res.Body.Close()
blob, _ := ioutil.ReadAll(res.Body)
fmt.Printf("response: %s\n", blob)

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNoSuchAPIKey      = errors.New("no such apiKey found")
	ErrEmptyTableName    = errors.New("expecting a non-empty table name")
	ErrSignatureMismatch = errors.New("invalid/mismatched signatures")
)

Functions

func Checker

func Checker(vf Authenticator) func(*http.Request) error

func Middleware

func Middleware(vf Authenticator, next http.Handler) http.Handler

Types

type Authenticator

type Authenticator interface {
	ReadOnlyBackend
	HTTPAuthMiddleware
}

type Backend

type Backend interface {
	ReadOnlyBackend
	WriteBackend
	Close() error
}

type CodedError

type CodedError interface {
	Error() string
	Code() int
}

type ExcludeMethodAndPather

type ExcludeMethodAndPather interface {
	ExcludeMethodAndPath() bool
}

type HTTPAuthMiddleware

type HTTPAuthMiddleware interface {
	HeaderValues(hdr http.Header) (values, warnings []string, err error)
	LookupAPIKey(hdr http.Header) (string, error)
	Signature(hdr http.Header) (string, error)
}

type ReadOnlyBackend

type ReadOnlyBackend interface {
	LookupSecret(apiKey string) ([]byte, error)
}

type WriteBackend

type WriteBackend interface {
	UpsertSecret(apiKey, apiSecret string) error
	DeleteAPIKey(apiKey string) error
}

Directories

Path Synopsis
backend

Jump to

Keyboard shortcuts

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