81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
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)
|
|
}
|
|
|
|
func NewJWT(s jwt.Signer) *JWT {
|
|
return &JWT{signer: s}
|
|
}
|