dex/server/server_test.go

834 lines
22 KiB
Go
Raw Normal View History

2015-08-18 05:57:27 +05:30
package server
import (
"encoding/base64"
2015-08-18 05:57:27 +05:30
"errors"
"fmt"
2015-08-18 05:57:27 +05:30
"net/url"
"reflect"
"testing"
"time"
"github.com/coreos/dex/client"
"github.com/coreos/dex/db"
2015-08-18 05:57:27 +05:30
"github.com/coreos/dex/refresh/refreshtest"
"github.com/coreos/dex/session/manager"
2015-08-18 05:57:27 +05:30
"github.com/coreos/dex/user"
"github.com/coreos/go-oidc/jose"
"github.com/coreos/go-oidc/key"
"github.com/coreos/go-oidc/oauth2"
"github.com/coreos/go-oidc/oidc"
"github.com/kylelemons/godebug/pretty"
2015-08-18 05:57:27 +05:30
)
var clientTestSecret = base64.URLEncoding.EncodeToString([]byte("secrete"))
2015-08-18 05:57:27 +05:30
type StaticKeyManager struct {
key.PrivateKeyManager
expiresAt time.Time
signer jose.Signer
keys []jose.JWK
}
func (m *StaticKeyManager) ExpiresAt() time.Time {
return m.expiresAt
}
func (m *StaticKeyManager) Signer() (jose.Signer, error) {
return m.signer, nil
}
func (m *StaticKeyManager) JWKs() ([]jose.JWK, error) {
return m.keys, nil
}
type StaticSigner struct {
sig []byte
err error
}
func (ss *StaticSigner) ID() string {
return "static"
}
func (ss *StaticSigner) Alg() string {
return "static"
}
func (ss *StaticSigner) Verify(sig, data []byte) error {
if !reflect.DeepEqual(ss.sig, sig) {
return errors.New("signature mismatch")
}
return nil
}
func (ss *StaticSigner) Sign(data []byte) ([]byte, error) {
return ss.sig, ss.err
}
func (ss *StaticSigner) JWK() jose.JWK {
return jose.JWK{}
}
func staticGenerateCodeFunc(code string) manager.GenerateCodeFunc {
2015-08-18 05:57:27 +05:30
return func() (string, error) {
return code, nil
}
}
func makeNewUserRepo() (user.UserRepo, error) {
2016-02-10 01:52:40 +05:30
userRepo := db.NewUserRepo(db.NewMemDB())
2015-08-18 05:57:27 +05:30
id := "testid-1"
err := userRepo.Create(nil, user.User{
ID: id,
Email: "testname@example.com",
})
if err != nil {
return nil, err
}
err = userRepo.AddRemoteIdentity(nil, id, user.RemoteIdentity{
ConnectorID: "test_connector_id",
ID: "YYY",
})
if err != nil {
return nil, err
}
return userRepo, nil
}
func TestServerProviderConfig(t *testing.T) {
srv := &Server{IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"}}
want := oidc.ProviderConfig{
Issuer: &url.URL{Scheme: "http", Host: "server.example.com"},
AuthEndpoint: &url.URL{Scheme: "http", Host: "server.example.com", Path: "/auth"},
TokenEndpoint: &url.URL{Scheme: "http", Host: "server.example.com", Path: "/token"},
KeysEndpoint: &url.URL{Scheme: "http", Host: "server.example.com", Path: "/keys"},
2015-08-18 05:57:27 +05:30
GrantTypesSupported: []string{oauth2.GrantTypeAuthCode, oauth2.GrantTypeClientCreds},
ResponseTypesSupported: []string{"code"},
SubjectTypesSupported: []string{"public"},
IDTokenSigningAlgValues: []string{"RS256"},
2015-08-18 05:57:27 +05:30
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic"},
}
got := srv.ProviderConfig()
if diff := pretty.Compare(want, got); diff != "" {
t.Fatalf("provider config did not match expected: %s", diff)
2015-08-18 05:57:27 +05:30
}
}
func TestServerNewSession(t *testing.T) {
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
srv := &Server{
SessionManager: sm,
}
state := "pants"
nonce := "oncenay"
ci := oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: "secrete",
},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
2015-08-18 05:57:27 +05:30
url.URL{
Scheme: "http",
Host: "client.example.com",
Path: "/callback",
},
},
},
}
key, err := srv.NewSession("bogus_idpc", ci.Credentials.ID, state, ci.Metadata.RedirectURIs[0], nonce, false, []string{"openid"})
2015-08-18 05:57:27 +05:30
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
sessionID, err := sm.ExchangeKey(key)
if err != nil {
t.Fatalf("Session not retreivable: %v", err)
}
ses, err := sm.AttachRemoteIdentity(sessionID, oidc.Identity{})
if err != nil {
t.Fatalf("Unable to add Identity to Session: %v", err)
}
if !reflect.DeepEqual(ci.Metadata.RedirectURIs[0], ses.RedirectURL) {
t.Fatalf("Session created with incorrect RedirectURL: want=%#v got=%#v", ci.Metadata.RedirectURIs[0], ses.RedirectURL)
2015-08-18 05:57:27 +05:30
}
if ci.Credentials.ID != ses.ClientID {
t.Fatalf("Session created with incorrect ClientID: want=%q got=%q", ci.Credentials.ID, ses.ClientID)
}
if state != ses.ClientState {
t.Fatalf("Session created with incorrect State: want=%q got=%q", state, ses.ClientState)
}
if nonce != ses.Nonce {
t.Fatalf("Session created with incorrect Nonce: want=%q got=%q", nonce, ses.Nonce)
}
}
func TestServerLogin(t *testing.T) {
ci := oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
2015-08-18 05:57:27 +05:30
url.URL{
Scheme: "http",
Host: "client.example.com",
Path: "/callback",
},
},
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
return repo
}()
2015-08-18 05:57:27 +05:30
km := &StaticKeyManager{
signer: &StaticSigner{sig: []byte("beer"), err: nil},
}
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
sm.GenerateCode = staticGenerateCodeFunc("fakecode")
sessionID, err := sm.NewSession("test_connector_id", ci.Credentials.ID, "bogus", ci.Metadata.RedirectURIs[0], "", false, []string{"openid"})
2015-08-18 05:57:27 +05:30
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
srv := &Server{
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
}
ident := oidc.Identity{ID: "YYY", Name: "elroy", Email: "elroy@example.com"}
key, err := sm.NewSessionKey(sessionID)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
redirectURL, err := srv.Login(ident, key)
if err != nil {
t.Fatalf("Unexpected err from Server.Login: %v", err)
}
wantRedirectURL := "http://client.example.com/callback?code=fakecode&state=bogus"
if wantRedirectURL != redirectURL {
t.Fatalf("Unexpected redirectURL: want=%q, got=%q", wantRedirectURL, redirectURL)
}
}
func TestServerLoginUnrecognizedSessionKey(t *testing.T) {
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX", Secret: clientTestSecret,
},
2015-08-18 05:57:27 +05:30
},
})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
return repo
}()
2015-08-18 05:57:27 +05:30
km := &StaticKeyManager{
signer: &StaticSigner{sig: nil, err: errors.New("fail")},
}
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
}
ident := oidc.Identity{ID: "YYY", Name: "elroy", Email: "elroy@example.com"}
code, err := srv.Login(ident, "XXX")
if err == nil {
t.Fatalf("Expected non-nil error")
}
if code != "" {
t.Fatalf("Expected empty code, got=%s", code)
}
}
func TestServerLoginDisabledUser(t *testing.T) {
ci := oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
url.URL{
Scheme: "http",
Host: "client.example.com",
Path: "/callback",
},
},
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
return repo
}()
km := &StaticKeyManager{
signer: &StaticSigner{sig: []byte("beer"), err: nil},
}
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
sm.GenerateCode = staticGenerateCodeFunc("fakecode")
sessionID, err := sm.NewSession("test_connector_id", ci.Credentials.ID, "bogus", ci.Metadata.RedirectURIs[0], "", false, []string{"openid"})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = userRepo.Create(nil, user.User{
ID: "disabled-1",
Email: "disabled@example.com",
Disabled: true,
})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = userRepo.AddRemoteIdentity(nil, "disabled-1", user.RemoteIdentity{
ConnectorID: "test_connector_id",
ID: "disabled-connector-id",
})
srv := &Server{
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
}
ident := oidc.Identity{ID: "disabled-connector-id", Name: "elroy", Email: "elroy@example.com"}
key, err := sm.NewSessionKey(sessionID)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
_, err = srv.Login(ident, key)
if err == nil {
t.Errorf("disabled user was allowed to log in")
}
}
2015-08-18 05:57:27 +05:30
func TestServerCodeToken(t *testing.T) {
ci := oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
return repo
}()
2015-08-18 05:57:27 +05:30
km := &StaticKeyManager{
signer: &StaticSigner{sig: []byte("beer"), err: nil},
}
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
2016-02-10 01:07:32 +05:30
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
RefreshTokenRepo: refreshTokenRepo,
}
tests := []struct {
scope []string
refreshToken string
}{
// No 'offline_access' in scope, should get empty refresh token.
{
scope: []string{"openid"},
refreshToken: "",
},
// Have 'offline_access' in scope, should get non-empty refresh token.
{
2016-02-10 01:07:32 +05:30
// NOTE(ericchiang): This test assumes that the database ID of the first
// refresh token will be "1".
scope: []string{"openid", "offline_access"},
2016-02-10 01:07:32 +05:30
refreshToken: fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
},
2015-08-18 05:57:27 +05:30
}
for i, tt := range tests {
sessionID, err := sm.NewSession("bogus_idpc", ci.Credentials.ID, "bogus", url.URL{}, "", false, tt.scope)
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
}
_, err = sm.AttachRemoteIdentity(sessionID, oidc.Identity{})
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
}
2015-08-18 05:57:27 +05:30
_, err = sm.AttachUser(sessionID, "testid-1")
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
}
2015-08-18 05:57:27 +05:30
key, err := sm.NewSessionKey(sessionID)
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
}
jwt, token, err := srv.CodeToken(ci.Credentials, key)
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
}
if jwt == nil {
t.Fatalf("case %d: expect non-nil jwt", i)
}
if token != tt.refreshToken {
t.Fatalf("case %d: expect refresh token %q, got %q", i, tt.refreshToken, token)
}
2015-08-18 05:57:27 +05:30
}
}
func TestServerTokenUnrecognizedKey(t *testing.T) {
ci := oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
return repo
}()
2015-08-18 05:57:27 +05:30
km := &StaticKeyManager{
signer: &StaticSigner{sig: []byte("beer"), err: nil},
}
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
}
sessionID, err := sm.NewSession("connector_id", ci.Credentials.ID, "bogus", url.URL{}, "", false, []string{"openid", "offline_access"})
2015-08-18 05:57:27 +05:30
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
_, err = sm.AttachRemoteIdentity(sessionID, oidc.Identity{})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
jwt, token, err := srv.CodeToken(ci.Credentials, "foo")
if err == nil {
t.Fatalf("Expected non-nil error")
}
if jwt != nil {
t.Fatalf("Expected nil jwt")
}
if token != "" {
t.Fatalf("Expected empty refresh token")
}
}
func TestServerTokenFail(t *testing.T) {
issuerURL := url.URL{Scheme: "http", Host: "server.example.com"}
keyFixture := "goodkey"
ccFixture := oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
}
signerFixture := &StaticSigner{sig: []byte("beer"), err: nil}
tests := []struct {
signer jose.Signer
argCC oidc.ClientCredentials
argKey string
err error
scope []string
refreshToken string
2015-08-18 05:57:27 +05:30
}{
// control test case to make sure fixtures check out
{
2016-02-10 01:07:32 +05:30
// NOTE(ericchiang): This test assumes that the database ID of the first
// refresh token will be "1".
signer: signerFixture,
argCC: ccFixture,
argKey: keyFixture,
scope: []string{"openid", "offline_access"},
2016-02-10 01:07:32 +05:30
refreshToken: fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
},
// no 'offline_access' in 'scope', should get empty refresh token
2015-08-18 05:57:27 +05:30
{
signer: signerFixture,
argCC: ccFixture,
argKey: keyFixture,
scope: []string{"openid"},
2015-08-18 05:57:27 +05:30
},
// unrecognized key
{
signer: signerFixture,
argCC: ccFixture,
argKey: "foo",
err: oauth2.NewError(oauth2.ErrorInvalidGrant),
scope: []string{"openid", "offline_access"},
2015-08-18 05:57:27 +05:30
},
// unrecognized client
{
signer: signerFixture,
argCC: oidc.ClientCredentials{ID: "YYY"},
argKey: keyFixture,
err: oauth2.NewError(oauth2.ErrorInvalidClient),
scope: []string{"openid", "offline_access"},
2015-08-18 05:57:27 +05:30
},
// signing operation fails
{
signer: &StaticSigner{sig: nil, err: errors.New("fail")},
argCC: ccFixture,
argKey: keyFixture,
err: oauth2.NewError(oauth2.ErrorServerError),
scope: []string{"openid", "offline_access"},
2015-08-18 05:57:27 +05:30
},
}
for i, tt := range tests {
sm := manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB()))
2015-08-18 05:57:27 +05:30
sm.GenerateCode = func() (string, error) { return keyFixture, nil }
sessionID, err := sm.NewSession("connector_id", ccFixture.ID, "bogus", url.URL{}, "", false, tt.scope)
2015-08-18 05:57:27 +05:30
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
_, err = sm.AttachRemoteIdentity(sessionID, oidc.Identity{})
if err != nil {
t.Errorf("case %d: unexpected error: %v", i, err)
continue
}
km := &StaticKeyManager{
signer: tt.signer,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
2015-08-18 05:57:27 +05:30
oidc.ClientIdentity{Credentials: ccFixture},
})
if err != nil {
t.Errorf("case %d: failed to create client identity repo: %v", i, err)
continue
}
2015-08-18 05:57:27 +05:30
_, err = sm.AttachUser(sessionID, "testid-1")
if err != nil {
t.Fatalf("case %d: unexpected error: %v", i, err)
2015-08-18 05:57:27 +05:30
}
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
2016-02-10 01:07:32 +05:30
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: issuerURL,
KeyManager: km,
SessionManager: sm,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
RefreshTokenRepo: refreshTokenRepo,
}
_, err = sm.NewSessionKey(sessionID)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
jwt, token, err := srv.CodeToken(tt.argCC, tt.argKey)
if token != tt.refreshToken {
fmt.Printf("case %d: expect refresh token %q, got %q\n", i, tt.refreshToken, token)
t.Fatalf("case %d: expect refresh token %q, got %q", i, tt.refreshToken, token)
panic("")
}
if !reflect.DeepEqual(err, tt.err) {
t.Errorf("case %d: expect %v, got %v", i, tt.err, err)
}
if err == nil && jwt == nil {
t.Errorf("case %d: got nil JWT", i)
}
if err != nil && jwt != nil {
t.Errorf("case %d: got non-nil JWT %v", i, jwt)
2015-08-18 05:57:27 +05:30
}
}
}
func TestServerRefreshToken(t *testing.T) {
issuerURL := url.URL{Scheme: "http", Host: "server.example.com"}
credXXX := oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
}
credYYY := oidc.ClientCredentials{
ID: "YYY",
Secret: clientTestSecret,
2015-08-18 05:57:27 +05:30
}
signerFixture := &StaticSigner{sig: []byte("beer"), err: nil}
2016-02-10 01:07:32 +05:30
// NOTE(ericchiang): These tests assume that the database ID of the first
// refresh token will be "1".
2015-08-18 05:57:27 +05:30
tests := []struct {
token string
clientID string // The client that associates with the token.
creds oidc.ClientCredentials
signer jose.Signer
err error
2015-08-18 05:57:27 +05:30
}{
// Everything is good.
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
credXXX,
signerFixture,
nil,
2015-08-18 05:57:27 +05:30
},
// Invalid refresh token(malformatted).
{
"invalid-token",
"XXX",
credXXX,
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidRequest),
2015-08-18 05:57:27 +05:30
},
// Invalid refresh token(invalid payload content).
2015-08-18 05:57:27 +05:30
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-2"))),
2015-08-18 05:57:27 +05:30
"XXX",
credXXX,
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidRequest),
},
// Invalid refresh token(invalid ID content).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("0/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
"XXX",
credXXX,
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidRequest),
2015-08-18 05:57:27 +05:30
},
// Invalid client(client is not associated with the token).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
credYYY,
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidClient),
2015-08-18 05:57:27 +05:30
},
// Invalid client(no client ID).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
oidc.ClientCredentials{ID: "", Secret: "aaa"},
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidClient),
2015-08-18 05:57:27 +05:30
},
// Invalid client(no such client).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
oidc.ClientCredentials{ID: "AAA", Secret: "aaa"},
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidClient),
2015-08-18 05:57:27 +05:30
},
// Invalid client(no secrets).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
oidc.ClientCredentials{ID: "XXX"},
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidClient),
2015-08-18 05:57:27 +05:30
},
// Invalid client(invalid secret).
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
oidc.ClientCredentials{ID: "XXX", Secret: "bad-secret"},
signerFixture,
oauth2.NewError(oauth2.ErrorInvalidClient),
2015-08-18 05:57:27 +05:30
},
// Signing operation fails.
{
2016-02-10 01:07:32 +05:30
fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))),
2015-08-18 05:57:27 +05:30
"XXX",
credXXX,
&StaticSigner{sig: nil, err: errors.New("fail")},
oauth2.NewError(oauth2.ErrorServerError),
2015-08-18 05:57:27 +05:30
},
}
for i, tt := range tests {
km := &StaticKeyManager{
signer: tt.signer,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
2015-08-18 05:57:27 +05:30
oidc.ClientIdentity{Credentials: credXXX},
oidc.ClientIdentity{Credentials: credYYY},
})
if err != nil {
t.Errorf("case %d: failed to create client identity repo: %v", i, err)
continue
}
2015-08-18 05:57:27 +05:30
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
2016-02-10 01:07:32 +05:30
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: issuerURL,
KeyManager: km,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
RefreshTokenRepo: refreshTokenRepo,
}
if _, err := refreshTokenRepo.Create("testid-1", tt.clientID); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
jwt, err := srv.RefreshToken(tt.creds, tt.token)
if !reflect.DeepEqual(err, tt.err) {
t.Errorf("Case %d: expect: %v, got: %v", i, tt.err, err)
2015-08-18 05:57:27 +05:30
}
if jwt != nil {
if string(jwt.Signature) != "beer" {
t.Errorf("Case %d: expect signature: beer, got signature: %v", i, jwt.Signature)
}
claims, err := jwt.Claims()
if err != nil {
t.Errorf("Case %d: unexpected error: %v", i, err)
}
if claims["iss"] != issuerURL.String() || claims["sub"] != "testid-1" || claims["aud"] != "XXX" {
t.Errorf("Case %d: invalid claims: %v", i, claims)
}
}
}
// Test that we should return error when user cannot be found after
// verifying the token.
km := &StaticKeyManager{
signer: signerFixture,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
2015-08-18 05:57:27 +05:30
oidc.ClientIdentity{Credentials: credXXX},
oidc.ClientIdentity{Credentials: credYYY},
})
if err != nil {
t.Fatalf("failed to create client identity repo: %v", err)
}
2015-08-18 05:57:27 +05:30
userRepo, err := makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Create a user that will be removed later.
if err := userRepo.Create(nil, user.User{
ID: "testid-2",
Email: "test-2@example.com",
}); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
2016-02-10 01:07:32 +05:30
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
2015-08-18 05:57:27 +05:30
srv := &Server{
IssuerURL: issuerURL,
KeyManager: km,
ClientIdentityRepo: ciRepo,
UserRepo: userRepo,
RefreshTokenRepo: refreshTokenRepo,
}
if _, err := refreshTokenRepo.Create("testid-2", credXXX.ID); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Recreate the user repo to remove the user we created.
userRepo, err = makeNewUserRepo()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
srv.UserRepo = userRepo
2016-02-10 01:07:32 +05:30
_, err = srv.RefreshToken(credXXX, fmt.Sprintf("1/%s", base64.URLEncoding.EncodeToString([]byte("refresh-1"))))
if !reflect.DeepEqual(err, oauth2.NewError(oauth2.ErrorServerError)) {
t.Errorf("Expect: %v, got: %v", oauth2.NewError(oauth2.ErrorServerError), err)
2015-08-18 05:57:27 +05:30
}
}