297 lines
6.8 KiB
Go
297 lines
6.8 KiB
Go
package oauth2
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
gojwt "github.com/dgrijalva/jwt-go"
|
|
)
|
|
|
|
type MockTokenizer struct {
|
|
Principal Principal
|
|
ValidErr error
|
|
Token Token
|
|
CreateErr error
|
|
ExtendErr error
|
|
}
|
|
|
|
func (m *MockTokenizer) ValidPrincipal(ctx context.Context, token Token, duration time.Duration) (Principal, error) {
|
|
return m.Principal, m.ValidErr
|
|
}
|
|
|
|
func (m *MockTokenizer) Create(ctx context.Context, p Principal) (Token, error) {
|
|
return m.Token, m.CreateErr
|
|
}
|
|
|
|
func (m *MockTokenizer) ExtendedPrincipal(ctx context.Context, principal Principal, extension time.Duration) (Principal, error) {
|
|
return principal, m.ExtendErr
|
|
}
|
|
|
|
func (m *MockTokenizer) GetClaims(tokenString string) (gojwt.MapClaims, error) {
|
|
return gojwt.MapClaims{}, nil
|
|
}
|
|
|
|
func TestCookieAuthorize(t *testing.T) {
|
|
var test = []struct {
|
|
Desc string
|
|
Value string
|
|
Expected string
|
|
Err error
|
|
CreateErr error
|
|
}{
|
|
{
|
|
Desc: "Unable to create token",
|
|
Err: ErrAuthentication,
|
|
CreateErr: ErrAuthentication,
|
|
},
|
|
{
|
|
Desc: "Cookie token extracted",
|
|
Value: "reallyimportant",
|
|
Expected: "reallyimportant",
|
|
Err: nil,
|
|
},
|
|
}
|
|
for _, test := range test {
|
|
cook := cookie{
|
|
Lifespan: 1 * time.Second,
|
|
Now: func() time.Time {
|
|
return time.Unix(0, 0)
|
|
},
|
|
Tokens: &MockTokenizer{
|
|
Token: Token(test.Value),
|
|
CreateErr: test.CreateErr,
|
|
},
|
|
}
|
|
principal := Principal{}
|
|
w := httptest.NewRecorder()
|
|
err := cook.Authorize(context.Background(), w, principal)
|
|
if err != test.Err {
|
|
t.Fatalf("Cookie extract error; expected %v actual %v", test.Err, err)
|
|
}
|
|
if test.Err != nil {
|
|
continue
|
|
}
|
|
|
|
cookies := w.Header()["Set-Cookie"]
|
|
|
|
if len(cookies) == 0 {
|
|
t.Fatal("Expected some cookies but got zero")
|
|
}
|
|
log.Printf("%s", cookies[0])
|
|
if !strings.Contains(cookies[0], fmt.Sprintf("%s=%s", DefaultCookieName, test.Expected)) {
|
|
t.Errorf("Token extract error; expected %v actual %v", test.Expected, principal.Subject)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCookieValidate(t *testing.T) {
|
|
var test = []struct {
|
|
Desc string
|
|
Name string
|
|
Value string
|
|
Lookup string
|
|
Expected string
|
|
Err error
|
|
ValidErr error
|
|
}{
|
|
{
|
|
Desc: "No cookie of this name",
|
|
Name: "Auth",
|
|
Value: "reallyimportant",
|
|
Lookup: "Doesntexist",
|
|
Expected: "",
|
|
Err: ErrAuthentication,
|
|
},
|
|
{
|
|
Desc: "Unable to create token",
|
|
Name: "Auth",
|
|
Lookup: "Auth",
|
|
Err: ErrAuthentication,
|
|
ValidErr: ErrAuthentication,
|
|
},
|
|
{
|
|
Desc: "Cookie token extracted",
|
|
Name: "Auth",
|
|
Value: "reallyimportant",
|
|
Lookup: "Auth",
|
|
Expected: "reallyimportant",
|
|
Err: nil,
|
|
},
|
|
}
|
|
for _, test := range test {
|
|
req, _ := http.NewRequest("", "http://howdy.com", nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: test.Name,
|
|
Value: test.Value,
|
|
})
|
|
|
|
cook := cookie{
|
|
Name: test.Lookup,
|
|
Lifespan: 1 * time.Second,
|
|
Inactivity: DefaultInactivityDuration,
|
|
Now: func() time.Time {
|
|
return time.Unix(0, 0)
|
|
},
|
|
Tokens: &MockTokenizer{
|
|
Principal: Principal{
|
|
Subject: test.Value,
|
|
},
|
|
ValidErr: test.ValidErr,
|
|
},
|
|
}
|
|
principal, err := cook.Validate(context.Background(), req)
|
|
if err != test.Err {
|
|
t.Errorf("Cookie extract error; expected %v actual %v", test.Err, err)
|
|
}
|
|
|
|
if principal.Subject != test.Expected {
|
|
t.Errorf("Token extract error; expected %v actual %v", test.Expected, principal.Subject)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewCookieJWT(t *testing.T) {
|
|
auth := NewCookieJWT("secret", 2*time.Second)
|
|
if cookie, ok := auth.(*cookie); !ok {
|
|
t.Errorf("NewCookieJWT() did not create cookie Authenticator")
|
|
} else if cookie.Inactivity != time.Second {
|
|
t.Errorf("NewCookieJWT() inactivity was not two seconds: %s", cookie.Inactivity)
|
|
}
|
|
|
|
auth = NewCookieJWT("secret", time.Hour)
|
|
if cookie, ok := auth.(*cookie); !ok {
|
|
t.Errorf("NewCookieJWT() did not create cookie Authenticator")
|
|
} else if cookie.Inactivity != DefaultInactivityDuration {
|
|
t.Errorf("NewCookieJWT() inactivity was not five minutes: %s", cookie.Inactivity)
|
|
}
|
|
|
|
auth = NewCookieJWT("secret", 0)
|
|
if cookie, ok := auth.(*cookie); !ok {
|
|
t.Errorf("NewCookieJWT() did not create cookie Authenticator")
|
|
} else if cookie.Inactivity != DefaultInactivityDuration {
|
|
t.Errorf("NewCookieJWT() inactivity was not five minutes: %s", cookie.Inactivity)
|
|
}
|
|
}
|
|
|
|
func TestCookieExtend(t *testing.T) {
|
|
history := time.Unix(-446774400, 0)
|
|
type fields struct {
|
|
Name string
|
|
Lifespan time.Duration
|
|
Inactivity time.Duration
|
|
Now func() time.Time
|
|
Tokens Tokenizer
|
|
}
|
|
type args struct {
|
|
ctx context.Context
|
|
w *httptest.ResponseRecorder
|
|
p Principal
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
want Principal
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "Successful extention",
|
|
want: Principal{
|
|
Subject: "subject",
|
|
},
|
|
fields: fields{
|
|
Name: "session",
|
|
Lifespan: time.Second,
|
|
Inactivity: time.Second,
|
|
Now: func() time.Time {
|
|
return history
|
|
},
|
|
Tokens: &MockTokenizer{
|
|
Principal: Principal{
|
|
Subject: "subject",
|
|
},
|
|
Token: "token",
|
|
ExtendErr: nil,
|
|
},
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
w: httptest.NewRecorder(),
|
|
p: Principal{
|
|
Subject: "subject",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Unable to extend",
|
|
wantErr: true,
|
|
fields: fields{
|
|
Tokens: &MockTokenizer{
|
|
ExtendErr: fmt.Errorf("bad extend"),
|
|
},
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
w: httptest.NewRecorder(),
|
|
p: Principal{
|
|
Subject: "subject",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Unable to create",
|
|
wantErr: true,
|
|
fields: fields{
|
|
Tokens: &MockTokenizer{
|
|
CreateErr: fmt.Errorf("bad extend"),
|
|
},
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
w: httptest.NewRecorder(),
|
|
p: Principal{
|
|
Subject: "subject",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &cookie{
|
|
Name: tt.fields.Name,
|
|
Lifespan: tt.fields.Lifespan,
|
|
Inactivity: tt.fields.Inactivity,
|
|
Now: tt.fields.Now,
|
|
Tokens: tt.fields.Tokens,
|
|
}
|
|
got, err := c.Extend(tt.args.ctx, tt.args.w, tt.args.p)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("cookie.Extend() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !tt.wantErr {
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("cookie.Extend() = %v, want %v", got, tt.want)
|
|
}
|
|
|
|
cookies := tt.args.w.Header()["Set-Cookie"]
|
|
if len(cookies) == 0 {
|
|
t.Fatal("Expected some cookies but got zero")
|
|
}
|
|
log.Printf("%s", cookies)
|
|
want := fmt.Sprintf("%s=%s", DefaultCookieName, "token")
|
|
if !strings.Contains(cookies[0], want) {
|
|
t.Errorf("cookie.Extend() = %v, want %v", cookies[0], want)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|