diff --git a/README.md b/README.md index 6707437..b093535 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,8 @@ ECHOIP_PROFILE=false ECHOIP_IPSTACK_USE_HTTPS=true ECHOIP_IPSTACK_ENABLE_SECURITY=true ECHOIP_JWT_AUTH=false -ECHOIP_JWT_SECRET="" +ECHOIP_JWT_SIGNING_METHOD=HS256 +ECHOIP_JWT_SECRET="HS256" ``` ### Authenticate each API request with JWT @@ -165,6 +166,14 @@ ECHOIP_JWT_SECRET="" You can authenticate each API request with JWT token. Just enable `config.Jwt.Enabled` and add your JWT secret to `config.Jwt.Secret`. +EchoIP validates JWT signing algorithm, `config.SigningMethod` should be one of available from `golang-jwt/jwt` and match your expceted algorithm. Currently only supporting HMAC signing. + +`config.SigningMethod string` + +``` +# HS256 | HS384 | HS512 +``` + Requests will be accepted if a valid token is provided in `Authorization: Bearer $token` header. A `401` will be returned should the token not be valid. diff --git a/config/config.go b/config/config.go index 188ea2a..9f9a033 100644 --- a/config/config.go +++ b/config/config.go @@ -19,8 +19,9 @@ type GeoIP struct { } type Jwt struct { - Enabled bool - Secret string + Enabled bool + SigningMethod string + Secret string } type Config struct { @@ -49,7 +50,8 @@ func GetConfig() (Config, error) { RedisUrl: getenv_string("ECHOIP_REDIS_URL", ""), Database: getenv_string("ECHOIP_DATABASE", "geoip"), Jwt: Jwt{ - Secret: getenv_string("ECHOIP_JWT_SECRET", ""), + Secret: getenv_string("ECHOIP_JWT_SECRET", ""), + SigningMethod: getenv_string("ECHOIP_JWT_SIGNING_METHOD", "HS256"), }, IPStack: IPStack{ ApiKey: getenv_string("ECHOIP_IPSTACK_API_KEY", ""), diff --git a/etc/echoip/config.toml b/etc/echoip/config.toml index 8079850..6560a5e 100644 --- a/etc/echoip/config.toml +++ b/etc/echoip/config.toml @@ -12,6 +12,7 @@ Debug = false # enable debugging, ex print jwt token errors [Jwt] Enabled = false +SigningMethod = "HS256" # HS256 | HS384 | HS512 Secret = "" [IPStack] diff --git a/http/http.go b/http/http.go index d18b15f..6247975 100644 --- a/http/http.go +++ b/http/http.go @@ -7,6 +7,7 @@ import ( "html/template" "log" "path/filepath" + "reflect" "strings" "net/http/pprof" @@ -426,6 +427,13 @@ func handleAuth(r *http.Request, runConfig *config.Config) error { tokenString := strings.ReplaceAll(authorization, "Bearer ", "") if _, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + expected := reflect.TypeOf(jwt.GetSigningMethod(runConfig.Jwt.SigningMethod)) + got := reflect.TypeOf(token.Method) + if expected != got { + return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) + } + + // Only support SigningMethodHMAC ( Others will be quite a bit more complicated ) return []byte(runConfig.Jwt.Secret), nil }); err != nil { if runConfig.Debug {