mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
7.5 KiB
299 lines
7.5 KiB
package server |
|
|
|
import ( |
|
"encoding/base64" |
|
"fmt" |
|
"net/url" |
|
"time" |
|
|
|
"github.com/coreos/go-oidc/key" |
|
"github.com/coreos/go-oidc/oidc" |
|
|
|
"github.com/coreos/dex/client" |
|
clientmanager "github.com/coreos/dex/client/manager" |
|
"github.com/coreos/dex/connector" |
|
"github.com/coreos/dex/db" |
|
"github.com/coreos/dex/email" |
|
"github.com/coreos/dex/refresh/refreshtest" |
|
sessionmanager "github.com/coreos/dex/session/manager" |
|
"github.com/coreos/dex/user" |
|
useremail "github.com/coreos/dex/user/email" |
|
usermanager "github.com/coreos/dex/user/manager" |
|
) |
|
|
|
const ( |
|
templatesLocation = "../static/html" |
|
emailTemplatesLocation = "../static/email" |
|
) |
|
|
|
var ( |
|
testUserID1 = "ID-1" |
|
testUserEmail1 = "Email-1@example.com" |
|
testUserRemoteID1 = "RID-1" |
|
|
|
testIssuerURL = url.URL{Scheme: "http", Host: "server.example.com"} |
|
|
|
testClientID = "client.example.com" |
|
clientTestSecret = base64.URLEncoding.EncodeToString([]byte("secret")) |
|
testClientCredentials = oidc.ClientCredentials{ |
|
ID: testClientID, |
|
Secret: clientTestSecret, |
|
} |
|
|
|
testPublicClientID = "publicclient.example.com" |
|
publicClientTestSecret = base64.URLEncoding.EncodeToString([]byte("secret")) |
|
testPublicClientCredentials = oidc.ClientCredentials{ |
|
ID: testPublicClientID, |
|
Secret: publicClientTestSecret, |
|
} |
|
testClients = []client.LoadableClient{ |
|
{ |
|
Client: client.Client{ |
|
Credentials: testClientCredentials, |
|
Metadata: oidc.ClientMetadata{ |
|
RedirectURIs: []url.URL{ |
|
testRedirectURL, |
|
}, |
|
}, |
|
}, |
|
}, |
|
{ |
|
Client: client.Client{ |
|
Credentials: testPublicClientCredentials, |
|
Public: true, |
|
}, |
|
}, |
|
} |
|
|
|
testConnectorID1 = "IDPC-1" |
|
|
|
testConnectorIDOpenID = "oidc" |
|
testConnectorIDOpenIDTrusted = "oidc-trusted" |
|
testConnectorLocalID = "local" |
|
|
|
testRedirectURL = url.URL{Scheme: "http", Host: "client.example.com", Path: "/callback"} |
|
|
|
testUsers = []user.UserWithRemoteIdentities{ |
|
{ |
|
User: user.User{ |
|
ID: testUserID1, |
|
Email: testUserEmail1, |
|
}, |
|
RemoteIdentities: []user.RemoteIdentity{ |
|
{ |
|
ConnectorID: testConnectorID1, |
|
ID: testUserRemoteID1, |
|
}, |
|
}, |
|
}, |
|
{ |
|
User: user.User{ |
|
ID: "ID-Verified", |
|
Email: "Email-Verified@example.com", |
|
EmailVerified: true, |
|
}, |
|
RemoteIdentities: []user.RemoteIdentity{ |
|
{ |
|
ConnectorID: "IDPC-1", |
|
ID: "RID-2", |
|
}, |
|
}, |
|
}, |
|
} |
|
|
|
testPasswordInfos = []user.PasswordInfo{ |
|
{ |
|
UserID: "ID-1", |
|
Password: []byte("password"), |
|
}, |
|
{ |
|
UserID: "ID-Verified", |
|
Password: []byte("password"), |
|
}, |
|
} |
|
|
|
testPrivKey, _ = key.GeneratePrivateKey() |
|
|
|
testClientCreds = oidc.ClientCredentials{ |
|
ID: testClientID, |
|
Secret: base64.URLEncoding.EncodeToString([]byte("secret")), |
|
} |
|
) |
|
|
|
type testFixtures struct { |
|
srv *Server |
|
userRepo user.UserRepo |
|
sessionManager *sessionmanager.SessionManager |
|
emailer *email.TemplatizedEmailer |
|
redirectURL url.URL |
|
clientRepo client.ClientRepo |
|
clientManager *clientmanager.ClientManager |
|
clientCreds map[string]oidc.ClientCredentials |
|
} |
|
|
|
type testFixtureOptions struct { |
|
clients []client.LoadableClient |
|
} |
|
|
|
func sequentialGenerateCodeFunc() sessionmanager.GenerateCodeFunc { |
|
x := 0 |
|
return func() (string, error) { |
|
x += 1 |
|
return fmt.Sprintf("code-%d", x), nil |
|
} |
|
} |
|
|
|
func makeTestFixtures() (*testFixtures, error) { |
|
return makeTestFixturesWithOptions(testFixtureOptions{}) |
|
} |
|
|
|
func makeTestFixturesWithOptions(options testFixtureOptions) (*testFixtures, error) { |
|
dbMap := db.NewMemDB() |
|
userRepo, err := db.NewUserRepoFromUsers(dbMap, testUsers) |
|
if err != nil { |
|
return nil, err |
|
} |
|
pwRepo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, testPasswordInfos) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
connConfigs := []connector.ConnectorConfig{ |
|
&connector.OIDCConnectorConfig{ |
|
ID: testConnectorIDOpenID, |
|
IssuerURL: testIssuerURL.String(), |
|
ClientID: "12345", |
|
ClientSecret: "567789", |
|
}, |
|
&connector.OIDCConnectorConfig{ |
|
ID: testConnectorIDOpenIDTrusted, |
|
IssuerURL: testIssuerURL.String(), |
|
ClientID: "12345-trusted", |
|
ClientSecret: "567789-trusted", |
|
TrustedEmailProvider: true, |
|
}, |
|
&connector.OIDCConnectorConfig{ |
|
ID: testConnectorID1, |
|
IssuerURL: testIssuerURL.String(), |
|
ClientID: testConnectorID1 + "_client_id", |
|
ClientSecret: testConnectorID1 + "_client_secret", |
|
TrustedEmailProvider: true, |
|
}, |
|
&connector.LocalConnectorConfig{ |
|
ID: testConnectorLocalID, |
|
}, |
|
} |
|
connCfgRepo := db.NewConnectorConfigRepo(dbMap) |
|
if err := connCfgRepo.Set(connConfigs); err != nil { |
|
return nil, err |
|
} |
|
|
|
userManager := usermanager.NewUserManager(userRepo, pwRepo, connCfgRepo, db.TransactionFactory(dbMap), usermanager.ManagerOptions{}) |
|
|
|
sessionManager := sessionmanager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB())) |
|
sessionManager.GenerateCode = sequentialGenerateCodeFunc() |
|
|
|
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo() |
|
|
|
emailer, err := email.NewTemplatizedEmailerFromGlobs( |
|
emailTemplatesLocation+"/*.txt", |
|
emailTemplatesLocation+"/*.html", |
|
&email.FakeEmailer{}, |
|
"admin@example.com") |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
var clients []client.LoadableClient |
|
if options.clients == nil { |
|
clients = testClients |
|
} else { |
|
clients = options.clients |
|
} |
|
|
|
clientIDGenerator := func(hostport string) (string, error) { |
|
return hostport, nil |
|
} |
|
secGen := func() ([]byte, error) { |
|
return []byte("secret"), nil |
|
} |
|
clientRepo, err := db.NewClientRepoFromClients(dbMap, clients) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
clientManager := clientmanager.NewClientManager(clientRepo, db.TransactionFactory(dbMap), clientmanager.ManagerOptions{ClientIDGenerator: clientIDGenerator, SecretGenerator: secGen}) |
|
|
|
km := key.NewPrivateKeyManager() |
|
err = km.Set(key.NewPrivateKeySet([]*key.PrivateKey{testPrivKey}, time.Now().Add(time.Minute))) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
tpl, err := getTemplates("dex", "https://coreos.com", |
|
"https://coreos.com/assets/images/brand/coreos-mark-30px.png", |
|
true, templatesLocation) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
srv := &Server{ |
|
IssuerURL: testIssuerURL, |
|
SessionManager: sessionManager, |
|
ClientRepo: clientRepo, |
|
Templates: tpl, |
|
UserRepo: userRepo, |
|
PasswordInfoRepo: pwRepo, |
|
UserManager: userManager, |
|
ClientManager: clientManager, |
|
KeyManager: km, |
|
RefreshTokenRepo: refreshTokenRepo, |
|
} |
|
|
|
err = setTemplates(srv, tpl) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
for _, config := range connConfigs { |
|
if err := srv.AddConnector(config); err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
srv.UserEmailer = useremail.NewUserEmailer(srv.UserRepo, |
|
srv.PasswordInfoRepo, |
|
srv.KeyManager.Signer, |
|
srv.SessionManager.ValidityWindow, |
|
srv.IssuerURL, |
|
emailer, |
|
srv.absURL(httpPathResetPassword), |
|
srv.absURL(httpPathEmailVerify), |
|
srv.absURL(httpPathAcceptInvitation), |
|
) |
|
|
|
clientCreds := map[string]oidc.ClientCredentials{} |
|
for _, c := range clients { |
|
clientCreds[c.Client.Credentials.ID] = c.Client.Credentials |
|
} |
|
return &testFixtures{ |
|
srv: srv, |
|
redirectURL: testRedirectURL, |
|
userRepo: userRepo, |
|
sessionManager: sessionManager, |
|
emailer: emailer, |
|
clientRepo: clientRepo, |
|
clientManager: clientManager, |
|
clientCreds: clientCreds, |
|
}, nil |
|
} |
|
|
|
func clientsToLoadableClients(cs []client.Client) []client.LoadableClient { |
|
lcs := make([]client.LoadableClient, len(cs), len(cs)) |
|
for i, c := range cs { |
|
lcs[i] = client.LoadableClient{ |
|
Client: c, |
|
} |
|
} |
|
return lcs |
|
}
|
|
|