jws: added parsing from http requests
diff --git a/jws/errors.go b/jws/errors.go
index 6120bc1..0512a0e 100644
--- a/jws/errors.go
+++ b/jws/errors.go
@@ -56,4 +56,7 @@
// ErrNotEnoughValidSignatures means the JWS did not meet the required
// number of signatures.
ErrNotEnoughValidSignatures = errors.New("not enough valid signatures in the JWS")
+
+ // ErrNoTokenInRequest means there's no token present inside the *http.Request.
+ ErrNoTokenInRequest = errors.New("no token present in request")
)
diff --git a/jws/jws.go b/jws/jws.go
index 6673c9c..e84db43 100644
--- a/jws/jws.go
+++ b/jws/jws.go
@@ -3,6 +3,8 @@
import (
"bytes"
"encoding/json"
+ "net/http"
+ "strings"
"github.com/SermoDigital/jose"
"github.com/SermoDigital/jose/crypto"
@@ -302,7 +304,7 @@
return parseCompact(encoded, false)
}
-func parseCompact(encoded []byte, jwt bool) (*jws, error) {
+func parseCompact(encoded []byte, jwt bool, u ...json.Unmarshaler) (*jws, error) {
// This section loosely follows
// https://tools.ietf.org/html/rfc7519#section-7.2
@@ -329,8 +331,13 @@
return nil, err
}
+ var pl payload
+ if len(u) > 0 {
+ pl.u = u[0]
+ }
+
j := jws{
- payload: &payload{},
+ payload: &pl,
plcache: parts[1],
sb: []sigHead{s},
isJWT: jwt,
@@ -354,6 +361,79 @@
return &j, nil
}
+var (
+ // JWSFormKey is the form "key" which should be used inside
+ // ParseFromRequest if the request is a multipart.Form.
+ JWSFormKey = "access_token"
+
+ // MaxMemory is maximum amount of memory which should be used
+ // inside ParseFromRequest while parsing the multipart.Form
+ // if the request is a multipart.Form.
+ MaxMemory int64 = 10e6
+)
+
+// Format specifies which "format" the JWS is in -- Flat, General,
+// or compact. Additionally, constants for JWT/Unknown are added.
+type Format uint8
+
+const (
+ // Unknown format.
+ Unknown Format = iota
+
+ // Flat format.
+ Flat
+
+ // General format.
+ General
+
+ // Compact format.
+ Compact
+)
+
+var parseJumpTable = [^uint8(0)]func([]byte, ...json.Unmarshaler) (JWS, error){
+ Unknown: Parse,
+ Flat: ParseFlat,
+ General: ParseGeneral,
+ Compact: ParseCompact,
+}
+
+func init() {
+ for i := range parseJumpTable {
+ if parseJumpTable[i] == nil {
+ parseJumpTable[i] = Parse
+ }
+ }
+}
+
+func fromHeader(req *http.Request) ([]byte, bool) {
+ if ah := req.Header.Get("Authorization"); ah != "" && len(ah) > 6 && strings.EqualFold(ah[0:6], "BEARER") {
+ return []byte(ah[:7]), true
+ }
+ return nil, false
+}
+
+func fromForm(req *http.Request) ([]byte, bool) {
+ if err := req.ParseMultipartForm(MaxMemory); err != nil {
+ return nil, false
+ }
+ if tokStr := req.Form.Get(JWSFormKey); tokStr != "" {
+ return []byte(tokStr), true
+ }
+ return nil, false
+}
+
+// ParseFromRequest tries to find the JWS in an http.Request.
+// This method will call ParseMultipartForm if there's no token in the header.
+func ParseFromRequest(req *http.Request, format Format, u ...json.Unmarshaler) (JWS, error) {
+ if b, ok := fromHeader(req); ok {
+ return parseJumpTable[format](b, u...)
+ }
+ if b, ok := fromForm(req); ok {
+ return parseJumpTable[format](b, u...)
+ }
+ return nil, ErrNoTokenInRequest
+}
+
// IgnoreDupes should be set to true if the internal duplicate header key check
// should ignore duplicate Header keys instead of reporting an error when
// duplicate Header keys are found.
diff --git a/jws/jwt.go b/jws/jwt.go
index 51090b4..67f18f7 100644
--- a/jws/jwt.go
+++ b/jws/jwt.go
@@ -1,6 +1,7 @@
package jws
import (
+ "net/http"
"time"
"github.com/SermoDigital/jose/crypto"
@@ -33,6 +34,18 @@
return nil
}
+// ParseJWTFromRequest tries to find the JWT in an http.Request.
+// This method will call ParseMultipartForm if there's no token in the header.
+func ParseJWTFromRequest(req *http.Request) (jwt.JWT, error) {
+ if b, ok := fromHeader(req); ok {
+ return ParseJWT(b)
+ }
+ if b, ok := fromForm(req); ok {
+ return ParseJWT(b)
+ }
+ return nil, ErrNoTokenInRequest
+}
+
// ParseJWT parses a serialized jwt.JWT into a physical jwt.JWT.
// If its payload isn't a set of claims (or able to be coerced into
// a set of claims) it'll return an error stating the