samlidp

package
v0.0.0-...-1efe09a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2020 License: BSD-2-Clause Imports: 20 Imported by: 0

Documentation

Overview

Package samlidp a rudimentary SAML identity provider suitable for testing or as a starting point for a more complex service.

Index

Constants

View Source
const (
	LoginFormUserOptions contextKey = iota
	SubPath
)
View Source
const (
	KeySessionCreationHandler key = iota
	KeyLoginFormCallback
)

Variables

View Source
var DefaultLoginFormDataInputOptions = LoginFormDataInputOptions{
	PasswordLabel:       "Password",
	PasswordPlaceholder: "your password",
	UserPlaceholder:     "your user name",
	UserLabel:           "User",
	UserInputType:       "text",
	SubmitLabel:         "Log In",
}
View Source
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)
	}
})
View Source
var ErrInvalidUserOrPassword = errors.New("Invalid user or password")
View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned from Store.Get() when a stored item is not present

View Source
var ErrServiceProviderNotFound = errors.New("service provider not found")

Functions

func ContextGetSubPath

func ContextGetSubPath(ctx context.Context) (sub string)

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 HttpHandlers struct {
	Login,
	Metadata,
	SSO http.Handler
}

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 (*LoginFormDataInputOptions) Merge

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

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is an implementation of Store that resides completely in memory.

func (*MemoryStore) Delete

func (s *MemoryStore) Delete(key string) error

Delete removes `key`

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

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 New

func New(opts Options) (*Server, error)

New returns a new Server

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

func (s *Server) HandleDeleteShortcut(c web.C, w http.ResponseWriter, r *http.Request)

HandleDeleteShortcut handles the `DELETE /shortcuts/:id` request.

func (*Server) HandleGetShortcut

func (s *Server) HandleGetShortcut(c web.C, w http.ResponseWriter, r *http.Request)

HandleGetShortcut handles the `GET /shortcuts/:id` request and responds with the shortcut object in JSON format.

func (*Server) HandleIDPInitiated

func (s *Server) HandleIDPInitiated(c web.C, w http.ResponseWriter, r *http.Request)

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

func (s *Server) HandleListShortcuts(c web.C, w http.ResponseWriter, r *http.Request)

HandleListShortcuts handles the `GET /shortcuts/` request and responds with a JSON formatted list of shortcut names.

func (*Server) HandlePutShortcut

func (s *Server) HandlePutShortcut(c web.C, w http.ResponseWriter, r *http.Request)

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 (s *Server) HttpHandler() http.Handler

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 ServicesProvider interface {
	Get(req *saml.IdpAuthnRequest, ID string) (saml.IDPServiceProvider, error)
}

type ServicesProviders

type ServicesProviders []ServicesProvider

func (ServicesProviders) Add

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 SessionCreationHandlerFunc func(req *saml.IdpAuthnRequest, user User, session *saml.Session) (*saml.Session, error)

func (SessionCreationHandlerFunc) Handle

func (f SessionCreationHandlerFunc) Handle(req *saml.IdpAuthnRequest, user User, session *saml.Session) (*saml.Session, error)

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.

type User

type User interface {
	ID() string
	Name() string
	Email() string
}

type UsersServiceProvider

type UsersServiceProvider interface {
	Authenticates(req *saml.IdpAuthnRequest) (user User, err error)
	Get(r *http.Request, key string) (user User, err error)
}

Directories

Path Synopsis
drivers

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL