Skip to content

Commit

Permalink
add more auth unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
adwski committed May 16, 2024
1 parent 733951f commit 8a33952
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 1 deletion.
2 changes: 1 addition & 1 deletion internal/api/user/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (a *Auth) parseToken(signedToken string) (*Claims, error) {
return a.secret, nil
})
if err != nil {
return nil, fmt.Errorf("cannot parse token from session cookie: %w", err)
return nil, fmt.Errorf("cannot parse token: %w", err)
}
if !token.Valid {
return nil, errors.New("token is not valid")
Expand Down
113 changes: 113 additions & 0 deletions internal/api/user/auth/auth_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//nolint:lll // jwt tokens in test cases
package auth

import (
"testing"
"time"

"github.com/labstack/gommon/random"

"github.com/adwski/vidi/internal/api/user/model"
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
Expand Down Expand Up @@ -123,3 +126,113 @@ func TestAuth_MiddlewareUser(t *testing.T) {
var echoMWType echo.MiddlewareFunc
assert.IsType(t, echoMWType, echoMW)
}

func TestAuth_New(t *testing.T) {
a, err := NewAuth(&Config{Secret: random.String(minSecretLen - 1)})
require.Error(t, err)
require.Nil(t, a)

a, err = NewAuth(&Config{Secret: random.String(minSecretLen)})
require.NoError(t, err)
require.NotNil(t, a)
}

func TestAuth_parseToken(t *testing.T) {
type args struct {
token string
}
type want struct {
claims *Claims
errMsg string
}
tests := []struct {
name string
args args
want want
}{
{
name: "valid token",
args: args{
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJ0ZXN0dXNlcmlkIiwibmFtZSI6InRlc3RVc2VyIiwiZXhwIjo0NzE1ODM5MzY0fQ.QpWCWosIauu56J4LsEvpxBImwvl_mUoUMVyEeSRKL-M",
},
want: want{
claims: &Claims{
UserID: "testuserid",
Name: "testUser",
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: &jwt.NumericDate{Time: time.Unix(4715839364, 0)},
},
},
},
},
{
name: "expired token",
args: args{
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJ0ZXN0dXNlcmlkIiwibmFtZSI6InRlc3RVc2VyIiwiZXhwIjoxNzE1ODM5MzY0fQ.YF7N1-AooC5naxX9RygOsN-6UqwjS52lPLtA_amSk5k",
},
want: want{
errMsg: "cannot parse token: token has invalid claims: token is expired",
},
},
{
name: "empty userid token",
args: args{
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGVzdFVzZXIiLCJleHAiOjQ3MTU4MzkzNjR9.-xk_69_qo3_PY0_5-pD86q4hB3Ktp2Q3ivLrjYlN1xA",
},
want: want{
errMsg: "user id is empty",
},
},
{
name: "no expiration time",
args: args{
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGVzdFVzZXIifQ.xSfUPYDMFUoZFQAOnR6wy1vO-k1jJExhcbiJc5eIfgw",
},
want: want{
errMsg: "expiration claim is missing",
},
},
{
name: "invalid token",
args: args{
token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTcxNTg0MTQ1OSwiZXhwIjoxNzE1ODQ1MDU5fQ",
},
want: want{
errMsg: "cannot parse token: token is malformed: token contains an invalid number of segments",
},
},
{
name: "invalid algorithm",
args: args{
token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTcxNTg0MTQ1OSwiZXhwIjoxNzE1ODQ1MDU5fQ.Ab_S-6Ec6o1JKSy91PIurPMABMD4CeQjG1Js75mfw34yOkutoL8BptpNJ2w9SnWZGl_Jlbt3JAsrvlj4oG5vXpYAAJRg-EOOX14NM_rdFlUfYrJAEtbE5TPK81lcGPQSiPwFOVASsgIiFZIrT8szznTXJsINM-8AS08Qh3kLtuhQOOZ6",
},
want: want{
errMsg: "cannot parse token: token is unverifiable: error while executing keyfunc: unexpected signing method: ES512",
},
},
{
name: "no claims",
args: args{
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.hD10zcHw1CBGmgjuxh4tkVZ9SDMLQE-zNDX7xlcYObo",
},
want: want{
errMsg: "expiration claim is missing",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a, err := NewAuth(&Config{Secret: "superSecret"})
require.NoError(t, err)
require.NotNil(t, a)

claims, err := a.parseToken(tt.args.token)
if tt.want.errMsg != "" {
assert.EqualError(t, err, tt.want.errMsg)
} else {
require.NoError(t, err)
assert.Equal(t, tt.want.claims, claims)
}
})
}
}
91 changes: 91 additions & 0 deletions internal/api/user/auth/grpc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//nolint:lll // jwt tokens in test cases
package auth

import (
"context"
"testing"
"time"

"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/metadata"
)

func TestAuth_GRPCAuthFunc(t *testing.T) {
type args struct {
ctxFunc func() context.Context
}
type want struct {
claims *Claims
errMsg string
}
tests := []struct {
name string
args args
want want
}{
{
name: "valid token",
args: args{
ctxFunc: func() context.Context {
return metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("authorization", "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJ0ZXN0dXNlcmlkIiwibmFtZSI6InRlc3RVc2VyIiwiZXhwIjo0NzE1ODM5MzY0fQ.QpWCWosIauu56J4LsEvpxBImwvl_mUoUMVyEeSRKL-M"))
},
},
want: want{
claims: &Claims{
UserID: "testuserid",
Name: "testUser",
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: &jwt.NumericDate{Time: time.Unix(4715839364, 0)},
},
},
},
},
{
name: "invalid token",
args: args{
ctxFunc: func() context.Context {
return metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("authorization", "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQ"))
},
},
want: want{
errMsg: "invalid token",
},
},
{
name: "missing token",
args: args{
ctxFunc: func() context.Context {
return metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("qwe", "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQ"))
},
},
want: want{
errMsg: "missing token",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a, err := NewAuth(&Config{Secret: "superSecret"})
require.NoError(t, err)
require.NotNil(t, a)

outCtx, err := a.GRPCAuthFunc(tt.args.ctxFunc())
if tt.want.errMsg == "" {
require.NoError(t, err)
claims, ok := GetClaimsFromContext(outCtx)
require.True(t, ok)
require.Equal(t, tt.want.claims, claims)
} else {
require.Error(t, err)
require.Nil(t, outCtx)
}
})
}
}
71 changes: 71 additions & 0 deletions internal/api/user/auth/http_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package auth

