Documentation ¶
Overview ¶
Package samlidp a rudimentary SAML identity provider suitable for testing or as a starting point for a more complex service.
Index ¶
- Constants
- Variables
- func ContextGetSubPath(ctx context.Context) (sub string)
- func ServiceProviderParseMetadata(bytes []byte) (spMetadata *saml.EntityDescriptor, err error)
- func ServiceProviderParseMetadataR(r io.Reader) (spMetadata *saml.EntityDescriptor, err error)
- func WithLoginFormHandler(req *saml.IdpAuthnRequest, cb ...func(next LoginFormHandler) LoginFormHandler)
- func WithSessionCreationHandler(req *saml.IdpAuthnRequest, ...)
- type HttpHandlers
- type LoginFormData
- type LoginFormDataInputOptions
- type LoginFormHandler
- type LoginFormHandlerFunc
- type MemoryStore
- type MultipleSessionCreationHandlers
- type MuxFuncHandler
- type Options
- type Server
- func (s *Server) GetServiceProvider(req *saml.IdpAuthnRequest, serviceProviderID string) (saml.IDPServiceProvider, error)
- func (s *Server) GetSession(w http.ResponseWriter, req *saml.IdpAuthnRequest) (session *saml.Session)
- func (s *Server) HTTPLoginHandle(w http.ResponseWriter, r *http.Request)
- func (s *Server) HTTPMetadataHandle(w http.ResponseWriter, r *http.Request)
- func (s *Server) HTTPSSOHandle(w http.ResponseWriter, r *http.Request)
- func (s *Server) HandleDeleteShortcut(c web.C, w http.ResponseWriter, r *http.Request)
- func (s *Server) HandleGetShortcut(c web.C, w http.ResponseWriter, r *http.Request)
- func (s *Server) HandleIDPInitiated(c web.C, w http.ResponseWriter, r *http.Request)
- func (s *Server) HandleListShortcuts(c web.C, w http.ResponseWriter, r *http.Request)
- func (s *Server) HandlePutShortcut(c web.C, w http.ResponseWriter, r *http.Request)
- func (s *Server) HttpHandler() http.Handler
- func (s *Server) Mount(...)
- type Service
- type ServicesProvider
- type ServicesProviders
- type SessionCreationHandler
- type SessionCreationHandlerFunc
- type SessionsStorer
- type Shortcut
- type Store
- type User
- type UsersServiceProvider
Constants ¶
const ( LoginFormUserOptions contextKey = iota SubPath )
const ( KeySessionCreationHandler key = iota KeyLoginFormCallback )
Variables ¶
var DefaultLoginFormDataInputOptions = LoginFormDataInputOptions{
PasswordLabel: "Password",
PasswordPlaceholder: "your password",
UserPlaceholder: "your user name",
UserLabel: "User",
UserInputType: "text",
SubmitLabel: "Log In",
}
var DefaultLoginFormHandler = LoginFormHandlerFunc(func(w http.ResponseWriter, req *saml.IdpAuthnRequest, err error) { tmpl := template.Must(template.New("saml-post-form").Parse(`` + `<html>` + `<p>{{.Toast}}</p>` + `<form method="post" action="{{.URL}}">` + `{{.UserLabel}}: <input type="{{.UserInputType}}" name="user" placeholder="{{.UserPlaceholder}}" value="" /><br />` + `{{.PasswordLabel}}: <input type="password" name="password" placeholder="{{.PasswordPlaceholder}}" value="" /><br />` + `<input type="hidden" name="SAMLRequest" value="{{.SAMLRequest}}" />` + `<input type="hidden" name="RelayState" value="{{.RelayState}}" />` + `<input type="submit" value="{{.SubmitLabel}}" />` + `</form>` + `</html>`)) data := NewLoginFormData(req, err) if err := tmpl.Execute(w, data); err != nil { panic(err) } })
var ErrInvalidUserOrPassword = errors.New("Invalid user or password")
var ErrNotFound = errors.New("not found")
ErrNotFound is returned from Store.Get() when a stored item is not present
var ErrServiceProviderNotFound = errors.New("service provider not found")
Functions ¶
func ContextGetSubPath ¶
func ServiceProviderParseMetadata ¶
func ServiceProviderParseMetadata(bytes []byte) (spMetadata *saml.EntityDescriptor, err error)
func ServiceProviderParseMetadataR ¶
func ServiceProviderParseMetadataR(r io.Reader) (spMetadata *saml.EntityDescriptor, err error)
func WithLoginFormHandler ¶
func WithLoginFormHandler(req *saml.IdpAuthnRequest, cb ...func(next LoginFormHandler) LoginFormHandler)
func WithSessionCreationHandler ¶
func WithSessionCreationHandler(req *saml.IdpAuthnRequest, handler ...func(next SessionCreationHandler) SessionCreationHandler)
Types ¶
type HttpHandlers ¶
type LoginFormData ¶
type LoginFormData struct { Req *saml.IdpAuthnRequest Toast, URL, SAMLRequest, RelayState string LoginFormDataInputOptions }
func NewLoginFormData ¶
func NewLoginFormData(req *saml.IdpAuthnRequest, err error, inputOptions ...*LoginFormDataInputOptions) *LoginFormData
type LoginFormDataInputOptions ¶
type LoginFormDataInputOptions struct { UserInputType, UserLabel, UserPlaceholder, PasswordLabel, PasswordPlaceholder, SubmitLabel string }
func ContextGetLoginFormDataInputOptions ¶
func ContextGetLoginFormDataInputOptions(ctx context.Context) (opts *LoginFormDataInputOptions)
func ContextGetOrSetLoginFormDataInputOptions ¶
func ContextGetOrSetLoginFormDataInputOptions(ctx context.Context) (c context.Context, opts *LoginFormDataInputOptions)
func (LoginFormDataInputOptions) Copy ¶
func (this LoginFormDataInputOptions) Copy(opt ...*LoginFormDataInputOptions) *LoginFormDataInputOptions
func (*LoginFormDataInputOptions) Merge ¶
func (this *LoginFormDataInputOptions) Merge(opt ...*LoginFormDataInputOptions) *LoginFormDataInputOptions
type LoginFormHandler ¶
type LoginFormHandler interface {
Handle(w http.ResponseWriter, req *saml.IdpAuthnRequest, err error)
}
LoginFormHandler is a login form handler ware produces a form which requests a username and password and directs the user back to the IDP authorize URL to restart the SAML login flow, this time establishing a session based on the credentials that were provided.
func GetLoginFormHandler ¶
func GetLoginFormHandler(req *saml.IdpAuthnRequest) LoginFormHandler
type LoginFormHandlerFunc ¶
type LoginFormHandlerFunc func(w http.ResponseWriter, req *saml.IdpAuthnRequest, err error)
func (LoginFormHandlerFunc) Handle ¶
func (h LoginFormHandlerFunc) Handle(w http.ResponseWriter, req *saml.IdpAuthnRequest, err error)
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is an implementation of Store that resides completely in memory.
func (*MemoryStore) Get ¶
func (s *MemoryStore) Get(key string, value interface{}) error
Get fetches the data stored in `key` and unmarshals it into `value`.
func (*MemoryStore) List ¶
func (s *MemoryStore) List(prefix string) ([]string, error)
List returns all the keys that start with `prefix`. The prefix is stripped from each returned value. So if keys are ["aa", "ab", "cd"] then List("a") would produce []string{"a", "b"}
func (*MemoryStore) Put ¶
func (s *MemoryStore) Put(key string, value interface{}) error
Put marshals `value` and stores it in `key`.
type MultipleSessionCreationHandlers ¶
type MultipleSessionCreationHandlers []SessionCreationHandler
func (MultipleSessionCreationHandlers) Handle ¶
func (handlers MultipleSessionCreationHandlers) Handle(req *saml.IdpAuthnRequest, user User, session *saml.Session) (*saml.Session, error)
func (*MultipleSessionCreationHandlers) Use ¶
func (handlers *MultipleSessionCreationHandlers) Use(h ...SessionCreationHandler) MultipleSessionCreationHandlers
type MuxFuncHandler ¶
type MuxFuncHandler interface { }
type Options ¶
type Options struct { URL func(idp *saml.IdentityProvider, r *http.Request, pth ...string) *url.URL Key crypto.PrivateKey Logger logger.Interface Certificate *x509.Certificate Store Store Users UsersServiceProvider Sessions SessionsStorer Services ServicesProvider SessionCreationHandlers MultipleSessionCreationHandlers LoginFormHandler LoginFormHandler Setup func(srv *Server) }
Options represent the parameters to New() for creating a new IDP server
type Server ¶
type Server struct { http.Handler IDP *saml.IdentityProvider // the underlying IDP Store Store // the data store Users UsersServiceProvider SessionCreationHandlers MultipleSessionCreationHandlers Sessions SessionsStorer LoginFormHandler LoginFormHandler Services ServicesProvider // contains filtered or unexported fields }
Server represents an IDP server. The server provides the following URLs:
/metadata - the SAML metadata /sso - the SAML endpoint to initiate an authentication flow /login - prompt for a username and password if no session established /login/:shortcut - kick off an IDP-initiated authentication flow /services - RESTful interface to Service objects /users - RESTful interface to UserImpl objects /sessions - RESTful interface to Session objects /shortcuts - RESTful interface to Shortcut objects
func (*Server) GetServiceProvider ¶
func (s *Server) GetServiceProvider(req *saml.IdpAuthnRequest, serviceProviderID string) (saml.IDPServiceProvider, error)
GetServiceProvider returns the Service Provider metadata for the service provider ID, which is typically the service provider's metadata URL. If an appropriate service provider cannot be found then the returned error must be os.ErrNotExist.
func (*Server) GetSession ¶
func (s *Server) GetSession(w http.ResponseWriter, req *saml.IdpAuthnRequest) (session *saml.Session)
GetSession returns the *Session for this request.
If the remote user has specified a username and password in the request then it is validated against the user database. If valid it sets a cookie and returns the newly created session object.
If the remote user has specified invalid credentials then a login form is returned with an English-language toast telling the user their password was invalid.
If a session cookie already exists and represents a valid session, then the session is returned
If neither credentials nor a valid session cookie exist, this function sends a login form and returns nil.
func (*Server) HTTPLoginHandle ¶
func (s *Server) HTTPLoginHandle(w http.ResponseWriter, r *http.Request)
HTTPLoginHandle handles the `POST /login` and `GET /login` forms. If credentials are present in the request body, then they are validated. For valid credentials, the response is a 200 OK and the JSON session object. For invalid credentials, the HTML login prompt form is sent.
func (*Server) HTTPMetadataHandle ¶
func (s *Server) HTTPMetadataHandle(w http.ResponseWriter, r *http.Request)
func (*Server) HTTPSSOHandle ¶
func (s *Server) HTTPSSOHandle(w http.ResponseWriter, r *http.Request)
func (*Server) HandleDeleteShortcut ¶
HandleDeleteShortcut handles the `DELETE /shortcuts/:id` request.
func (*Server) HandleGetShortcut ¶
HandleGetShortcut handles the `GET /shortcuts/:id` request and responds with the shortcut object in JSON format.
func (*Server) HandleIDPInitiated ¶
HandleIDPInitiated handles a request for an IDP initiated login flow. It looks up the specified shortcut, generates the appropriate SAML assertion and redirects the user via the HTTP-POST binding to the service providers ACS URL.
func (*Server) HandleListShortcuts ¶
HandleListShortcuts handles the `GET /shortcuts/` request and responds with a JSON formatted list of shortcut names.
func (*Server) HandlePutShortcut ¶
HandlePutShortcut handles the `PUT /shortcuts/:id` request. It accepts a JSON formatted shortcut object in the request body and stores it.
func (*Server) HttpHandler ¶
func (*Server) Mount ¶
func (s *Server) Mount(handleFunc func(pattern string, handler func(w http.ResponseWriter, r *http.Request)), pth string)
InitializeHTTP sets up the HTTP handler for the server. (This function is called automatically for you by New, but you may need to call it yourself if you don't create the object using New.)
type Service ¶
type Service struct { // Name is the name of the service provider Name string // Metdata is the XML metadata of the service provider. Metadata saml.EntityDescriptor }
Service represents a configured SP for whom this IDP provides authentication services.
type ServicesProvider ¶
type ServicesProviders ¶
type ServicesProviders []ServicesProvider
func (ServicesProviders) Add ¶
func (providers ServicesProviders) Add(p ...ServicesProvider) ServicesProviders
func (ServicesProviders) Get ¶
func (providers ServicesProviders) Get(req *saml.IdpAuthnRequest, ID string) (sp saml.IDPServiceProvider, err error)
type SessionCreationHandler ¶
type SessionCreationHandler interface {
Handle(req *saml.IdpAuthnRequest, user User, session *saml.Session) (*saml.Session, error)
}
func GetSessionCreationHandler ¶
func GetSessionCreationHandler(req *saml.IdpAuthnRequest) SessionCreationHandler
type SessionCreationHandlerFunc ¶
type SessionsStorer ¶
type SessionsStorer interface { Store(w http.ResponseWriter, req *saml.IdpAuthnRequest, session *saml.Session) error Get(w http.ResponseWriter, req *saml.IdpAuthnRequest) (session *saml.Session, err error) Delete(w http.ResponseWriter, req *saml.IdpAuthnRequest) (session *saml.Session, err error) }
type Shortcut ¶
type Shortcut struct { // The name of the shortcut. Name string `json:"name"` // The entity ID of the service provider to use for this shortcut, i.e. // https://someapp.example.com/saml/metadata. ServiceProviderID string `json:"service_provider"` // If specified then the relay state is the fixed string provided RelayState *string `json:"relay_state,omitempty"` // If true then the URL suffix is used as the relayState. So for example, a user // requesting https://idp.example.com/login/myservice/foo will get redirected // to the myservice endpoint with a RelayState of "foo". URISuffixAsRelayState bool `json:"url_suffix_as_relay_state,omitempty"` }
Shortcut represents an IDP-initiated SAML flow. When a user navigates to /login/:shortcut it initiates the login flow to the specified service provider with the specified RelayState.
type Store ¶
type Store interface { // Get fetches the data stored in `key` and unmarshals it into `value`. Get(key string, value interface{}) error // Put marshals `value` and stores it in `key`. Put(key string, value interface{}) error // Delete removes `key` Delete(key string) error // List returns all the keys that start with `prefix`. The prefix is // stripped from each returned value. So if keys are ["aa", "ab", "cd"] // then List("a") would produce []string{"a", "b"} List(prefix string) ([]string, error) }
Store is an interface that describes an abstract key-value store.