github.com/jcmturner/gokrb5/v8@v8.4.4/examples/httpServer.go (about)

     1  //go:build examples
     2  // +build examples
     3  
     4  package main
     5  
     6  import (
     7  	"encoding/hex"
     8  	"errors"
     9  	"fmt"
    10  	"log"
    11  	"net/http"
    12  	"os"
    13  
    14  	"github.com/gorilla/sessions"
    15  	"github.com/jcmturner/goidentity/v6"
    16  	"github.com/jcmturner/gokrb5/v8/keytab"
    17  	"github.com/jcmturner/gokrb5/v8/service"
    18  	"github.com/jcmturner/gokrb5/v8/spnego"
    19  	"github.com/jcmturner/gokrb5/v8/test/testdata"
    20  )
    21  
    22  const (
    23  	port = ":9080"
    24  )
    25  
    26  func main() {
    27  	//defer profile.Start(profile.TraceProfile).Stop()
    28  	// Create logger
    29  	l := log.New(os.Stderr, "GOKRB5 Service: ", log.Ldate|log.Ltime|log.Lshortfile)
    30  
    31  	// Load the service's keytab
    32  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
    33  	kt := keytab.New()
    34  	kt.Unmarshal(b)
    35  
    36  	// Create the application's specific handler
    37  	th := http.HandlerFunc(testAppHandler)
    38  
    39  	// Set up handler mappings wrapping in the SPNEGOKRB5Authenticate handler wrapper
    40  	mux := http.NewServeMux()
    41  	mux.Handle("/", spnego.SPNEGOKRB5Authenticate(th, kt, service.Logger(l), service.SessionManager(NewSessionMgr("gokrb5"))))
    42  
    43  	// Start up the web server
    44  	log.Fatal(http.ListenAndServe(port, mux))
    45  }
    46  
    47  // Simple application specific handler
    48  func testAppHandler(w http.ResponseWriter, r *http.Request) {
    49  	w.WriteHeader(http.StatusOK)
    50  	creds := goidentity.FromHTTPRequestContext(r)
    51  	fmt.Fprintf(w,
    52  		`<html>
    53  <h1>GOKRB5 Handler</h1>
    54  <ul>
    55  <li>Authenticed user: %s</li>
    56  <li>User's realm: %s</li>
    57  <li>Authn time: %v</li>
    58  <li>Session ID: %s</li>
    59  <ul>
    60  </html>`,
    61  		creds.UserName(),
    62  		creds.Domain(),
    63  		creds.AuthTime(),
    64  		creds.SessionID(),
    65  	)
    66  	return
    67  }
    68  
    69  type SessionMgr struct {
    70  	skey       []byte
    71  	store      sessions.Store
    72  	cookieName string
    73  }
    74  
    75  func NewSessionMgr(cookieName string) SessionMgr {
    76  	skey := []byte("thisistestsecret") // Best practice is to load this key from a secure location.
    77  	return SessionMgr{
    78  		skey:       skey,
    79  		store:      sessions.NewCookieStore(skey),
    80  		cookieName: cookieName,
    81  	}
    82  }
    83  
    84  func (smgr SessionMgr) Get(r *http.Request, k string) ([]byte, error) {
    85  	s, err := smgr.store.Get(r, smgr.cookieName)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	if s == nil {
    90  		return nil, errors.New("nil session")
    91  	}
    92  	b, ok := s.Values[k].([]byte)
    93  	if !ok {
    94  		return nil, fmt.Errorf("could not get bytes held in session at %s", k)
    95  	}
    96  	return b, nil
    97  }
    98  
    99  func (smgr SessionMgr) New(w http.ResponseWriter, r *http.Request, k string, v []byte) error {
   100  	s, err := smgr.store.New(r, smgr.cookieName)
   101  	if err != nil {
   102  		return fmt.Errorf("could not get new session from session manager: %v", err)
   103  	}
   104  	s.Values[k] = v
   105  	return s.Save(r, w)
   106  }