diff options
author | Steve Manuel <nilslice@gmail.com> | 2016-10-19 13:50:05 -0700 |
---|---|---|
committer | Steve Manuel <nilslice@gmail.com> | 2016-10-19 13:50:05 -0700 |
commit | ea078f9b4221332b9f63cc4e178aa814eec06e4f (patch) | |
tree | a90da6f77f265ce63c82da73f502f324bfb89ebc /cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go | |
parent | ea8ea4c22662aa082181a6c456ec56acf2bd777c (diff) |
vendoring all the dependencies into vendor directory prior to build step, which still vendors ponzu core code
Diffstat (limited to 'cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go')
-rw-r--r-- | cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go b/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go new file mode 100644 index 0000000..6d7eaa3 --- /dev/null +++ b/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go @@ -0,0 +1,204 @@ +package jwt + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "strings" +) + +var ( + privateKey = []byte("") + defaultHeader = header{Typ: "JWT", Alg: "HS256"} + registeredClaims = []string{"iss", "sub", "aud", "exp", "nbf", "iat", "jti"} +) + +type header struct { + Typ string `json:"typ"` + Alg string `json:"alg"` +} + +type payload map[string]interface{} + +type encoded struct { + token string +} +type decoded struct { + header string + payload string +} + +type signedDecoded struct { + decoded + signature string +} + +func newEncoded(claims map[string]interface{}) (encoded, error) { + header, err := json.Marshal(defaultHeader) + if err != nil { + return encoded{}, err + } + + for _, claim := range registeredClaims { + if _, ok := claims[claim]; !ok { + claims[claim] = nil + } + } + + payload, err := json.Marshal(claims) + if err != nil { + return encoded{}, err + } + + d := decoded{header: string(header), payload: string(payload)} + + d.encodeInternal() + signed, err := d.sign() + if err != nil { + return encoded{}, err + } + + token := signed.token() + e := encoded{token: token} + return e, nil +} + +func newDecoded(token string) (decoded, error) { + e := encoded{token: token} + d, err := e.parseToken() + if err != nil { + return d, nil + } + + return d, nil +} + +func encodeToString(src []byte) string { + return base64.RawURLEncoding.EncodeToString(src) +} + +func (d decoded) getHeader() []byte { + return []byte(d.header) +} + +func (d decoded) getPayload() []byte { + return []byte(d.payload) +} + +func (sd signedDecoded) getSignature() []byte { + return []byte(sd.signature) +} + +func (d *decoded) encodeInternal() { + d.header = encodeToString(d.getHeader()) + d.payload = encodeToString(d.getPayload()) +} + +func (d decoded) dot(internals ...string) string { + return strings.Join(internals, ".") +} + +func (d *decoded) sign() (signedDecoded, error) { + if d.header == "" || d.payload == "" { + return signedDecoded{}, errors.New("Missing header or payload on Decoded") + } + + unsigned := d.dot(d.header, d.payload) + + hash := hmac.New(sha256.New, privateKey) + _, err := hash.Write([]byte(unsigned)) + if err != nil { + return signedDecoded{}, err + } + + signed := signedDecoded{decoded: *d} + signed.signature = encodeToString(hash.Sum(nil)) + + return signed, nil +} + +func (sd signedDecoded) token() string { + return fmt.Sprintf("%s.%s.%s", sd.getHeader(), sd.getPayload(), sd.getSignature()) +} + +func (sd signedDecoded) verify(enc encoded) bool { + if sd.token() == enc.token { + return true + } + return false +} + +func (e encoded) parseToken() (decoded, error) { + parts := strings.Split(e.token, ".") + if len(parts) != 3 { + return decoded{}, errors.New("Error: incorrect # of results from string parsing") + } + + d := decoded{ + header: parts[0], + payload: parts[1], + } + + return d, nil +} + +// New returns a token (string) and error. The token is a fully qualified JWT to be sent to a client via HTTP Header or other method. Error returned will be from the newEncoded unexported function. +func New(claims map[string]interface{}) (string, error) { + enc, err := newEncoded(claims) + if err != nil { + return "", err + } + + return enc.token, nil +} + +// Passes returns a bool indicating whether a token (string) provided has been signed by our server. If true, the client is authenticated and may proceed. +func Passes(token string) bool { + dec, err := newDecoded(token) + if err != nil { + // may want to log some error here so we have visibility + // intentionally simplifying return type to bool for ease + // of use in API. Caller should only do `if auth.Passes(str) {}` + return false + } + signed, err := dec.sign() + if err != nil { + return false + } + + return signed.verify(encoded{token: token}) +} + +// GetClaims() returns a token's claims, allowing +// you to check the values to make sure they match +func GetClaims(token string) map[string]interface{} { + // decode the token + dec, err := newDecoded(token) + if err != nil { + return nil + } + + // base64 decode payload + payload, err := base64.RawURLEncoding.DecodeString(dec.payload) + if err != nil { + return nil + } + + dst := map[string]interface{}{} + err = json.Unmarshal(payload, &dst) + if err != nil { + return nil + } + + return dst + +} + +// Secret is a helper function to set the unexported privateKey variable used when signing and verifying tokens. +// Its argument is type []byte since we expect users to read this value from a file which can be excluded from source code. +func Secret(key []byte) { + privateKey = key +} |