package saml import ( "fmt" "net/http" "time" "github.com/crewjam/saml" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/phuslu/log" "go.sebtobie.de/httpserver" "gopkg.in/dgrijalva/jwt-go.v3" ) var defaccount = &account{ data: map[string]interface{}{ httpserver.AccountID: "", httpserver.AccountAnon: true, }, } func maptoarray(m map[string]interface{}) (output []interface{}) { for k, v := range m { output = append(output, []interface{}{k, v}) } return } // Account returns the Account representation of the user func (s *SAML) Account(c *gin.Context) httpserver.Account { acc := &(*defaccount) acc.s = s cookie, err := c.Cookie(s.Cookiename) if err != nil { log.Debug().Err(err).Msg("Cookie error") return acc } var ( claim *jwt.MapClaims ok bool ) token, err := jwt.ParseWithClaims(cookie, &jwt.MapClaims{}, s.signingkey) if err != nil { log.Debug().Err(err).Msg("Error while parsing token") } if claim, ok = token.Claims.(*jwt.MapClaims); ok && token.Valid { log.Debug().KeysAndValues(claim).Msg("Got valid token") acc.data = *claim return acc } log.Debug().Bool("valid", token.Valid).KeysAndValues(maptoarray(*claim)...).Msg("problem vith token") return acc } func (s *SAML) signingkey(token *jwt.Token) (key interface{}, err error) { if _, ok := token.Method.(*jwt.SigningMethodRSAPSS); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } return &s.jwtprivatekey.PublicKey, nil } type account struct { s *SAML data map[string]interface{} } func (a *account) Anonymous() bool { return a.data[httpserver.AccountAnon].(bool) } func (a *account) Redirect(c *gin.Context) { id := uuid.New().String() tokenstring, err := jwttoken(jwt.MapClaims{ httpserver.AccountID: id, httpserver.AccountAnon: true, }, a.s.jwtprivatekey) if err != nil { log.Error().Err(err).Msg("Failed to generate the token") c.AbortWithStatus(http.StatusInternalServerError) return } c.SetCookie(a.s.Cookiename, tokenstring, int(time.Hour), "", "", true, true) request, err := a.s.sp.MakeAuthenticationRequest(a.s.sp.GetSSOBindingLocation(saml.HTTPRedirectBinding)) if err != nil { c.AbortWithStatus(http.StatusInternalServerError) } request.ID = id log.Debug().Msgf("Leite weiter: %s", request.Redirect(c.Request.URL.String()).String()) c.Redirect(http.StatusSeeOther, request.Redirect(c.Request.URL.String()).String()) } func (a *account) Get(key string) interface{} { return a.data[key] } func (a *account) List() []string { liste := make([]string, len(a.data)) for key := range a.data { liste = append(liste, key) } return liste }