rpc/jwt_test.go
// Copyright © 2016 Asteris, LLC
//
// 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 rpc_test
import (
"fmt"
"strings"
"testing"
"time"
"github.com/asteris-llc/converge/rpc"
jwt "github.com/dgrijalva/jwt-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func TestJWTAuth(t *testing.T) {
t.Parallel()
secret := "secret"
token := rpc.NewJWTAuth(secret)
t.Run("New", func(t *testing.T) {
_, err := token.New()
require.NoError(t, err)
})
t.Run("Verify", func(t *testing.T) {
t.Run("good", func(t *testing.T) {
signed, err := token.New()
require.NoError(t, err)
err = token.Verify(signed)
assert.NoError(t, err)
})
t.Run("bad", func(t *testing.T) {
t.Run("nonsense", func(t *testing.T) {
err := token.Verify("blah")
assert.Error(t, err)
})
t.Run("bad key", func(t *testing.T) {
badSecret := "bad secret"
require.NotEqual(t, badSecret, secret, "can't testing the wrong secret, we have the same one")
bad, err := rpc.NewJWTAuth(badSecret).New()
require.NoError(t, err)
err = token.Verify(bad)
assert.Error(t, err)
})
t.Run("wrong hashing algorithm", func(t *testing.T) {
method := "HS256"
require.NotEqual(t, method, rpc.JWTAlg, "can't test the wrong alg, we have the same one")
badTok := jwt.NewWithClaims(jwt.GetSigningMethod(method), jwt.StandardClaims{})
bad, err := badTok.SignedString([]byte(secret))
require.NoError(t, err)
err = token.Verify(bad)
if assert.Error(t, err) {
assert.EqualError(t, err, "unexpected signing method: "+method)
}
})
t.Run("missing issued at", func(t *testing.T) {
badTok := jwt.NewWithClaims(
jwt.GetSigningMethod(rpc.JWTAlg),
jwt.StandardClaims{
ExpiresAt: time.Now().Unix(),
},
)
bad, err := badTok.SignedString([]byte(secret))
require.NoError(t, err)
err = token.Verify(bad)
if assert.Error(t, err) {
assert.EqualError(t, err, "issued at was invalid")
}
})
t.Run("missing expires at", func(t *testing.T) {
badTok := jwt.NewWithClaims(
jwt.GetSigningMethod(rpc.JWTAlg),
jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
},
)
bad, err := badTok.SignedString([]byte(secret))
require.NoError(t, err)
err = token.Verify(bad)
if assert.Error(t, err) {
assert.EqualError(t, err, "expires at was invalid")
}
})
t.Run("lifetime is too large", func(t *testing.T) {
badTok := jwt.NewWithClaims(
jwt.GetSigningMethod(rpc.JWTAlg),
jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(2 * rpc.JWTLifetime).Unix(),
},
)
bad, err := badTok.SignedString([]byte(secret))
require.NoError(t, err)
err = token.Verify(bad)
if assert.Error(t, err) {
assert.EqualError(t, err, fmt.Sprintf("lifetime too large. Expected %s, was %s", rpc.JWTLifetime, 2*rpc.JWTLifetime))
}
})
})
})
t.Run("GetRequestMetadata", func(t *testing.T) {
headers, err := token.GetRequestMetadata(context.Background())
assert.Nil(t, err)
require.Contains(t, headers, "authorization")
require.True(t, strings.HasPrefix(headers["authorization"], "BEARER "))
err = token.Verify(strings.TrimLeft(headers["authorization"], "BEARER "))
assert.NoError(t, err)
})
t.Run("RequireTransportSecurity", func(t *testing.T) {
assert.False(t, token.RequireTransportSecurity())
})
}