Skip to content

Commit

Permalink
Merge pull request #36 from nerdypinkbooks/add-jwt-based-auth
Browse files Browse the repository at this point in the history
Add jwt based auth
  • Loading branch information
pottava authored Feb 8, 2020
2 parents 0ea1014 + 3b55d48 commit 1a82bf4
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.13

require (
github.com/aws/aws-sdk-go v1.25.25
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-openapi/swag v0.19.5
github.com/stretchr/testify v1.3.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ github.com/aws/aws-sdk-go v1.25.25/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
Expand Down
2 changes: 2 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type config struct { // nolint
IdleConnTimeout time.Duration // IDLE_CONNECTION_TIMEOUT
DisableCompression bool // DISABLE_COMPRESSION
InsecureTLS bool // Disables TLS validation on request endpoints.
JwtSecretKey string // JWT_SECRET_KEY
}

// Setup configurations with environment variables
Expand Down Expand Up @@ -126,6 +127,7 @@ func Setup() {
IdleConnTimeout: idleConnTimeout,
DisableCompression: disableCompression,
InsecureTLS: insecureTLS,
JwtSecretKey: os.Getenv("JWT_SECRET_KEY"),
}
// Proxy
log.Printf("[config] Proxy to %v", Config.S3Bucket)
Expand Down
28 changes: 28 additions & 0 deletions internal/http/handler-wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/pottava/aws-s3-proxy/internal/config"
)

Expand Down Expand Up @@ -37,6 +38,14 @@ func WrapHandler(handler func(w http.ResponseWriter, r *http.Request)) http.Hand
return
}
}
// Auth with JWT
if len(c.HealthCheckPath) > 0 && r.URL.Path != c.HealthCheckPath {
if len(c.JwtSecretKey) > 0 && !isValidJwt(r) {
w.Header().Set("WWW-Authenticate", `Basic realm="REALM"`)
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
}
proc := time.Now()
addr := r.RemoteAddr
if ip, found := header(r, "X-Forwarded-For"); found {
Expand Down Expand Up @@ -100,3 +109,22 @@ func splitCsvLine(data string) []string {
}
return parsed
}

func isValidJwt(r *http.Request) bool {
reqToken := r.Header.Get("Authorization")
splitToken := strings.Split(reqToken, "Bearer")
if len(splitToken) != 2 {
// Error: Bearer token not in proper format
return false
}
reqToken = strings.TrimSpace(splitToken[1])
token, err := jwt.Parse(reqToken, func(t *jwt.Token) (interface{}, error) {
secretKey := config.Config.JwtSecretKey
return []byte(secretKey), nil
})
if err == nil && token.Valid {
return true
} else {
return false
}
}
35 changes: 35 additions & 0 deletions internal/http/handler-wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package http

import (
"encoding/base64"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/dgrijalva/jwt-go"
"github.com/pottava/aws-s3-proxy/internal/config"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -41,6 +44,38 @@ func TestAuthMatch(t *testing.T) {
assert.True(t, auth(req, username, password))
}

func TestWithValidJWT(t *testing.T) {
username := "user"
password := "pass"
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": username,
"password": password,
})
tokenString, _ := token.SignedString([]byte("secret"))
c := config.Config
c.JwtSecretKey = "secret"
req := httptest.NewRequest(http.MethodGet, sample, nil)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tokenString))

assert.True(t, isValidJwt(req))
}

func TestWithoutValidJWT(t *testing.T) {
username := "user"
password := "pass"
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": username,
"password": password,
})
tokenString, _ := token.SignedString([]byte("secret"))
c := config.Config
c.JwtSecretKey = "foo"
req := httptest.NewRequest(http.MethodGet, sample, nil)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tokenString))

assert.False(t, isValidJwt(req))
}

func TestHeaderWithValue(t *testing.T) {
expected := "test"

Expand Down

0 comments on commit 1a82bf4

Please sign in to comment.