initial commit
This commit is contained in:
127
vendor/gopkg.in/square/go-jose.v2/jwt/builder.go
generated
vendored
Normal file
127
vendor/gopkg.in/square/go-jose.v2/jwt/builder.go
generated
vendored
Normal 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
83
vendor/gopkg.in/square/go-jose.v2/jwt/claims.go
generated
vendored
Normal 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
58
vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go
generated
vendored
Normal 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
47
vendor/gopkg.in/square/go-jose.v2/jwt/errors.go
generated
vendored
Normal 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
179
vendor/gopkg.in/square/go-jose.v2/jwt/json.go
generated
vendored
Normal 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
54
vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go
generated
vendored
Normal 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
77
vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go
generated
vendored
Normal 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
87
vendor/gopkg.in/square/go-jose.v2/jwt/validation.go
generated
vendored
Normal 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
|
||||
}
|
||||
90
vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go
generated
vendored
Normal file
90
vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user