Browse Source

http handler wrapper for kerberos SPNEGO

Jonathan Turner 9 years ago
parent
commit
2b042e70fc
3 changed files with 25 additions and 7 deletions
  1. 17 0
      README.md
  2. 7 4
      debug.go
  3. 1 3
      service/http.go

+ 17 - 0
README.md

@@ -71,6 +71,23 @@ cl.SetSPNEGOHeader(r)
 HTTPResp, err := http.DefaultClient.Do(r)
 HTTPResp, err := http.DefaultClient.Do(r)
 ```
 ```
 
 
+### Kerberos Web Service
+A HTTP handler wrapper can be used to implement Kerberos SPNEGO authentication for web services.
+To configure the wrapper the keytab of for the service SPN and a Logger are required:
+```go
+kt, err := keytab.Load("/path/to/file.keytab")
+l := log.New(os.Stderr, "GOKRB5 Service: ", log.Ldate|log.Ltime|log.Lshortfile)
+```
+Create a handler function of the application's handling method (apphandler in the example below):
+```go
+h := http.HandlerFunc(apphandler)
+```
+Configure the HTTP handler:
+```go
+http.Handler("/", service.SPNEGOKRB5Authenticate(h, kt, l))
+```
+
+
 ## References
 ## References
 ### RFCs
 ### RFCs
 * RFC 4120 The Kerberos Network Authentication Service (V5)
 * RFC 4120 The Kerberos Network Authentication Service (V5)

+ 7 - 4
debug.go

@@ -69,6 +69,7 @@ func runClient() {
 }
 }
 
 
 func httpRequest(url string) {
 func httpRequest(url string) {
+	l := log.New(os.Stderr, "GOKRB5 Client: ", log.Ldate|log.Ltime|log.Lshortfile)
 	b, err := hex.DecodeString(testdata.TESTUSER1_KEYTAB)
 	b, err := hex.DecodeString(testdata.TESTUSER1_KEYTAB)
 	kt, _ := keytab.Parse(b)
 	kt, _ := keytab.Parse(b)
 	c, _ := config.NewConfigFromString(krb5conf)
 	c, _ := config.NewConfigFromString(krb5conf)
@@ -77,22 +78,24 @@ func httpRequest(url string) {
 
 
 	err = cl.Login()
 	err = cl.Login()
 	if err != nil {
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "Error on AS_REQ: %v\n", err)
+		l.Printf("Error on AS_REQ: %v\n", err)
 	}
 	}
 	r, _ := http.NewRequest("GET", url, nil)
 	r, _ := http.NewRequest("GET", url, nil)
 	err = cl.SetSPNEGOHeader(r, "HTTP/host.test.gokrb5")
 	err = cl.SetSPNEGOHeader(r, "HTTP/host.test.gokrb5")
 	if err != nil {
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "Error setting client SPNEGO header: %v", err)
+		l.Printf("Error setting client SPNEGO header: %v", err)
 	}
 	}
 	httpResp, err := http.DefaultClient.Do(r)
 	httpResp, err := http.DefaultClient.Do(r)
