File: auth.go

package info (click to toggle)
golang-github-abbot-go-http-auth 0.4.0-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 152 kB
  • sloc: makefile: 13
file content (109 lines) | stat: -rw-r--r-- 3,160 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Package auth is an implementation of HTTP Basic and HTTP Digest authentication.
package auth

import (
	"net/http"

	"golang.org/x/net/context"
)

/*
 Request handlers must take AuthenticatedRequest instead of http.Request
*/
type AuthenticatedRequest struct {
	http.Request
	/*
	 Authenticated user name. Current API implies that Username is
	 never empty, which means that authentication is always done
	 before calling the request handler.
	*/
	Username string
}

/*
 AuthenticatedHandlerFunc is like http.HandlerFunc, but takes
 AuthenticatedRequest instead of http.Request
*/
type AuthenticatedHandlerFunc func(http.ResponseWriter, *AuthenticatedRequest)

/*
 Authenticator wraps an AuthenticatedHandlerFunc with
 authentication-checking code.

 Typical Authenticator usage is something like:

   authenticator := SomeAuthenticator(...)
   http.HandleFunc("/", authenticator(my_handler))

 Authenticator wrapper checks the user authentication and calls the
 wrapped function only after authentication has succeeded. Otherwise,
 it returns a handler which initiates the authentication procedure.
*/
type Authenticator func(AuthenticatedHandlerFunc) http.HandlerFunc

// Info contains authentication information for the request.
type Info struct {
	// Authenticated is set to true when request was authenticated
	// successfully, i.e. username and password passed in request did
	// pass the check.
	Authenticated bool

	// Username contains a user name passed in the request when
	// Authenticated is true. It's value is undefined if Authenticated
	// is false.
	Username string

	// ResponseHeaders contains extra headers that must be set by server
	// when sending back HTTP response.
	ResponseHeaders http.Header
}

// UpdateHeaders updates headers with this Info's ResponseHeaders. It is
// safe to call this function on nil Info.
func (i *Info) UpdateHeaders(headers http.Header) {
	if i == nil {
		return
	}
	for k, values := range i.ResponseHeaders {
		for _, v := range values {
			headers.Add(k, v)
		}
	}
}

type key int // used for context keys

var infoKey key = 0

type AuthenticatorInterface interface {
	// NewContext returns a new context carrying authentication
	// information extracted from the request.
	NewContext(ctx context.Context, r *http.Request) context.Context

	// Wrap returns an http.HandlerFunc which wraps
	// AuthenticatedHandlerFunc with this authenticator's
	// authentication checks.
	Wrap(AuthenticatedHandlerFunc) http.HandlerFunc
}

// FromContext returns authentication information from the context or
// nil if no such information present.
func FromContext(ctx context.Context) *Info {
	info, ok := ctx.Value(infoKey).(*Info)
	if !ok {
		return nil
	}
	return info
}

// AuthUsernameHeader is the header set by JustCheck functions. It
// contains an authenticated username (if authentication was
// successful).
const AuthUsernameHeader = "X-Authenticated-Username"

func JustCheck(auth AuthenticatorInterface, wrapped http.HandlerFunc) http.HandlerFunc {
	return auth.Wrap(func(w http.ResponseWriter, ar *AuthenticatedRequest) {
		ar.Header.Set(AuthUsernameHeader, ar.Username)
		wrapped(w, &ar.Request)
	})
}