chrly/http/jwt.go

79 lines
1.5 KiB
Go
Raw Permalink Normal View History

package http
2018-01-16 02:22:22 +05:30
import (
"errors"
"net/http"
"strings"
2018-01-16 02:22:22 +05:30
"time"
"github.com/SermoDigital/jose/crypto"
"github.com/SermoDigital/jose/jws"
)
var hashAlg = crypto.SigningMethodHS256
const scopesClaim = "scopes"
type Scope string
var (
SkinScope = Scope("skin")
)
type JwtAuth struct {
Emitter
Key []byte
2018-01-16 02:22:22 +05:30
}
func (t *JwtAuth) NewToken(scopes ...Scope) ([]byte, error) {
if len(t.Key) == 0 {
return nil, errors.New("signing key not available")
2018-01-16 02:22:22 +05:30
}
claims := jws.Claims{}
claims.Set(scopesClaim, scopes)
claims.SetIssuedAt(time.Now())
encoder := jws.NewJWT(claims, hashAlg)
token, err := encoder.Serialize(t.Key)
2018-01-16 02:22:22 +05:30
if err != nil {
return nil, err
}
return token, nil
}
func (t *JwtAuth) Authenticate(req *http.Request) error {
if len(t.Key) == 0 {
return t.emitErr(errors.New("Signing key not set"))
2018-01-16 02:22:22 +05:30
}
bearerToken := req.Header.Get("Authorization")
if bearerToken == "" {
return t.emitErr(errors.New("Authentication header not presented"))
2018-01-16 02:22:22 +05:30
}
if !strings.EqualFold(bearerToken[0:7], "BEARER ") {
return t.emitErr(errors.New("Cannot recognize JWT token in passed value"))
}
2018-01-16 02:22:22 +05:30
tokenStr := bearerToken[7:]
token, err := jws.ParseJWT([]byte(tokenStr))
if err != nil {
return t.emitErr(errors.New("Cannot parse passed JWT token"))
2018-01-16 02:22:22 +05:30
}
err = token.Validate(t.Key, hashAlg)
2018-01-16 02:22:22 +05:30
if err != nil {
return t.emitErr(errors.New("JWT token have invalid signature. It may be corrupted or expired"))
2018-01-16 02:22:22 +05:30
}
t.Emit("authentication:success")
2018-01-16 02:22:22 +05:30
return nil
}
func (t *JwtAuth) emitErr(err error) error {
t.Emit("authentication:error", err)
return err
2018-01-16 02:22:22 +05:30
}