initial commit

This commit is contained in:
Eric Chiang
2016-07-25 13:00:28 -07:00
commit cab271f304
1438 changed files with 335968 additions and 0 deletions

127
vendor/gopkg.in/square/go-jose.v2/jwt/builder.go generated vendored Normal file
View File

@@ -0,0 +1,127 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import "gopkg.in/square/go-jose.v2"
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and
// errors are accumulated until the final call to CompactSerialize/FullSerialize.
type Builder struct {
transform func([]byte) (serializer, payload, error)
payload payload
serializer serializer
err error
}
type payload func(interface{}) ([]byte, error)
type serializer interface {
FullSerialize() string
CompactSerialize() (string, error)
}
// Signed creates builder for signed tokens.
func Signed(sig jose.Signer) *Builder {
return &Builder{
transform: func(b []byte) (serializer, payload, error) {
s, err := sig.Sign(b)
if err != nil {
return nil, nil, err
}
return s, s.Verify, nil
},
}
}
// Encrypted creates builder for encrypted tokens.
func Encrypted(enc jose.Encrypter) *Builder {
return &Builder{
transform: func(b []byte) (serializer, payload, error) {
e, err := enc.Encrypt(b)
if err != nil {
return nil, nil, err
}
return e, e.Decrypt, nil
},
}
}
// Claims encodes claims into the builder.
func (b *Builder) Claims(c interface{}) *Builder {
if b.transform == nil {
panic("Signer/Encrypter not set")
}
if b.payload != nil {
panic("Claims already set")
}
raw, err := marshalClaims(c)
if err != nil {
return &Builder{
err: err,
}
}
ser, pl, err := b.transform(raw)
return &Builder{
transform: b.transform,
serializer: ser,
payload: pl,
err: err,
}
}
// Token builds a JSONWebToken from provided data.
func (b *Builder) Token() (*JSONWebToken, error) {
if b.err != nil {
return nil, b.err
}
if b.payload == nil {
return nil, ErrInvalidClaims
}
return &JSONWebToken{b.payload}, nil
}
// FullSerialize serializes a token using the full serialization format.
func (b *Builder) FullSerialize() (string, error) {
if b.err != nil {
return "", b.err
}
if b.serializer == nil {
return "", ErrInvalidClaims
}
return b.serializer.FullSerialize(), nil
}
// CompactSerialize serializes a token using the compact serialization format.
func (b *Builder) CompactSerialize() (string, error) {
if b.err != nil {
return "", b.err
}
if b.serializer == nil {
return "", ErrInvalidClaims
}
return b.serializer.CompactSerialize()
}

83
vendor/gopkg.in/square/go-jose.v2/jwt/claims.go generated vendored Normal file
View File

@@ -0,0 +1,83 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"time"
"gopkg.in/square/go-jose.v2"
)
// Claims represents public claim values (as specified in RFC 7519).
type Claims struct {
Issuer string `json:"-"`
Subject string `json:"-"`
Audience []string `json:"-"`
Expiry time.Time `json:"-"`
NotBefore time.Time `json:"-"`
IssuedAt time.Time `json:"-"`
ID string `json:"-"`
}
type rawClaims struct {
Iss string `json:"iss,omitempty"`
Sub string `json:"sub,omitempty"`
Aud audience `json:"aud,omitempty"`
Exp NumericDate `json:"exp,omitempty"`
Nbf NumericDate `json:"nbf,omitempty"`
Iat NumericDate `json:"iat,omitempty"`
Jti string `json:"jti,omitempty"`
}
func (c *Claims) marshalJSON() ([]byte, error) {
t := rawClaims{
Iss: c.Issuer,
Sub: c.Subject,
Aud: audience(c.Audience),
Exp: TimeToNumericDate(c.Expiry),
Nbf: TimeToNumericDate(c.NotBefore),
Iat: TimeToNumericDate(c.IssuedAt),
Jti: c.ID,
}
b, err := jose.MarshalJSON(t)
if err != nil {
return nil, err
}
return b, err
}
func (c *Claims) unmarshalJSON(b []byte) error {
t := rawClaims{}
if err := jose.UnmarshalJSON(b, &t); err != nil {
return err
}
c.Issuer = t.Iss
c.Subject = t.Sub
c.Audience = []string(t.Aud)
c.Expiry = t.Exp.Time()
c.NotBefore = t.Nbf.Time()
c.IssuedAt = t.Iat.Time()
c.ID = t.Jti
return nil
}

