Files
sxchnge/backend/product/auth/config/middleware.go
T

111 lines
3.1 KiB
Go

package middleware
import (
"os"
"strings"
"git.sendico.io/tech/sxchnge/shared/errors"
)
type CORSSettings struct {
MaxAge int `yaml:"max_age"`
AllowedOrigins []string `yaml:"allowed_origins"`
AllowedMethods []string `yaml:"allowed_methods"`
AllowedHeaders []string `yaml:"allowed_headers"`
ExposedHeaders []string `yaml:"exposed_headers"`
AllowCredentials bool `yaml:"allow_credentials"`
}
func (c CORSSettings) Validate() error {
if !c.AllowCredentials {
return nil
}
if len(c.AllowedOrigins) == 0 {
return merrors.InvalidArgument("credentialed CORS requires explicit allowed origins", "middleware.CORS.allowed_origins")
}
for _, origin := range c.AllowedOrigins {
if strings.TrimSpace(origin) == "*" {
return merrors.InvalidArgument("credentialed CORS does not allow wildcard origins", "middleware.CORS.allowed_origins")
}
}
return nil
}
type Signature struct {
PublicKey any
PrivateKey []byte
Algorithm string
}
type SignatureConfig struct {
PublicKeyEnv string `yaml:"public_key_env,omitempty"`
PrivateKeyEnv string `yaml:"secret_key_env"`
Algorithm string `yaml:"algorithm"`
}
type TokenExpiration struct {
Account int `yaml:"account"`
Refresh int `yaml:"refresh"`
}
type TokenConfig struct {
Expiration TokenExpiration `yaml:"expiration_hours"`
Length int `yaml:"length"`
}
const MaxAccessTokenTTLHours = 1
func (c TokenConfig) Validate() error {
if c.Expiration.Account <= 0 || c.Expiration.Account > MaxAccessTokenTTLHours {
return merrors.InvalidArgument("access token expiration must be between 1 and 1 hour", "middleware.token.expiration_hours.account")
}
if c.Expiration.Refresh <= c.Expiration.Account {
return merrors.InvalidArgument("refresh token expiration must exceed access token expiration", "middleware.token.expiration_hours.refresh")
}
if c.Length < 32 {
return merrors.InvalidArgument("refresh token length must be at least 32 bytes", "middleware.token.length")
}
return nil
}
type PasswordChecks struct {
Digit bool `yaml:"digit"`
Upper bool `yaml:"upper"`
Lower bool `yaml:"lower"`
Special bool `yaml:"special"`
MinLength int `yaml:"min_length"`
}
type PasswordConfig struct {
TokenLength int `yaml:"token_length"`
Check PasswordChecks `yaml:"check"`
}
type Config struct {
DomainEnv string `yaml:"domain_env"`
EndPointEnv string `yaml:"api_endpoint_env"`
APIProtocolEnv string `yaml:"api_protocol_env"`
Signature SignatureConfig `yaml:"signature"`
CORS CORSSettings `yaml:"CORS"`
Token TokenConfig `yaml:"token"`
Password PasswordConfig `yaml:"password"`
LoginRateLimits *LoginRateLimitsConfig `yaml:"login_rate_limits"`
}
type MapClaims = map[string]any
func getKey(osEnv string) any {
if len(osEnv) == 0 {
return nil
}
return []byte(os.Getenv(osEnv))
}
func SignatureConf(conf *Config) Signature {
return Signature{
PrivateKey: []byte(os.Getenv(conf.Signature.PrivateKeyEnv)),
PublicKey: getKey(conf.Signature.PublicKeyEnv),
Algorithm: conf.Signature.Algorithm,
}
}