1
0
Fork 0
httpserver/modules/saml/account.go

116 Zeilen
2.8 KiB
Go

package saml
import (
"fmt"
"net/http"
"time"
"github.com/crewjam/saml"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
"github.com/phuslu/log"
"go.sebtobie.de/httpserver/auth"
)
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),
saml.HTTPRedirectBinding,
saml.HTTPRedirectBinding,
)
if err != nil {
c.AbortWithStatus(http.StatusInternalServerError)
}
request.ID = id
u, err := request.Redirect(c.Request.URL.String(), a.s.sp)
if err != nil {
log.Error().Err(err).Msg("Failed to create redirect")
c.AbortWithStatus(500)
return
}
log.Debug().Msgf("Leite weiter: %s", u.String())
c.Redirect(http.StatusSeeOther, u.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
}