probably should verify signing method -- and this only supports HMAC

This commit is contained in:
Ethan Knowlton 2023-10-10 23:46:49 -04:00
parent 4fc865d36c
commit bc03347fec
4 changed files with 24 additions and 4 deletions

View File

@ -157,7 +157,8 @@ ECHOIP_PROFILE=false
ECHOIP_IPSTACK_USE_HTTPS=true ECHOIP_IPSTACK_USE_HTTPS=true
ECHOIP_IPSTACK_ENABLE_SECURITY=true ECHOIP_IPSTACK_ENABLE_SECURITY=true
ECHOIP_JWT_AUTH=false ECHOIP_JWT_AUTH=false
ECHOIP_JWT_SECRET="" ECHOIP_JWT_SIGNING_METHOD=HS256
ECHOIP_JWT_SECRET="HS256"
``` ```
### Authenticate each API request with JWT ### Authenticate each API request with JWT
@ -165,6 +166,14 @@ ECHOIP_JWT_SECRET=""
You can authenticate each API request with JWT token. You can authenticate each API request with JWT token.
Just enable `config.Jwt.Enabled` and add your JWT secret to `config.Jwt.Secret`. 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. 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. A `401` will be returned should the token not be valid.

View File

@ -19,8 +19,9 @@ type GeoIP struct {
} }
type Jwt struct { type Jwt struct {
Enabled bool Enabled bool
Secret string SigningMethod string
Secret string
} }
type Config struct { type Config struct {
@ -49,7 +50,8 @@ func GetConfig() (Config, error) {
RedisUrl: getenv_string("ECHOIP_REDIS_URL", ""), RedisUrl: getenv_string("ECHOIP_REDIS_URL", ""),
Database: getenv_string("ECHOIP_DATABASE", "geoip"), Database: getenv_string("ECHOIP_DATABASE", "geoip"),
Jwt: Jwt{ Jwt: Jwt{
Secret: getenv_string("ECHOIP_JWT_SECRET", ""), Secret: getenv_string("ECHOIP_JWT_SECRET", ""),
SigningMethod: getenv_string("ECHOIP_JWT_SIGNING_METHOD", "HS256"),
}, },
IPStack: IPStack{ IPStack: IPStack{
ApiKey: getenv_string("ECHOIP_IPSTACK_API_KEY", ""), ApiKey: getenv_string("ECHOIP_IPSTACK_API_KEY", ""),

View File

@ -12,6 +12,7 @@ Debug = false # enable debugging, ex print jwt token errors
[Jwt] [Jwt]
Enabled = false Enabled = false
SigningMethod = "HS256" # HS256 | HS384 | HS512
Secret = "" Secret = ""
[IPStack] [IPStack]

View File

@ -7,6 +7,7 @@ import (
"html/template" "html/template"
"log" "log"
"path/filepath" "path/filepath"
"reflect"
"strings" "strings"
"net/http/pprof" "net/http/pprof"
@ -426,6 +427,13 @@ func handleAuth(r *http.Request, runConfig *config.Config) error {
tokenString := strings.ReplaceAll(authorization, "Bearer ", "") tokenString := strings.ReplaceAll(authorization, "Bearer ", "")
if _, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { 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 return []byte(runConfig.Jwt.Secret), nil
}); err != nil { }); err != nil {
if runConfig.Debug { if runConfig.Debug {