Commit 977a3c32 authored by Kurt Jung's avatar Kurt Jung Committed by Matt Holt

basicauth: Store name of authenticated user (#1426)

* Store name of authenticated user in basicauth for use by upstream middleware such as fastcgi and cgi.

* Use request context to transfer name of authorized user from basicauth to upstream middleware. Test retrieval of name from context.

* Remove development code that was inadvertently left in place

* Use keys of type httpserver.CtxKey to access Context values
parent 82cbd7a9
...@@ -7,6 +7,7 @@ package basicauth ...@@ -7,6 +7,7 @@ package basicauth
import ( import (
"bufio" "bufio"
"context"
"crypto/sha1" "crypto/sha1"
"crypto/subtle" "crypto/subtle"
"fmt" "fmt"
...@@ -60,6 +61,11 @@ func (a BasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error ...@@ -60,6 +61,11 @@ func (a BasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
// remove credentials from request to avoid leaking upstream // remove credentials from request to avoid leaking upstream
r.Header.Del("Authorization") r.Header.Del("Authorization")
// let upstream middleware (e.g. fastcgi and cgi) know about authenticated
// user; this replaces the request with a wrapped instance
r = r.WithContext(context.WithValue(r.Context(),
httpserver.CtxKey("remote_user"), username))
} }
} }
......
...@@ -14,19 +14,31 @@ import ( ...@@ -14,19 +14,31 @@ import (
) )
func TestBasicAuth(t *testing.T) { func TestBasicAuth(t *testing.T) {
var i int
// This handler is registered for tests in which the only authorized user is
// "okuser"
upstreamHandler := func(w http.ResponseWriter, r *http.Request) (int, error) {
remoteUser, _ := r.Context().Value(httpserver.CtxKey("remote_user")).(string)
if remoteUser != "okuser" {
t.Errorf("Test %d: expecting remote user 'okuser', got '%s'", i, remoteUser)
}
return http.StatusOK, nil
}
rw := BasicAuth{ rw := BasicAuth{
Next: httpserver.HandlerFunc(contentHandler), Next: httpserver.HandlerFunc(upstreamHandler),
Rules: []Rule{ Rules: []Rule{
{Username: "okuser", Password: PlainMatcher("okpass"), Resources: []string{"/testing"}}, {Username: "okuser", Password: PlainMatcher("okpass"), Resources: []string{"/testing"}},
}, },
} }
tests := []struct { type testType struct {
from string from string
result int result int
user string user string
password string password string
}{ }
tests := []testType{
{"/testing", http.StatusOK, "okuser", "okpass"}, {"/testing", http.StatusOK, "okuser", "okpass"},
{"/testing", http.StatusUnauthorized, "baduser", "okpass"}, {"/testing", http.StatusUnauthorized, "baduser", "okpass"},
{"/testing", http.StatusUnauthorized, "okuser", "badpass"}, {"/testing", http.StatusUnauthorized, "okuser", "badpass"},
...@@ -37,7 +49,8 @@ func TestBasicAuth(t *testing.T) { ...@@ -37,7 +49,8 @@ func TestBasicAuth(t *testing.T) {
{"/testing", http.StatusUnauthorized, "", ""}, {"/testing", http.StatusUnauthorized, "", ""},
} }
for i, test := range tests { var test testType
for i, test = range tests {
req, err := http.NewRequest("GET", test.from, nil) req, err := http.NewRequest("GET", test.from, nil)
if err != nil { if err != nil {
t.Fatalf("Test %d: Could not create HTTP request: %v", i, err) t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
......
...@@ -220,6 +220,10 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string] ...@@ -220,6 +220,10 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
reqURI = origURI reqURI = origURI
} }
// Retrieve name of remote user that was set by some downstream middleware,
// possibly basicauth.
remoteUser, _ := r.Context().Value(httpserver.CtxKey("remote_user")).(string) // Blank if not set
// Some variables are unused but cleared explicitly to prevent // Some variables are unused but cleared explicitly to prevent
// the parent environment from interfering. // the parent environment from interfering.
env = map[string]string{ env = map[string]string{
...@@ -235,7 +239,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string] ...@@ -235,7 +239,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
"REMOTE_HOST": ip, // For speed, remote host lookups disabled "REMOTE_HOST": ip, // For speed, remote host lookups disabled
"REMOTE_PORT": port, "REMOTE_PORT": port,
"REMOTE_IDENT": "", // Not used "REMOTE_IDENT": "", // Not used
"REMOTE_USER": "", // Not used "REMOTE_USER": remoteUser,
"REQUEST_METHOD": r.Method, "REQUEST_METHOD": r.Method,
"SERVER_NAME": h.ServerName, "SERVER_NAME": h.ServerName,
"SERVER_PORT": h.ServerPort, "SERVER_PORT": h.ServerPort,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment