forked from crewjam/saml
-
Notifications
You must be signed in to change notification settings - Fork 1
/
samlidp.go
100 lines (87 loc) · 3.11 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
// Package samlidp a rudimentary SAML identity provider suitable for
// testing or as a starting point for a more complex service.
package samlidp
import (
"net/http"
"sync"
"github.com/edaniels/go-saml"
"github.com/zenazn/goji/web"
)
// Options represent the parameters to New() for creating a new IDP server
type Options struct {
URL string
Key string
Certificate string
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
IDP saml.IdentityProvider // the underlying IDP
Store Store // the data store
}
// New returns a new Server
func New(opts Options) (*Server, error) {
s := &Server{
IDP: saml.IdentityProvider{
Key: opts.Key,
Certificate: opts.Certificate,
MetadataURL: opts.URL + "/metadata",
SSOURL: opts.URL + "/sso",
ServiceProviders: map[string]*saml.Metadata{},
},
Store: opts.Store,
}
s.IDP.SessionProvider = 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)
}