58
vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestEncodeClaims(t *testing.T) {
now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)
c := Claims{
Issuer: "issuer",
Subject: "subject",
Audience: []string{"a1", "a2"},
IssuedAt: now,
Expiry: now.Add(1 * time.Hour),
}
b, err := c.marshalJSON()
assert.NoError(t, err)
expected := `{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}`
assert.Equal(t, expected, string(b))
}
func TestDecodeClaims(t *testing.T) {
s := []byte(`{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}`)
now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)
c := Claims{}
err := c.unmarshalJSON(s)
assert.NoError(t, err)
assert.Equal(t, "issuer", c.Issuer)
assert.Equal(t, "subject", c.Subject)
assert.Equal(t, []string{"a1", "a2"}, c.Audience)
assert.True(t, now.Equal(c.IssuedAt))
assert.True(t, now.Add(1*time.Hour).Equal(c.Expiry))
}

47
vendor/gopkg.in/square/go-jose.v2/jwt/errors.go generated vendored Normal file
View File

@@ -0,0 +1,47 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import "errors"
// ErrUnmarshalAudience indicates that aud claim could not be unmarshalled.
var ErrUnmarshalAudience = errors.New("square/go-jose/jwt: expected string or array value to unmarshal to Audience")
// ErrUnmarshalNumericDate indicates that JWT NumericDate could not be unmarshalled.
var ErrUnmarshalNumericDate = errors.New("square/go-jose/jwt: expected number value to unmarshal NumericDate")
// ErrInvalidClaims indicates that given claims have invalid type.
var ErrInvalidClaims = errors.New("square/go-jose/jwt: expected claims to be value convertible into JSON object")
// ErrInvalidIssuer indicates invalid iss claim.
var ErrInvalidIssuer = errors.New("square/go-jose/jwt: validation failed, invalid issuer claim (iss)")
// ErrInvalidSubject indicates invalid sub claim.
var ErrInvalidSubject = errors.New("square/go-jose/jwt: validation failed, invalid subject claim (sub)")
// ErrInvalidAudience indicated invalid aud claim.
var ErrInvalidAudience = errors.New("square/go-jose/jwt: validation failed, invalid audience claim (aud)")
// ErrInvalidID indicates invalid jti claim.
var ErrInvalidID = errors.New("square/go-jose/jwt: validation failed, invalid ID claim (jti)")
// ErrNotValidYet indicates that token is used before time indicated in nbf claim.
var ErrNotValidYet = errors.New("square/go-jose/jwt: validation failed, token not valid yet (nbf)")
// ErrExpired indicates that token is used after expiry time indicated in exp claim.
var ErrExpired = errors.New("square/go-jose/jwt: validation failed, token is expired (exp)")

179
vendor/gopkg.in/square/go-jose.v2/jwt/json.go generated vendored Normal file
View File