-	fmt.Fprintf(os.Stderr, "Request error: %v\n", err)
+	if err != nil {
+		l.Printf("Request error: %v\n", err)
+	}
 	fmt.Fprintf(os.Stdout, "RESPONSE CODE: %v\n", httpResp.StatusCode)
 	fmt.Fprintf(os.Stdout, "RESPONSE CODE: %v\n", httpResp.StatusCode)
 	content, _ := ioutil.ReadAll(httpResp.Body)
 	content, _ := ioutil.ReadAll(httpResp.Body)
 	fmt.Fprintf(os.Stdout, "ResponseBody: %s\n", content)
 	fmt.Fprintf(os.Stdout, "ResponseBody: %s\n", content)
 }
 }
 
 
 func httpServer(tls bool) *httptest.Server {
 func httpServer(tls bool) *httptest.Server {
-	l := log.New(os.Stderr, "GOKRB5: ", log.Ldate|log.Ltime|log.Lshortfile)
+	l := log.New(os.Stderr, "GOKRB5 Service: ", log.Ldate|log.Ltime|log.Lshortfile)
 	ks := "0502000000580002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300120020c2bcd4abcde0d2608d5f505e7ab5dc92df5f627e5819703c0b0f1d2c05d51c1600000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300110010da152175c7a73f49e5ce4ece7068856400000003000000500002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603001000187fc8ef5276e083da6bf89e676d7f98fd1acb9ec2cb20083d00000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300170010011f2ef8e75e8378a94154beb002163200000003000000580002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603001a0020f9db4e36aad9688d9ea30dbcc269c7ee46bf4f8bd6250f203a9f3836f0a673a600000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300190010434981c9dce61ae1012f808bb60fc1c900000003000000400002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603000800080b0d4f31e061529800000003000000400002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300030008f7df40f457aec42c00000003"
 	ks := "0502000000580002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300120020c2bcd4abcde0d2608d5f505e7ab5dc92df5f627e5819703c0b0f1d2c05d51c1600000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300110010da152175c7a73f49e5ce4ece7068856400000003000000500002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603001000187fc8ef5276e083da6bf89e676d7f98fd1acb9ec2cb20083d00000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300170010011f2ef8e75e8378a94154beb002163200000003000000580002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603001a0020f9db4e36aad9688d9ea30dbcc269c7ee46bf4f8bd6250f203a9f3836f0a673a600000003000000480002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300190010434981c9dce61ae1012f808bb60fc1c900000003000000400002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d03603000800080b0d4f31e061529800000003000000400002000b544553542e474f4b5242350004485454500010686f73742e746573742e676f6b7262350000000158e7d0360300030008f7df40f457aec42c00000003"
 	b, _ := hex.DecodeString(ks)
 	b, _ := hex.DecodeString(ks)
 	kt, _ := keytab.Parse(b)
 	kt, _ := keytab.Parse(b)

+ 1 - 3
service/http.go

@@ -13,7 +13,6 @@ import (
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/jcmturner/gokrb5/types"
 	"log"
 	"log"
 	"net/http"
 	"net/http"
-	"os"
 	"strings"
 	"strings"
 	"time"
 	"time"
 )
 )
@@ -82,10 +81,9 @@ func SPNEGOKRB5Authenticate(f http.Handler, ktab keytab.Keytab, l *log.Logger) h
 			ctx = context.WithValue(ctx, "crealm", a.CRealm)
 			ctx = context.WithValue(ctx, "crealm", a.CRealm)
 			ctx = context.WithValue(ctx, "authenticated", true)
 			ctx = context.WithValue(ctx, "authenticated", true)
 			if l != nil {
 			if l != nil {
-				l.Printf("SPNEGO authentication succeeded: %v %s@%s", r.RemoteAddr, cnameStr, a.CRealm)
+				l.Printf("%v %s@%s - SPNEGO authentication succeeded", r.RemoteAddr, cnameStr, a.CRealm)
 			}
 			}
 			w.Header().Set("WWW-Authenticate", SPNEGO_NegTokenResp_Krb_Accept_Completed)
 			w.Header().Set("WWW-Authenticate", SPNEGO_NegTokenResp_Krb_Accept_Completed)
-			fmt.Fprintln(os.Stderr, "AUTHED")
 			f.ServeHTTP(w, r.WithContext(ctx))
 			f.ServeHTTP(w, r.WithContext(ctx))
 		} else {
 		} else {
 			rejectSPNEGO(w, l, fmt.Sprintf("%v - SPNEGO Kerberos authentication failed: %v", r.RemoteAddr, err))
 			rejectSPNEGO(w, l, fmt.Sprintf("%v - SPNEGO Kerberos authentication failed: %v", r.RemoteAddr, err))