src.dualinventive.com/go/mtinfo-go/authgrpc_test.go

455 lines
12 KiB
Go

package mtinfo
import (
"crypto/rsa"
"errors"
"io/ioutil"
"os"
"testing"
"time"
"github.com/dgrijalva/jwt-go.git"
"google.golang.org/grpc/metadata"
"golang.org/x/net/context"
"google.golang.org/grpc"
"github.com/stretchr/testify/assert"
auth "src.dualinventive.com/go/authentication-service/grpc"
)
const (
someUsername = "some-username"
someCompanyCode = "some-company-code"
somePassword = "some-password"
someUserAgent = "some-user-agent"
someToken = "abc"
someResetCode = "def"
)
var mock *testGrpcAuthClient //nolint:gochecknoglobals
var client grpcAuthServiceClient //nolint:gochecknoglobals
var pk *rsa.PrivateKey //nolint:gochecknoglobals
func TestMain(m *testing.M) {
code := m.Run()
os.Exit(code)
}
func TestGrpcAuthServiceClient_Login(t *testing.T) {
before(t)
mock.resp = &auth.LoginResponse{Token: &auth.Token{Secret: someToken}}
tkn, err := client.Login(someUsername, someCompanyCode, somePassword)
assert.Nil(t, err)
in := mock.in.(*auth.LoginRequest)
assert.Equal(t, in.Credentials.Username, someUsername)
assert.Equal(t, in.Credentials.CompanyCode, someCompanyCode)
assert.Equal(t, in.Credentials.Password, somePassword)
assert.Equal(t, tkn, someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_Login_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.LoginResponse{}
mock.err = errors.New("some-error")
_, err := client.Login(someUsername, someCompanyCode, somePassword)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_Logout(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
err := client.Logout(someToken)
assert.Nil(t, err)
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_Logout_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
mock.err = errors.New("some-error")
err := client.Logout(someToken)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_Me(t *testing.T) {
before(t)
mock.resp = &auth.MeResponse{User: &auth.User{
UserId: 1,
UserName: "test",
Company: &auth.Company{Id: 1, Name: "test", Code: "tst"},
Roles: []*auth.Role{{Name: "role", Rights: []string{"right"}}}}}
usr, err := client.Me(someToken)
assert.Nil(t, err)
assert.Equal(t, usr.ID, uint(1))
assert.Equal(t, usr.Name, "test")
assert.Equal(t, usr.Company.Name, "test")
assert.Equal(t, usr.Company.Code, "tst")
assert.Equal(t, usr.Company.ID, uint(1))
assert.Len(t, usr.Roles, 1)
assert.Equal(t, usr.Roles[0].Name, "role")
assert.Len(t, usr.Roles[0].Rights, 1)
assert.Equal(t, usr.Roles[0].Rights[0], Right("right"))
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_Me_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.MeResponse{}
mock.err = errors.New("some-error")
_, err := client.Me(someToken)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_RequestPasswordReset(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
err := client.RequestPasswordReset(someUsername)
assert.Nil(t, err)
in := mock.in.(*auth.RequestPasswordResetRequest)
assert.Equal(t, in.UserName, someUsername)
}
func TestGrpcAuthServiceClient_RequestPasswordReset_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
mock.err = errors.New("some-error")
err := client.RequestPasswordReset(someToken)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_RedeemPasswordReset(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
err := client.RedeemPasswordReset(someUsername, someResetCode, somePassword, somePassword)
assert.Nil(t, err)
in := mock.in.(*auth.RedeemPasswordResetRequest)
assert.Equal(t, in.UserName, someUsername)
assert.Equal(t, in.ResetCode, someResetCode)
assert.Equal(t, in.Password, somePassword)
assert.Equal(t, in.PasswordVerify, somePassword)
}
func TestGrpcAuthServiceClient_RedeemPasswordReset_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
mock.err = errors.New("some-error")
err := client.RedeemPasswordReset(someUsername, someResetCode, somePassword, somePassword)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_ListTokens(t *testing.T) {
before(t)
mock.resp = &auth.ListTokensResponse{Tokens: []*auth.OpaqueToken{
{UserAgent: "2", OpaqueId: "abc"},
{UserAgent: "1", OpaqueId: "def"},
}}
list, err := client.ListTokens(someToken)
assert.Nil(t, err)
assert.Len(t, list, 2)
assert.Equal(t, list["abc"], "2")
assert.Equal(t, list["def"], "1")
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_ListTokens_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.ListTokensResponse{}
mock.err = errors.New("some-error")
_, err := client.ListTokens(someToken)
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_DeleteToken(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
err := client.DeleteToken(someToken, "1")
assert.Nil(t, err)
in := mock.in.(*auth.DeleteTokenRequest)
assert.Equal(t, in.OpaqueId, "1")
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_DeleteToken_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.Empty{}
mock.err = errors.New("some-error")
err := client.DeleteToken(someToken, "")
assert.NotNil(t, err)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_VerifyTokenRemotely(t *testing.T) {
before(t)
mock.resp = &auth.VerifyTokenResponse{Valid: true}
valid, err := client.VerifyTokenRemotely(someToken)
assert.Nil(t, err)
assert.True(t, valid)
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_VerifyTokenRemotely_WhenGrpcErrorMessage(t *testing.T) {
before(t)
mock.resp = &auth.VerifyTokenResponse{}
mock.err = errors.New("some-error")
valid, err := client.VerifyTokenRemotely(someToken)
assert.NotNil(t, err)
assert.False(t, valid)
assert.EqualError(t, err, "some-error")
}
func TestGrpcAuthServiceClient_VerifyToken_WithPublicKey_DecryptsLocally(t *testing.T) {
before(t)
valid, err := client.VerifyToken(randomToken(t))
assert.Nil(t, err)
assert.True(t, valid)
assert.Nil(t, mock.ctx)
}
func TestGrpcAuthServiceClient_VerifyToken_WithPublicKeyWithValidRights_DecryptsLocally(t *testing.T) {
before(t)
valid, err := client.VerifyToken(randomToken(t), "a", "b")
assert.Nil(t, err)
assert.True(t, valid)
assert.Nil(t, mock.ctx)
}
func TestGrpcAuthServiceClient_VerifyToken_WithPublicKeyWithInvalidRights_DecryptsLocally(t *testing.T) {
before(t)
valid, err := client.VerifyToken(randomToken(t), "a", "b", "d")
assert.Nil(t, err)
assert.False(t, valid)
assert.Nil(t, mock.ctx)
}
func TestGrpcAuthServiceClient_VerifyToken_WithBadPublicKey_DecryptsLocallyAndReturnsError(t *testing.T) {
before(t)
badPublicKey, err := configurePublicKey("./testdata/key_rsa_bad.pub")
assert.Nil(t, err)
client.publicKey = badPublicKey
valid, err := client.VerifyToken(randomToken(t))
assert.NotNil(t, err)
assert.False(t, valid)
assert.EqualError(t, err, "error parsing jwt token: crypto/rsa: verification error")
}
func TestGrpcAuthServiceClient_VerifyTokenWithoutPublicKey_DecryptsRemotely(t *testing.T) {
before(t)
mock.resp = &auth.VerifyTokenResponse{Valid: true}
client.publicKey = nil
valid, err := client.VerifyToken(someToken)
assert.Nil(t, err)
assert.True(t, valid)
in := mock.in.(*auth.VerifyTokenRequest)
assert.Len(t, in.Rights, 0)
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func TestGrpcAuthServiceClient_VerifyTokenWithoutPublicKeyWithRights_DecryptsRemotely(t *testing.T) {
before(t)
mock.resp = &auth.VerifyTokenResponse{Valid: true}
client.publicKey = nil
valid, err := client.VerifyToken(someToken, "a", "b", "c")
assert.Nil(t, err)
assert.True(t, valid)
in := mock.in.(*auth.VerifyTokenRequest)
assert.Len(t, in.Rights, 3)
assert.Contains(t, in.Rights, "a")
assert.Contains(t, in.Rights, "b")
assert.Contains(t, in.Rights, "c")
assert.Equal(t, getValue(mock.ctx, "token"), someToken)
assert.Equal(t, getValue(mock.ctx, "userAgent"), someUserAgent)
}
func before(t *testing.T) {
publicKey, err := configurePublicKey("./testdata/key_rsa.pub")
assert.Nil(t, err)
privateKey, err := configurePrivateKey("./testdata/key_rsa")
assert.Nil(t, err)
mock = &testGrpcAuthClient{}
client = grpcAuthServiceClient{
client: mock,
userAgent: someUserAgent,
publicKey: publicKey,
}
pk = privateKey
}
func configurePrivateKey(filepath string) (*rsa.PrivateKey, error) {
f, err := ioutil.ReadFile(filepath)
if err != nil {
return nil, err
}
return jwt.ParseRSAPrivateKeyFromPEM(f)
}
func randomToken(t *testing.T) string {
expirationTime := time.Now().Add(time.Second * 3)
claims := claims{
Rights: []string{"a", "b", "c"},
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
tokenString, err := token.SignedString(pk)
assert.Nil(t, err)
return tokenString
}
type claims struct {
Rights []string
jwt.StandardClaims
}
func getValue(ctx context.Context, s string) string {
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
return ""
}
raw := md.Get(s)
if raw == nil {
return ""
}
if len(raw) == 0 {
return ""
}
return raw[0]
}
type testGrpcAuthClient struct {
ctx context.Context
in interface{}
opts []grpc.CallOption
resp interface{}
err error
}
func (m *testGrpcAuthClient) Login(
ctx context.Context,
in *auth.LoginRequest,
opts ...grpc.CallOption) (*auth.LoginResponse, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.LoginResponse), m.err
}
func (m *testGrpcAuthClient) Logout(
ctx context.Context,
in *auth.Empty,
opts ...grpc.CallOption) (*auth.Empty, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.Empty), m.err
}
func (m *testGrpcAuthClient) VerifyToken(
ctx context.Context,
in *auth.VerifyTokenRequest,
opts ...grpc.CallOption) (*auth.VerifyTokenResponse, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.VerifyTokenResponse), m.err
}
func (m *testGrpcAuthClient) Me(
ctx context.Context,
in *auth.Empty,
opts ...grpc.CallOption) (*auth.MeResponse, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.MeResponse), m.err
}
func (m *testGrpcAuthClient) RequestPasswordReset(
ctx context.Context,
in *auth.RequestPasswordResetRequest,
opts ...grpc.CallOption) (*auth.Empty, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.Empty), m.err
}
func (m *testGrpcAuthClient) RedeemPasswordReset(
ctx context.Context,
in *auth.RedeemPasswordResetRequest,
opts ...grpc.CallOption) (*auth.Empty, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.Empty), m.err
}
func (m *testGrpcAuthClient) ListTokens(
ctx context.Context,
in *auth.Empty,
opts ...grpc.CallOption) (*auth.ListTokensResponse, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.ListTokensResponse), m.err
}
func (m *testGrpcAuthClient) DeleteToken(
ctx context.Context,
in *auth.DeleteTokenRequest,
opts ...grpc.CallOption) (*auth.Empty, error) {
m.ctx = ctx
m.in = in
m.opts = opts
return m.resp.(*auth.Empty), m.err
}