@@ -0,0 +1,179 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"math"
"reflect"
"strconv"
"time"
"gopkg.in/square/go-jose.v2"
)
// NumericDate represents date and time as the number of seconds since the
// epoch, including leap seconds. Non-integer values can be represented
// in the serialized format, but we round to the nearest second.
type NumericDate int64
// TimeToNumericDate converts time.Time value into NumericDate.
func TimeToNumericDate(t time.Time) NumericDate {
if t.IsZero() {
return NumericDate(0)
}
// While RFC 7519 technically states that NumericDate values may be
// non-integer values, we don't bother serializing timestamps in
// claims with sub-second accurancy and just round to the nearest
// second instead. Not convined sub-second accuracy is useful here.
return NumericDate(t.Unix())
}
// MarshalJSON serializes the given NumericDate into its JSON representation.
func (n NumericDate) MarshalJSON() ([]byte, error) {
return []byte(strconv.FormatInt(int64(n), 10)), nil
}
// UnmarshalJSON reads a date from its JSON representation.
func (n *NumericDate) UnmarshalJSON(b []byte) error {
s := string(b)
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return ErrUnmarshalNumericDate
}
*n = NumericDate(f)
return nil
}
// Time returns time.Time representation of NumericDate.
func (n NumericDate) Time() time.Time {
i, f := math.Modf(float64(n))
return time.Unix(int64(i), int64(f*float64(time.Second)))
}
type audience []string
func (s *audience) UnmarshalJSON(b []byte) error {
var v interface{}
if err := jose.UnmarshalJSON(b, &v); err != nil {
return err
}
switch v := v.(type) {
case string:
*s = append(*s, v)
case []interface{}:
a := make([]string, len(v))
for i, e := range v {
s, ok := e.(string)
if !ok {
return ErrUnmarshalAudience
}
a[i] = s
}
*s = a
default:
return ErrUnmarshalAudience
}
return nil
}
var claimsType = reflect.TypeOf((*Claims)(nil)).Elem()
func publicClaims(cl interface{}) (*Claims, error) {
v := reflect.ValueOf(cl)
if v.IsNil() || v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return nil, ErrInvalidClaims
}
v = v.Elem()
f := v.FieldByName("Claims")
if !f.IsValid() || f.Type() != claimsType {
return nil, nil
}
c := f.Addr().Interface().(*Claims)
return c, nil
}
func marshalClaims(cl interface{}) ([]byte, error) {
switch cl := cl.(type) {
case *Claims:
return cl.marshalJSON()
case map[string]interface{}:
return jose.MarshalJSON(cl)
}
public, err := publicClaims(cl)
if err != nil {
return nil, err
}
// i doesn't contain nested jwt.Claims
if public == nil {
return jose.MarshalJSON(cl)
}
// marshal jwt.Claims
b1, err := public.marshalJSON()
if err != nil {
return nil, err
}
// marshal private claims
b2, err := jose.MarshalJSON(cl)
if err != nil {
return nil, err
}
// merge claims
r := make([]byte, len(b1)+len(b2)-1)
copy(r, b1)
r[len(b1)-1] = ','
copy(r[len(b1):], b2[1:])
return r, nil
}
func unmarshalClaims(b []byte, cl interface{}) error {
switch cl := cl.(type) {
case *Claims:
return cl.unmarshalJSON(b)
case map[string]interface{}:
return jose.UnmarshalJSON(b, cl)
}
if err := jose.UnmarshalJSON(b, cl); err != nil {
return err
}
public, err := publicClaims(cl)
if err != nil {
return err
}
// unmarshal jwt.Claims
if public != nil {
if err := public.unmarshalJSON(b); err != nil {
return err
}
}
return nil
}

54
vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go generated vendored Normal file
View File

@@ -0,0 +1,54 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import "gopkg.in/square/go-jose.v2"
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
type JSONWebToken struct {
payload func(k interface{}) ([]byte, error)
}
// Claims deserializes a JSONWebToken into dest using the provided key.
func (t *JSONWebToken) Claims(dest interface{}, key interface{}) error {
b, err := t.payload(key)
if err != nil {
return err
}
return unmarshalClaims(b, dest)
}
// ParseSigned parses token from JWS form.
func ParseSigned(s string) (*JSONWebToken, error) {
sig, err := jose.ParseSigned(s)
if err != nil {
return nil, err
}
return &JSONWebToken{sig.Verify}, nil
}
// ParseEncrypted parses token from JWE form.
func ParseEncrypted(s string) (*JSONWebToken, error) {
enc, err := jose.ParseEncrypted(s)
if err != nil {
return nil, err
}
return &JSONWebToken{enc.Decrypt}, nil
}

77
vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go generated vendored Normal file
View File

