github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/session/delegated.go (about) 1 package session 2 3 import ( 4 "encoding/base64" 5 "errors" 6 "time" 7 8 jwt "github.com/golang-jwt/jwt/v5" 9 10 "github.com/cozy/cozy-stack/model/instance" 11 "github.com/cozy/cozy-stack/pkg/config/config" 12 "github.com/cozy/cozy-stack/pkg/crypto" 13 ) 14 15 // ExternalClaims is the format for JWT for authentication from external sources 16 type ExternalClaims struct { 17 jwt.RegisteredClaims 18 Name string `json:"name"` 19 Code string `json:"code"` 20 Email string `json:"email,omitempty"` 21 UUID string `json:"uuid,omitempty"` 22 } 23 24 // CheckDelegatedJWT checks if a delegated JWT is valid for a given instance 25 func CheckDelegatedJWT(instance *instance.Instance, token string) error { 26 authenticationConfig := config.GetConfig().Authentication 27 context := instance.ContextName 28 29 if context == "" { 30 context = config.DefaultInstanceContext 31 } 32 delegatedTypes, ok := authenticationConfig[context] 33 if !ok { 34 return errors.New("No delegated authentication defined for this context") 35 } 36 37 JWTSecret, ok := delegatedTypes.(map[string]interface{})["jwt_secret"] 38 if !ok { 39 return errors.New("JWT delegated type is not defined for this context") 40 } 41 42 claims := ExternalClaims{} 43 keyFunc := func(token *jwt.Token) (interface{}, error) { 44 return base64.StdEncoding.DecodeString(JWTSecret.(string)) 45 } 46 47 err := crypto.ParseJWT(token, keyFunc, &claims) 48 if err != nil { 49 return err 50 } 51 52 if claims.RegisteredClaims.ExpiresAt != nil && claims.RegisteredClaims.ExpiresAt.Before(time.Now()) { 53 return errors.New("Token has expired") 54 } 55 56 if claims.Name != instance.Domain { 57 return errors.New("Issuer is not valid") 58 } 59 60 return nil 61 }