// adapted from https://github.com/crewjam/saml/blob/main/samlidp/session.go package main import ( "encoding/base64" "encoding/hex" "log" "net/http" "net/http/fcgi" "strings" "time" "github.com/crewjam/saml" ) var sessionMaxAge = time.Hour func randomBytes(n int) []byte { rv := make([]byte, n) if _, err := saml.RandReader.Read(rv); err != nil { panic(err) } return rv } type User struct { Username string Email string GivenName string Surname string Groups []string } type BasicSessionProvider struct { UsernameKey string EmailKey string GivenNameKey string SurnameKey string GroupsKey string } func (s *BasicSessionProvider) getUser(r *http.Request) *User { env := fcgi.ProcessEnv(r) user := &User{} user.Username, _ = env[s.UsernameKey] user.Email, _ = env[s.EmailKey] user.GivenName, _ = env[s.GivenNameKey] user.Surname, _ = env[s.SurnameKey] groupsStr, _ := env[s.GroupsKey] user.Groups = strings.Split(groupsStr, ";") return user } func (s *BasicSessionProvider) GetSession(w http.ResponseWriter, r *http.Request, req *saml.IdpAuthnRequest) *saml.Session { user := s.getUser(r) if user.Username == "" { log.Println("Could not obtain username from FCGI") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return nil } session := &saml.Session{ ID: base64.StdEncoding.EncodeToString(randomBytes(32)), NameID: user.Username, CreateTime: saml.TimeNow(), ExpireTime: saml.TimeNow().Add(sessionMaxAge), Index: hex.EncodeToString(randomBytes(32)), UserName: user.Username, Groups: user.Groups, UserEmail: user.Email, UserSurname: user.Surname, UserGivenName: user.GivenName, } return session }