mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									82cbd7a96b
								
							
						
					
					
						commit
						977a3c3226
					
				@ -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
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			// 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 (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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) {
 | 
				
			|||||||
		{"/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]
 | 
				
			|||||||
		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]
 | 
				
			|||||||
		"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,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user