116 Zeilen
2.8 KiB
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
|
|
}
|