forked from crewjam/saml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
samlidp.go
120 lines (105 loc) · 3.55 KB
/
samlidp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Package samlidp a rudimentary SAML identity provider suitable for
// testing or as a starting point for a more complex service.
package samlidp
import (
"crypto"
"crypto/x509"
"net/http"
"net/url"
"sync"
"github.com/tripism/saml"
"github.com/tripism/saml/logger"
"github.com/zenazn/goji/web"
)
// Options represent the parameters to New() for creating a new IDP server
type Options struct {
URL url.URL
Key crypto.PrivateKey
Logger logger.Interface
Certificate *x509.Certificate
Store Store
}
// 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 User objects
// /sessions - RESTful interface to Session objects
// /shortcuts - RESTful interface to Shortcut objects
type Server struct {
http.Handler
idpConfigMu sync.RWMutex // protects calls into the IDP
logger logger.Interface
serviceProviders map[string]*saml.EntityDescriptor
IDP saml.IdentityProvider // the underlying IDP
Store Store // the data store
}
// New returns a new Server
func New(opts Options) (*Server, error) {
metadataURL := opts.URL
metadataURL.Path = metadataURL.Path + "/metadata"
ssoURL := opts.URL
ssoURL.Path = ssoURL.Path + "/sso"
logr := opts.Logger
if logr == nil {
logr = logger.DefaultLogger
}
s := &Server{
serviceProviders: map[string]*saml.EntityDescriptor{},
IDP: saml.IdentityProvider{
Key: opts.Key,
Logger: logr,
Certificate: opts.Certificate,
MetadataURL: metadataURL,
SSOURL: ssoURL,
},
logger: logr,
Store: opts.Store,
}
s.IDP.SessionProvider = s
s.IDP.ServiceProviderProvider = s
if err := s.initializeServices(); err != nil {
return nil, err
}
s.InitializeHTTP()
return s, nil
}
// 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.)
func (s *Server) InitializeHTTP() {
mux := web.New()
s.Handler = mux
mux.Get("/metadata", func(w http.ResponseWriter, r *http.Request) {
s.idpConfigMu.RLock()
defer s.idpConfigMu.RUnlock()
s.IDP.ServeMetadata(w, r)
})
mux.Handle("/sso", func(w http.ResponseWriter, r *http.Request) {
s.idpConfigMu.RLock()
defer s.idpConfigMu.RUnlock()
s.IDP.ServeSSO(w, r)
})
mux.Handle("/login", s.HandleLogin)
mux.Handle("/login/:shortcut", s.HandleIDPInitiated)
mux.Handle("/login/:shortcut/*", s.HandleIDPInitiated)
mux.Get("/services/", s.HandleListServices)
mux.Get("/services/:id", s.HandleGetService)
mux.Put("/services/:id", s.HandlePutService)
mux.Post("/services/:id", s.HandlePutService)
mux.Delete("/services/:id", s.HandleDeleteService)
mux.Get("/users/", s.HandleListUsers)
mux.Get("/users/:id", s.HandleGetUser)
mux.Put("/users/:id", s.HandlePutUser)
mux.Delete("/users/:id", s.HandleDeleteUser)
mux.Get("/sessions/", s.HandleListSessions)
mux.Get("/sessions/:id", s.HandleGetSession)
mux.Delete("/sessions/:id", s.HandleDeleteSession)
mux.Get("/shortcuts/", s.HandleListShortcuts)
mux.Get("/shortcuts/:id", s.HandleGetShortcut)
mux.Put("/shortcuts/:id", s.HandlePutShortcut)
mux.Delete("/shortcuts/:id", s.HandleDeleteShortcut)
}