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/auth" "gopkg.in/dgrijalva/jwt-go.v3" ) var defaccount = &account{ data: map[auth.AccountConstant]interface{}{ auth.AccountID: uuid.Nil, auth.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) auth.Account { acc := &(*defaccount) acc.s = s cookie, err := c.Cookie(s.Cookiename) if err != nil { 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") for key, value := range *claim { acc.data[auth.AccountConstant(key)] = value } 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[auth.AccountConstant]interface{} } func (a *account) Anonymous() bool { return a.data[auth.AccountAnon].(bool) } func (a *account) Redirect(c *gin.Context) { id := uuid.New().String() tokenstring, err := jwttoken(jwt.MapClaims{ string(auth.AccountID): id, string(auth.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 auth.AccountConstant) interface{} { return a.data[key] } func (a *account) List() []auth.AccountConstant { var liste []auth.AccountConstant for key := range a.data { liste = append(liste, key) } return liste }