ginoidc/keycloakclaims/claims.go

79 lines
2.2 KiB
Go

package keycloakclaims
import (
"errors"
"log"
"code.icod.de/dalu/ginoidc/ginerror"
"github.com/gin-gonic/gin"
)
// Claims represent the condensed and stripped version of Keycloak's JWT claims payload
type Claims struct {
Sub string `json:"sub,omitempty"`
RealmAccess struct {
Roles []string `json:"roles,omitempty"`
} `json:"realm_access,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
}
// FromRequest returns a Claims instance or nil if and error occurs.
// In case of an error it sets or appends to the "oidcerrors" context value of *gin.Context
func FromRequest(cx *gin.Context) *Claims {
claimsValue, found := cx.Get("claims")
if !found {
const errText = "claims not present"
errorType := ginerror.Error{
Description: errText,
Error: errors.New(errText),
}
if e := addOrExtendErrors(cx, "oidcerrors", errorType); e != nil {
log.Println(e.Error())
}
return nil
}
claims, ok := claimsValue.(map[string]interface{})
if !ok {
const errText = "claims are not of type map[string]interface{}"
errorType := ginerror.Error{
Description: errText,
Error: errors.New(errText),
}
if e := addOrExtendErrors(cx, "oidcerrors", errorType); e != nil {
log.Println(e.Error())
}
return nil
}
c := new(Claims)
c.Sub, _ = claims["sub"].(string)
c.PreferredUsername, _ = claims["preferred_username"].(string)
c.RealmAccess, _ = claims["realm_access"].(struct {
Roles []string `json:"roles,omitempty"`
})
return c
}
// addOrExtendErrors adds or appends to the options.ErrorContextKeyName values
func addOrExtendErrors(cx *gin.Context, key string, newerror ginerror.Error) error {
errorsValue, errorsFound := cx.Get("oidcerrors")
if !errorsFound {
var errs []ginerror.Error
errs = append(errs, newerror)
// TODO: find a way to get the error context key from options
cx.Set("oidcerrors", errs)
return nil
} else {
errs, ok := errorsValue.([]ginerror.Error)
if !ok {
return errors.New("claims: errorsValue is not of type []ginerror.Error")
} else {
errs = append(errs, newerror)
// TODO: find a way to get the error context key from options
cx.Set("oidcerrors", errs)
return nil
}
}
}