github.com/crewjam/saml@v0.4.14/samlidp/samlidp.go (about)

     1  // Package samlidp a rudimentary SAML identity provider suitable for
     2  // testing or as a starting point for a more complex service.
     3  package samlidp
     4  
     5  import (
     6  	"crypto"
     7  	"crypto/x509"
     8  	"net/http"
     9  	"net/url"
    10  	"regexp"
    11  	"sync"
    12  
    13  	"github.com/zenazn/goji/web"
    14  
    15  	"github.com/crewjam/saml"
    16  	"github.com/crewjam/saml/logger"
    17  )
    18  
    19  // Options represent the parameters to New() for creating a new IDP server
    20  type Options struct {
    21  	URL         url.URL
    22  	Key         crypto.PrivateKey
    23  	Signer      crypto.Signer
    24  	Logger      logger.Interface
    25  	Certificate *x509.Certificate
    26  	Store       Store
    27  }
    28  
    29  // Server represents an IDP server. The server provides the following URLs:
    30  //
    31  //	/metadata     - the SAML metadata
    32  //	/sso          - the SAML endpoint to initiate an authentication flow
    33  //	/login        - prompt for a username and password if no session established
    34  //	/login/:shortcut - kick off an IDP-initiated authentication flow
    35  //	/services     - RESTful interface to Service objects
    36  //	/users        - RESTful interface to User objects
    37  //	/sessions     - RESTful interface to Session objects
    38  //	/shortcuts    - RESTful interface to Shortcut objects
    39  type Server struct {
    40  	http.Handler
    41  	idpConfigMu      sync.RWMutex // protects calls into the IDP
    42  	logger           logger.Interface
    43  	serviceProviders map[string]*saml.EntityDescriptor
    44  	IDP              saml.IdentityProvider // the underlying IDP
    45  	Store            Store                 // the data store
    46  }
    47  
    48  // New returns a new Server
    49  func New(opts Options) (*Server, error) {
    50  	metadataURL := opts.URL
    51  	metadataURL.Path += "/metadata"
    52  	ssoURL := opts.URL
    53  	ssoURL.Path += "/sso"
    54  	logr := opts.Logger
    55  	if logr == nil {
    56  		logr = logger.DefaultLogger
    57  	}
    58  
    59  	s := &Server{
    60  		serviceProviders: map[string]*saml.EntityDescriptor{},
    61  		IDP: saml.IdentityProvider{
    62  			Key:         opts.Key,
    63  			Signer:      opts.Signer,
    64  			Logger:      logr,
    65  			Certificate: opts.Certificate,
    66  			MetadataURL: metadataURL,
    67  			SSOURL:      ssoURL,
    68  		},
    69  		logger: logr,
    70  		Store:  opts.Store,
    71  	}
    72  
    73  	s.IDP.SessionProvider = s
    74  	s.IDP.ServiceProviderProvider = s
    75  
    76  	if err := s.initializeServices(); err != nil {
    77  		return nil, err
    78  	}
    79  	s.InitializeHTTP()
    80  	return s, nil
    81  }
    82  
    83  // InitializeHTTP sets up the HTTP handler for the server. (This function
    84  // is called automatically for you by New, but you may need to call it
    85  // yourself if you don't create the object using New.)
    86  func (s *Server) InitializeHTTP() {
    87  	mux := web.New()
    88  	s.Handler = mux
    89  
    90  	mux.Get("/metadata", func(w http.ResponseWriter, r *http.Request) {
    91  		s.idpConfigMu.RLock()
    92  		defer s.idpConfigMu.RUnlock()
    93  		s.IDP.ServeMetadata(w, r)
    94  	})
    95  	mux.Handle("/sso", func(w http.ResponseWriter, r *http.Request) {
    96  		s.idpConfigMu.RLock()
    97  		defer s.idpConfigMu.RUnlock()
    98  		s.IDP.ServeSSO(w, r)
    99  	})
   100  
   101  	mux.Handle("/login", s.HandleLogin)
   102  	mux.Handle("/login/:shortcut", s.HandleIDPInitiated)
   103  	mux.Handle("/login/:shortcut/*", s.HandleIDPInitiated)
   104  
   105  	mux.Get("/services/", s.HandleListServices)
   106  	mux.Get("/services/:id", s.HandleGetService)
   107  	mux.Put("/services/:id", s.HandlePutService)
   108  	mux.Post("/services/:id", s.HandlePutService)
   109  	mux.Delete("/services/:id", s.HandleDeleteService)
   110  
   111  	mux.Get("/users/", s.HandleListUsers)
   112  	mux.Get("/users/:id", s.HandleGetUser)
   113  	mux.Put("/users/:id", s.HandlePutUser)
   114  	mux.Delete("/users/:id", s.HandleDeleteUser)
   115  
   116  	sessionPath := regexp.MustCompile("/sessions/(?P<id>.*)")
   117  	mux.Get("/sessions/", s.HandleListSessions)
   118  	mux.Get(sessionPath, s.HandleGetSession)
   119  	mux.Delete(sessionPath, s.HandleDeleteSession)
   120  
   121  	mux.Get("/shortcuts/", s.HandleListShortcuts)
   122  	mux.Get("/shortcuts/:id", s.HandleGetShortcut)
   123  	mux.Put("/shortcuts/:id", s.HandlePutShortcut)
   124  	mux.Delete("/shortcuts/:id", s.HandleDeleteShortcut)
   125  }