From 336987e806fa37abee78bfdce90cf9113eccfe11 Mon Sep 17 00:00:00 2001 From: Alexandre Tuleu Date: Tue, 18 Aug 2015 19:46:15 +0200 Subject: [PATCH] Adds a jwt middleware It is not certain that it is final, as the jwt is just an interface{} --- jwt.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 jwt.go diff --git a/jwt.go b/jwt.go new file mode 100644 index 0000000..42dc0f5 --- /dev/null +++ b/jwt.go @@ -0,0 +1,76 @@ +package narco + +import ( + "fmt" + "net/http" + "strings" + + "github.com/codemodus/chain" + "golang.org/x/net/context" + "ponyo.epfl.ch/gitlab/alexandre.tuleu/narco/jwt" +) + +type JWT struct { + signer jwt.Signer +} + +const ( + jwtKeyGenerator narcoKey = 2 + jwtKeyOutput narcoKey = 3 +) + +func (j *JWT) Wrap() func(chain.Handler) chain.Handler { + return func(other chain.Handler) chain.Handler { + return chain.HandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { + tokenGenerator, ok := ctx.Value(jwtKeyGenerator).(TokenCreator) + + if tokenGenerator == nil || ok == false { + //we did not register a token we ignore all processing + other.ServeHTTPContext(ctx, rw, req) + return + } + + // check for the header + tokenStr, ok := req.Header["Authorization"] + if ok == false { + // no Authorization header, we are just not + // authentified, we process down, no token added + other.ServeHTTPContext(ctx, rw, req) + return + } + + if len(tokenStr) != 1 || strings.HasPrefix(tokenStr[0], "Bearer ") == false { + Error(ctx, rw, fmt.Errorf("Invalid Authorization HTTP Header %v", tokenStr), http.StatusForbidden) + return + } + tkData := strings.TrimPrefix(tokenStr[0], "Bearer ") + + //parse the desired token, with signature checking + token := tokenGenerator() + err := jwt.DecodeJWS([]byte(tkData), token, j.signer) + if err != nil { + Error(ctx, rw, err, http.StatusForbidden) + return + } + + // we process down the pipeline, with the token added to + // context + other.ServeHTTPContext(context.WithValue(ctx, jwtKeyOutput, token), rw, req) + }) + } +} + +func GetJwt(ctx context.Context) interface{} { + return ctx.Value(jwtKeyOutput) +} + +//A Token Creator should produce a new pointer to a desired token +//struct +type TokenCreator func() interface{} + +// RegisterJwtType should be used to register the token rtyope +// expected in the context. TokenCreator should allocate a new, +// unparsed token. +func RegisterJwtType(ctx context.Context, generator TokenCreator) context.Context { + return context.WithValue(ctx, jwtKeyGenerator, generator) +}