Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT POC for API #147

Merged
merged 5 commits into from
Jul 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/server/handler_authenticate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package server

import (
"strings"

response "github.com/linkernetworks/vortex/src/net/http"
"github.com/linkernetworks/vortex/src/web"
)

// TODO move to entity
type UserCredentials struct {
Username string `json:"username"`
Password string `json:"password"`
}

func loginHandler(ctx *web.Context) {
_, req, resp := ctx.ServiceProvider, ctx.Request, ctx.Response
user := UserCredentials{}
if err := req.ReadEntity(&user); err != nil {
response.Forbidden(req.Request, resp.ResponseWriter, err)
return
}

// TODO query mongodb to check user account and password
if strings.ToLower(user.Username) != "someone" || user.Password != "p@ssword" {
response.Forbidden(req.Request, resp.ResponseWriter)
return
}

tokenString, err := generateToken(strings.ToLower(user.Username))
if err != nil {
response.InternalServerError(req.Request, resp.ResponseWriter, err)
return
}

resp.WriteEntity(response.ActionResponse{
Error: false,
Message: tokenString,
})
}
20 changes: 20 additions & 0 deletions src/server/jwt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package server

import (
"time"

"github.com/dgrijalva/jwt-go"
)

func generateToken(userUUID string) (string, error) {
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = jwt.MapClaims{
// issuer of the claim
"exp": time.Now().Add(time.Hour * time.Duration(1)).Unix(),
// issued-at time
"iat": time.Now().Unix(),
// the subject of this token. This is the user associated with the relevant action
"sub": userUUID,
}
return token.SignedString([]byte(SecretKey))
}
13 changes: 13 additions & 0 deletions src/server/jwt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package server

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestGenerateToken(t *testing.T) {
tokenString, err := generateToken("234243353535330")
assert.NotNil(t, tokenString)
assert.NoError(t, err)
}
8 changes: 8 additions & 0 deletions src/server/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func (a *App) AppRoute() *mux.Router {

container.Add(newVersionService(a.ServiceProvider))
container.Add(newUserService(a.ServiceProvider))
container.Add(newAuthenticateService(a.ServiceProvider))
container.Add(newNetworkService(a.ServiceProvider))
container.Add(newStorageService(a.ServiceProvider))
container.Add(newVolumeService(a.ServiceProvider))
Expand All @@ -31,6 +32,7 @@ func (a *App) AppRoute() *mux.Router {
func newVersionService(sp *serviceprovider.Container) *restful.WebService {
webService := new(restful.WebService)
webService.Path("/v1/version").Consumes(restful.MIME_JSON, restful.MIME_JSON).Produces(restful.MIME_JSON, restful.MIME_JSON)
// webService.Filter(validateTokenMiddleware)
webService.Route(webService.GET("/").To(handler.RESTfulServiceHandler(sp, versionHandler)))
return webService
}
Expand All @@ -44,6 +46,12 @@ func newUserService(sp *serviceprovider.Container) *restful.WebService {
webService.Route(webService.GET("/{id}").To(handler.RESTfulServiceHandler(sp, getUserHandler)))
return webService
}
func newAuthenticateService(sp *serviceprovider.Container) *restful.WebService {
webService := new(restful.WebService)
webService.Path("/v1/login").Consumes(restful.MIME_JSON, restful.MIME_JSON).Produces(restful.MIME_JSON, restful.MIME_JSON)
webService.Route(webService.POST("/").To(handler.RESTfulServiceHandler(sp, loginHandler)))
return webService
}

func newNetworkService(sp *serviceprovider.Container) *restful.WebService {
webService := new(restful.WebService)
Expand Down
30 changes: 30 additions & 0 deletions src/server/route_filter.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
package server

import (
"net/http"

"github.com/dgrijalva/jwt-go"
"github.com/dgrijalva/jwt-go/request"
"github.com/emicklei/go-restful"
"github.com/linkernetworks/logger"
)

// FIXME using ldconfig go build to give a secretkey
const (
SecretKey = "linkernetworks"
)

func globalLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
logger.Infof("%s %s", req.Request.Method, req.Request.URL)
chain.ProcessFilter(req, resp)
}

func validateTokenMiddleware(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
token, err := request.ParseFromRequest(req.Request, request.AuthorizationHeaderExtractor,
func(token *jwt.Token) (interface{}, error) {
return []byte(SecretKey), nil
})

if err == nil {
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
// save to requests attributes
req.SetAttribute("UserID", claims["sub"])
chain.ProcessFilter(req, resp)
} else {
resp.WriteHeader(http.StatusUnauthorized)
logger.Infof("Token is not valid")
}
} else {
resp.WriteHeader(http.StatusUnauthorized)
logger.Infof("Unauthorized access to this resource")
}
}
6 changes: 6 additions & 0 deletions vendor/vendor.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
"revision": "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e",
"revisionTime": "2018-03-08T23:13:08Z"
},
{
"checksumSHA1": "SvAnbKinPLfP+DoIB/uHdGCKClE=",
"path": "github.com/dgrijalva/jwt-go/request",
"revision": "0b96aaa707760d6ab28d9b9d1913ff5993328bae",
"revisionTime": "2018-07-19T21:18:23Z"
},
{
"checksumSHA1": "wPbKObbGzS/43nrskRaJVFVEW/A=",
"path": "github.com/ema/qdisc",
Expand Down