import (
"testing"

"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
)

func TestGetClaimFromEchoContext(t *testing.T) {
type args struct {
ctxFunc func() echo.Context
}
type want struct {
errMsg string
}
tests := []struct {
name string
args args
want want
}{
{
name: "success",
args: args{
ctxFunc: func() echo.Context {
e := echo.New()
ctx := e.NewContext(nil, nil)
ctx.Set(sessionContextKey, &jwt.Token{Claims: &Claims{}})
return ctx
},
},
},
{
name: "no token",
args: args{
ctxFunc: func() echo.Context {
e := echo.New()
ctx := e.NewContext(nil, nil)
ctx.Set(sessionContextKey, "tuytu")
return ctx
},
},
want: want{errMsg: "cannot get jwt token from session context"},
},
{
name: "no claims",
args: args{
ctxFunc: func() echo.Context {
e := echo.New()
ctx := e.NewContext(nil, nil)
ctx.Set(sessionContextKey, &jwt.Token{Claims: Claims{}})
return ctx
},
},
want: want{errMsg: "cannot get claims from jwt token"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
claims, err := GetClaimFromEchoContext(tt.args.ctxFunc())
if tt.want.errMsg != "" {
assert.EqualError(t, err, tt.want.errMsg)
assert.Nil(t, claims)
} else {
assert.NoError(t, err)
assert.NotNil(t, claims)
}
})
}
}

0 comments on commit 8a33952

Please sign in to comment.