@@ -0,0 +1,77 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/square/go-jose.v2"
)
var encryptionKey = []byte("secret")
var rawToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0.Y6_PfQHrzRJ_Vlxij5VI07-pgDIuJNN3Z_g5sSaGQ0c`
type customClaims struct {
Claims
Scopes []string `json:"scopes,omitempty"`
}
func TestDecodeToken(t *testing.T) {
tok, err := ParseSigned(rawToken)
assert.NoError(t, err)
c := &Claims{}
if assert.NoError(t, tok.Claims(c, encryptionKey)) {
assert.Equal(t, c.Subject, "subject")
assert.Equal(t, c.Issuer, "issuer")
}
c2 := &customClaims{}
if assert.NoError(t, tok.Claims(c2, encryptionKey)) {
assert.Equal(t, c2.Subject, "subject")
assert.Equal(t, c2.Issuer, "issuer")
assert.Equal(t, c2.Scopes, []string{"s1", "s2"})
}
}
func TestEncodeToken(t *testing.T) {
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: encryptionKey}, &jose.SignerOptions{})
require.NoError(t, err)
c := &customClaims{
Claims: Claims{
Subject: "subject",
Issuer: "issuer",
},
Scopes: []string{"s1", "s2"},
}
raw, err := Signed(signer).Claims(c).CompactSerialize()
require.NoError(t, err)
tok, err := ParseSigned(raw)
require.NoError(t, err)
c2 := &customClaims{}
if assert.NoError(t, tok.Claims(c2, encryptionKey)) {
assert.Equal(t, c2.Subject, "subject")
assert.Equal(t, c2.Issuer, "issuer")
assert.Equal(t, c2.Scopes, []string{"s1", "s2"})
}
}

87
vendor/gopkg.in/square/go-jose.v2/jwt/validation.go generated vendored Normal file
View File

@@ -0,0 +1,87 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import "time"
const (
// DefaultLeeway defines the default leeway for matching NotBefore/Expiry claims.
DefaultLeeway = 1.0 * time.Minute
)
// Expected defines values used for claims validation.
type Expected struct {
Issuer string
Subject string
Audience []string
ID string
Time time.Time
}
// WithTime copies expectations with new time.
func (e Expected) WithTime(t time.Time) Expected {
e.Time = t
return e
}
// Validate checks claims in a token against expected values.
// A default leeway value of one minute is used to compare time values.
func (c Claims) Validate(e Expected) error {
return c.ValidateWithLeeway(e, DefaultLeeway)
}
// ValidateWithLeeway checks claims in a token against expected values. A
// custom leeway may be specified for comparing time values. You may pass a
// zero value to check time values with no leeway, but you should not that
// numeric date values are rounded to the nearest second and sub-second
// precision is not supported.
func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error {
if e.Issuer != "" && e.Issuer != c.Issuer {
return ErrInvalidIssuer
}
if e.Subject != "" && e.Subject != c.Subject {
return ErrInvalidSubject
}
if e.ID != "" && e.ID != c.ID {
return ErrInvalidID
}
if len(e.Audience) != 0 {
if len(e.Audience) != len(c.Audience) {
return ErrInvalidAudience
}
for i, a := range e.Audience {
if a != c.Audience[i] {
return ErrInvalidAudience
}
}
}
if !e.Time.IsZero() && e.Time.Add(leeway).Before(c.NotBefore) {
return ErrNotValidYet
}
if !e.Time.IsZero() && e.Time.Add(-leeway).After(c.Expiry) {
return ErrExpired
}
return nil
}

View File

@@ -0,0 +1,90 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestFieldsMatch(t *testing.T) {
c := Claims{
Issuer: "issuer",
Subject: "subject",
Audience: []string{"a1", "a2"},
ID: "42",
}
assert.NoError(t, c.Validate(Expected{Issuer: "issuer"}))
err := c.Validate(Expected{Issuer: "invalid-issuer"})
if assert.Error(t, err) {
assert.Equal(t, err, ErrInvalidIssuer)
}
assert.NoError(t, c.Validate(Expected{Subject: "subject"}))
err = c.Validate(Expected{Subject: "invalid-subject"})
if assert.Error(t, err) {
assert.Equal(t, err, ErrInvalidSubject)
}
assert.NoError(t, c.Validate(Expected{Audience: []string{"a1", "a2"}}))
err = c.Validate(Expected{Audience: []string{"invalid-audience"}})
if assert.Error(t, err) {
assert.Equal(t, err, ErrInvalidAudience)
}
assert.NoError(t, c.Validate(Expected{ID: "42"}))
err = c.Validate(Expected{ID: "invalid-id"})
if assert.Error(t, err) {
assert.Equal(t, err, ErrInvalidID)
}
}
func TestExpiryAndNotBefore(t *testing.T) {
now := time.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC)
twelveHoursAgo := now.Add(-12 * time.Hour)
c := Claims{
IssuedAt: twelveHoursAgo,
NotBefore: twelveHoursAgo,
Expiry: now,
}
// expired - default leeway (1 minute)
assert.NoError(t, c.Validate(Expected{Time: now}))
err := c.Validate(Expected{Time: now.Add(2 * DefaultLeeway)})
if assert.Error(t, err) {
assert.Equal(t, err, ErrExpired)
}
// expired - no leeway
assert.NoError(t, c.ValidateWithLeeway(Expected{Time: now}, 0))
err = c.ValidateWithLeeway(Expected{Time: now.Add(1 * time.Second)}, 0)
if assert.Error(t, err) {
assert.Equal(t, err, ErrExpired)
}
// not before - default leeway (1 minute)
assert.NoError(t, c.Validate(Expected{Time: twelveHoursAgo}))
err = c.Validate(Expected{Time: twelveHoursAgo.Add(-2 * DefaultLeeway)})
if assert.Error(t, err) {
assert.Equal(t, err, ErrNotValidYet)
}
}