blob: 63b7b5b9b67201e32168e19db9bb38cf113ed38c [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package blesser
import (
"reflect"
"sort"
"strings"
"testing"
"time"
"v.io/x/ref/services/identity/internal/oauth"
"v.io/x/ref/test/testutil"
"v.io/v23/security"
)
func join(elements ...string) string {
return strings.Join(elements, security.ChainSeparator)
}
func TestOAuthBlesser(t *testing.T) {
var (
provider, user = testutil.NewPrincipal(), testutil.NewPrincipal()
ctx, call = fakeContextAndCall(provider, user)
)
mockEmail := "testemail@example.com"
mockClientID := "test-client-id"
mockClientName := "test-client"
blesser := NewOAuthBlesserServer(OAuthBlesserParams{
OAuthProvider: oauth.NewMockOAuth(mockEmail, mockClientID),
BlessingDuration: time.Hour,
AccessTokenClients: []oauth.AccessTokenClient{
oauth.AccessTokenClient{
Name: mockClientName,
ClientID: mockClientID,
},
},
})
b, extension, err := blesser.BlessUsingAccessToken(ctx, call, "test-access-token")
if err != nil {
t.Errorf("BlessUsingAccessToken failed: %v", err)
}
wantExtension := join(mockEmail, mockClientName)
if extension != wantExtension {
t.Errorf("got extension: %s, want: %s", extension, wantExtension)
}
if !reflect.DeepEqual(b.PublicKey(), user.PublicKey()) {
t.Errorf("Received blessing for public key %v. Client:%v, Blesser:%v", b.PublicKey(), user.PublicKey(), provider.PublicKey())
}
// When the user does not recognize the provider, it should not see any strings for
// the client's blessings.
if got := user.BlessingsInfo(b); got != nil {
t.Errorf("Got blessing with info %v, want nil", got)
}
// But once it recognizes the provider, it should see exactly the name
// "provider/testemail@example.com/test-client".
security.AddToRoots(user, b)
binfo := user.BlessingsInfo(b)
if num := len(binfo); num != 1 {
t.Errorf("Got blessings with %d names, want exactly one name", num)
}
if _, ok := binfo[join("provider", wantExtension)]; !ok {
t.Errorf("BlessingsInfo %v does not have name %s", binfo, wantExtension)
}
}
func TestOAuthBlesserWithCaveats(t *testing.T) {
var (
provider, user = testutil.NewPrincipal(), testutil.NewPrincipal()
ctx, call = fakeContextAndCall(provider, user)
)
mockEmail := "testemail@example.com"
mockClientID := "test-client-id"
mockClientName := "test-client"
blesser := NewOAuthBlesserServer(OAuthBlesserParams{
OAuthProvider: oauth.NewMockOAuth(mockEmail, mockClientID),
BlessingDuration: time.Hour,
AccessTokenClients: []oauth.AccessTokenClient{
oauth.AccessTokenClient{
Name: mockClientName,
ClientID: mockClientID,
},
},
})
expiryCav, err := security.NewExpiryCaveat(time.Now().Add(time.Minute))
if err != nil {
t.Fatal(err)
}
methodCav, err := security.NewMethodCaveat("foo", "bar")
if err != nil {
t.Fatal(err)
}
caveats := []security.Caveat{expiryCav, methodCav}
b, extension, err := blesser.BlessUsingAccessTokenWithCaveats(ctx, call, "test-access-token", caveats)
if err != nil {
t.Errorf("BlessUsingAccessToken failed: %v", err)
}
wantExtension := join(mockEmail, mockClientName)
if extension != wantExtension {
t.Errorf("got extension: %s, want: %s", extension, wantExtension)
}
if !reflect.DeepEqual(b.PublicKey(), user.PublicKey()) {
t.Errorf("Received blessing for public key %v. Client:%v, Blesser:%v", b.PublicKey(), user.PublicKey(), provider.PublicKey())
}
// When the user does not recognize the provider, it should not see any strings for
// the client's blessings.
if got := user.BlessingsInfo(b); got != nil {
t.Errorf("Got blessing with info %v, want nil", got)
}
// But once it recognizes the provider, it should see exactly the name
// "provider/testemail@example.com/test-client".
security.AddToRoots(user, b)
binfo := user.BlessingsInfo(b)
if num := len(binfo); num != 1 {
t.Errorf("Got blessings with %d names, want exactly one name", num)
}
cavs, ok := binfo[join("provider", wantExtension)]
if !ok {
t.Errorf("BlessingsInfo %v does not have name %s", binfo, wantExtension)
}
if !caveatsMatch(cavs, caveats) {
t.Errorf("got %v, want %v", cavs, caveats)
}
}
func caveatsMatch(got, want []security.Caveat) bool {
if len(got) != len(want) {
return false
}
gotStrings := make([]string, len(got))
wantStrings := make([]string, len(want))
for i := 0; i < len(got); i++ {
gotStrings[i] = got[i].String()
wantStrings[i] = want[i].String()
}
sort.Strings(gotStrings)
sort.Strings(wantStrings)
return reflect.DeepEqual(gotStrings, wantStrings)
}