mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
chore(tests): use a coverage server binary (#8407)
# Which Problems Are Solved Use a single server instance for API integration tests. This optimizes the time taken for the integration test pipeline, because it allows running tests on multiple packages in parallel. Also, it saves time by not start and stopping a zitadel server for every package. # How the Problems Are Solved - Build a binary with `go build -race -cover ....` - Integration tests only construct clients. The server remains running in the background. - The integration package and tested packages now fully utilize the API. No more direct database access trough `query` and `command` packages. - Use Makefile recipes to setup, start and stop the server in the background. - The binary has the race detector enabled - Init and setup jobs are configured to halt immediately on race condition - Because the server runs in the background, races are only logged. When the server is stopped and race logs exist, the Makefile recipe will throw an error and print the logs. - Makefile recipes include logic to print logs and convert coverage reports after the server is stopped. - Some tests need a downstream HTTP server to make requests, like quota and milestones. A new `integration/sink` package creates an HTTP server and uses websockets to forward HTTP request back to the test packages. The package API uses Go channels for abstraction and easy usage. # Additional Changes - Integration test files already used the `//go:build integration` directive. In order to properly split integration from unit tests, integration test files need to be in a `integration_test` subdirectory of their package. - `UseIsolatedInstance` used to overwrite the `Tester.Client` for each instance. Now a `Instance` object is returned with a gRPC client that is connected to the isolated instance's hostname. - The `Tester` type is now `Instance`. The object is created for the first instance, used by default in any test. Isolated instances are also `Instance` objects and therefore benefit from the same methods and values. The first instance and any other us capable of creating an isolated instance over the system API. - All test packages run in an Isolated instance by calling `NewInstance()` - Individual tests that use an isolated instance use `t.Parallel()` # Additional Context - Closes #6684 - https://go.dev/doc/articles/race_detector - https://go.dev/doc/build-cover --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -28,17 +28,21 @@ var (
|
||||
)
|
||||
|
||||
func TestOPStorage_CreateAuthRequest(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
t.Parallel()
|
||||
|
||||
id := createAuthRequest(t, clientID, redirectURI)
|
||||
clientID, _ := createClient(t, Instance)
|
||||
|
||||
id := createAuthRequest(t, Instance, clientID, redirectURI)
|
||||
require.Contains(t, id, command.IDPrefixV2)
|
||||
}
|
||||
|
||||
func TestOPStorage_CreateAccessToken_code(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -51,13 +55,13 @@ func TestOPStorage_CreateAccessToken_code(t *testing.T) {
|
||||
|
||||
// test code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
// callback on a succeeded request must fail
|
||||
linkResp, err = Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
linkResp, err = Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -69,15 +73,17 @@ func TestOPStorage_CreateAccessToken_code(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
|
||||
// exchange with a used code must fail
|
||||
_, err = exchangeTokens(t, clientID, code, redirectURI)
|
||||
_, err = exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestOPStorage_CreateAccessToken_implicit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
clientID := createImplicitClient(t)
|
||||
authRequestID := createAuthRequestImplicit(t, clientID, redirectURIImplicit)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -104,14 +110,14 @@ func TestOPStorage_CreateAccessToken_implicit(t *testing.T) {
|
||||
assert.Equal(t, "state", values.Get("state"))
|
||||
|
||||
// check id_token / claims
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURIImplicit)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURIImplicit)
|
||||
require.NoError(t, err)
|
||||
claims, err := rp.VerifyTokens[*oidc.IDTokenClaims](context.Background(), accessToken, idToken, provider.IDTokenVerifier())
|
||||
require.NoError(t, err)
|
||||
assertIDTokenClaims(t, claims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
// callback on a succeeded request must fail
|
||||
linkResp, err = Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
linkResp, err = Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -124,10 +130,12 @@ func TestOPStorage_CreateAccessToken_implicit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_CreateAccessAndRefreshTokens_code(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -140,19 +148,21 @@ func TestOPStorage_CreateAccessAndRefreshTokens_code(t *testing.T) {
|
||||
|
||||
// test code exchange (expect refresh token to be returned)
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
}
|
||||
|
||||
func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -165,7 +175,7 @@ func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -183,12 +193,14 @@ func TestOPStorage_CreateAccessAndRefreshTokens_refresh(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_RevokeToken_access_token(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -201,7 +213,7 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -226,12 +238,14 @@ func TestOPStorage_RevokeToken_access_token(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -244,7 +258,7 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -263,12 +277,14 @@ func TestOPStorage_RevokeToken_access_token_invalid_token_hint_type(t *testing.T
|
||||
}
|
||||
|
||||
func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -281,7 +297,7 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -306,12 +322,14 @@ func TestOPStorage_RevokeToken_refresh_token(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -324,7 +342,7 @@ func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -343,10 +361,12 @@ func TestOPStorage_RevokeToken_refresh_token_invalid_token_type_hint(t *testing.
|
||||
}
|
||||
|
||||
func TestOPStorage_RevokeToken_invalid_client(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -359,26 +379,28 @@ func TestOPStorage_RevokeToken_invalid_client(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
// simulate second client (not part of the audience) trying to revoke the token
|
||||
otherClientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, otherClientID, redirectURI)
|
||||
otherClientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, otherClientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
err = rp.RevokeToken(CTX, provider, tokens.AccessToken, "")
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestOPStorage_TerminateSession(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -391,7 +413,7 @@ func TestOPStorage_TerminateSession(t *testing.T) {
|
||||
|
||||
// test code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -410,12 +432,14 @@ func TestOPStorage_TerminateSession(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -428,7 +452,7 @@ func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) {
|
||||
|
||||
// test code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -454,12 +478,14 @@ func TestOPStorage_TerminateSession_refresh_grant(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -472,21 +498,21 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
|
||||
|
||||
// test code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
postLogoutRedirect, err := rp.EndSession(CTX, provider, "", logoutRedirectURI, "state")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http_utils.BuildOrigin(Tester.Host(), Tester.Config.ExternalSecure)+Tester.Config.OIDC.DefaultLogoutURLV2+logoutRedirectURI+"?state=state", postLogoutRedirect.String())
|
||||
assert.Equal(t, http_utils.BuildOrigin(Instance.Host(), Instance.Config.Secure)+Instance.Config.LogoutURLV2+logoutRedirectURI+"?state=state", postLogoutRedirect.String())
|
||||
|
||||
// userinfo must not fail until login UI terminated session
|
||||
_, err = rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// simulate termination by login UI
|
||||
_, err = Tester.Client.SessionV2.DeleteSession(CTXLOGIN, &session.DeleteSessionRequest{
|
||||
_, err = Instance.Client.SessionV2.DeleteSession(CTXLOGIN, &session.DeleteSessionRequest{
|
||||
SessionId: sessionID,
|
||||
SessionToken: gu.Ptr(sessionToken),
|
||||
})
|
||||
@@ -497,15 +523,15 @@ func TestOPStorage_TerminateSession_empty_id_token_hint(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func exchangeTokens(t testing.TB, clientID, code, redirectURI string) (*oidc.Tokens[*oidc.IDTokenClaims], error) {
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
func exchangeTokens(t testing.TB, instance *integration.Instance, clientID, code, redirectURI string) (*oidc.Tokens[*oidc.IDTokenClaims], error) {
|
||||
provider, err := instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
|
||||
return rp.CodeExchange[*oidc.IDTokenClaims](context.Background(), code, provider, rp.WithCodeVerifier(integration.CodeVerifier))
|
||||
}
|
||||
|
||||
func refreshTokens(t testing.TB, clientID, refreshToken string) (*oidc.Tokens[*oidc.IDTokenClaims], error) {
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
|
||||
return rp.RefreshTokens[*oidc.IDTokenClaims](CTX, provider, refreshToken, "", "")
|
@@ -24,9 +24,11 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_Introspect(t *testing.T) {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
t.Parallel()
|
||||
|
||||
project, err := Instance.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
app, err := Instance.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantAudience := []string{app.GetClientId(), project.GetId()}
|
||||
@@ -39,16 +41,16 @@ func TestServer_Introspect(t *testing.T) {
|
||||
{
|
||||
name: "client assertion",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientJWT(CTX, project.GetId())
|
||||
api, err := Instance.CreateAPIClientJWT(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
keyResp, err := Tester.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{
|
||||
keyResp, err := Instance.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{
|
||||
ProjectId: project.GetId(),
|
||||
AppId: api.GetAppId(),
|
||||
Type: authn.KeyType_KEY_TYPE_JSON,
|
||||
ExpirationDate: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyResp.GetKeyDetails())
|
||||
resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyResp.GetKeyDetails())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
@@ -56,9 +58,9 @@ func TestServer_Introspect(t *testing.T) {
|
||||
{
|
||||
name: "client credentials",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
api, err := Instance.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), api.GetClientSecret())
|
||||
resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), api.GetClientSecret())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
@@ -66,9 +68,9 @@ func TestServer_Introspect(t *testing.T) {
|
||||
{
|
||||
name: "client invalid id, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
api, err := Instance.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, "xxxxx", api.GetClientSecret())
|
||||
resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, "xxxxx", api.GetClientSecret())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
@@ -77,9 +79,9 @@ func TestServer_Introspect(t *testing.T) {
|
||||
{
|
||||
name: "client invalid secret, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
api, err := Instance.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
@@ -88,9 +90,9 @@ func TestServer_Introspect(t *testing.T) {
|
||||
{
|
||||
name: "client credentials on jwt client, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientJWT(CTX, project.GetId())
|
||||
api, err := Instance.CreateAPIClientJWT(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
@@ -104,9 +106,9 @@ func TestServer_Introspect(t *testing.T) {
|
||||
wantAudience = append(wantAudience, apiID)
|
||||
|
||||
scope := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess, oidc_api.ScopeResourceOwner}
|
||||
authRequestID := createAuthRequest(t, app.GetClientId(), redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, app.GetClientId(), redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -119,7 +121,7 @@ func TestServer_Introspect(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, app.GetClientId(), code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, app.GetClientId(), code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
@@ -133,7 +135,7 @@ func TestServer_Introspect(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
assertIntrospection(t, introspection,
|
||||
Tester.OIDCIssuer(), app.GetClientId(),
|
||||
Instance.OIDCIssuer(), app.GetClientId(),
|
||||
scope, wantAudience,
|
||||
tokens.Expiry, tokens.Expiry.Add(-12*time.Hour))
|
||||
})
|
||||
@@ -141,9 +143,11 @@ func TestServer_Introspect(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_Introspect_invalid_auth_invalid_token(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// ensure that when an invalid authentication and token is sent, the authentication error is returned
|
||||
// https://github.com/zitadel/zitadel/pull/8133
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, "xxxxx", "xxxxx")
|
||||
resourceServer, err := Instance.CreateResourceServerClientCredentials(CTX, "xxxxx", "xxxxx")
|
||||
require.NoError(t, err)
|
||||
_, err = rs.Introspect[*oidc.IntrospectionResponse](context.Background(), resourceServer, "xxxxx")
|
||||
require.Error(t, err)
|
||||
@@ -187,17 +191,19 @@ func assertIntrospection(
|
||||
// TestServer_VerifyClient tests verification by running code flow tests
|
||||
// with clients that have different authentication methods.
|
||||
func TestServer_VerifyClient(t *testing.T) {
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
t.Parallel()
|
||||
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
project, err := Instance.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
|
||||
inactiveClient, err := Tester.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
inactiveClient, err := Instance.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
nativeClient, err := Instance.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
basicWebClient, err := Tester.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
basicWebClient, err := Instance.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
jwtWebClient, keyData, err := Tester.CreateOIDCWebClientJWT(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
jwtWebClient, keyData, err := Instance.CreateOIDCWebClientJWT(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
|
||||
type clientDetails struct {
|
||||
@@ -295,9 +301,9 @@ func TestServer_VerifyClient(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, tt.client.authReqClientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, oidc.ScopeOpenID)
|
||||
authRequestID, err := Instance.CreateOIDCAuthRequest(CTX, tt.client.authReqClientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID)
|
||||
require.NoError(t, err)
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -313,7 +319,7 @@ func TestServer_VerifyClient(t *testing.T) {
|
||||
if tt.client.keyData != nil {
|
||||
options = append(options, rp.WithJWTProfile(rp.SignerFromKeyFile(tt.client.keyData)))
|
||||
}
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), tt.client.clientID, tt.client.clientSecret, redirectURI, []string{oidc.ScopeOpenID}, options...)
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), tt.client.clientID, tt.client.clientSecret, redirectURI, []string{oidc.ScopeOpenID}, options...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// test code exchange
|
@@ -18,17 +18,23 @@ import (
|
||||
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
|
||||
oidc_pb "github.com/zitadel/zitadel/pkg/grpc/oidc/v2"
|
||||
)
|
||||
|
||||
func TestServer_Keys(t *testing.T) {
|
||||
// TODO: isolated instance
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
instance := integration.NewInstance(CTX)
|
||||
ctxLogin := instance.WithAuthorization(CTX, integration.UserTypeLogin)
|
||||
|
||||
clientID, _ := createClient(t, instance)
|
||||
authRequestID := createAuthRequest(t, instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
|
||||
instance.RegisterUserPasskey(instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), instance.AdminUserID)
|
||||
sessionID, sessionToken, _, _ := instance.CreateVerifiedWebAuthNSession(t, ctxLogin, instance.AdminUserID)
|
||||
linkResp, err := instance.Client.OIDCv2.CreateCallback(ctxLogin, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -41,10 +47,10 @@ func TestServer_Keys(t *testing.T) {
|
||||
|
||||
// code exchange so we are sure there is 1 legacy key pair.
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
_, err = exchangeTokens(t, clientID, code, redirectURI)
|
||||
_, err = exchangeTokens(t, instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
|
||||
issuer := http_util.BuildHTTP(Tester.Config.ExternalDomain, Tester.Config.Port, Tester.Config.ExternalSecure)
|
||||
issuer := http_util.BuildHTTP(instance.Domain, instance.Config.Port, instance.Config.Secure)
|
||||
discovery, err := client.Discover(CTX, issuer, http.DefaultClient)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -66,7 +72,7 @@ func TestServer_Keys(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ensureWebKeyFeature(t, tt.webKeyFeature)
|
||||
ensureWebKeyFeature(t, instance, tt.webKeyFeature)
|
||||
|
||||
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
resp, err := http.Get(discovery.JwksURI)
|
||||
@@ -100,14 +106,16 @@ func TestServer_Keys(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func ensureWebKeyFeature(t *testing.T, set bool) {
|
||||
_, err := Tester.Client.FeatureV2.SetInstanceFeatures(CTXIAM, &feature.SetInstanceFeaturesRequest{
|
||||
func ensureWebKeyFeature(t *testing.T, instance *integration.Instance, set bool) {
|
||||
ctxIam := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
_, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{
|
||||
WebKey: proto.Bool(set),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_, err := Tester.Client.FeatureV2.SetInstanceFeatures(CTXIAM, &feature.SetInstanceFeaturesRequest{
|
||||
_, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{
|
||||
WebKey: proto.Bool(false),
|
||||
})
|
||||
require.NoError(t, err)
|
@@ -28,7 +28,7 @@ var (
|
||||
CTX context.Context
|
||||
CTXLOGIN context.Context
|
||||
CTXIAM context.Context
|
||||
Tester *integration.Tester
|
||||
Instance *integration.Instance
|
||||
User *user.AddHumanUserResponse
|
||||
)
|
||||
|
||||
@@ -41,27 +41,26 @@ const (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(func() int {
|
||||
ctx, _, cancel := integration.Contexts(10 * time.Minute)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
Tester = integration.NewTester(ctx)
|
||||
defer Tester.Done()
|
||||
Instance = integration.NewInstance(ctx)
|
||||
|
||||
CTX = Tester.WithAuthorization(ctx, integration.OrgOwner)
|
||||
User = Tester.CreateHumanUser(CTX)
|
||||
Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false)
|
||||
Tester.RegisterUserPasskey(CTX, User.GetUserId())
|
||||
CTXLOGIN = Tester.WithAuthorization(ctx, integration.Login)
|
||||
CTXIAM = Tester.WithAuthorization(ctx, integration.IAMOwner)
|
||||
CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner)
|
||||
User = Instance.CreateHumanUser(CTX)
|
||||
Instance.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false)
|
||||
Instance.RegisterUserPasskey(CTX, User.GetUserId())
|
||||
CTXLOGIN = Instance.WithAuthorization(ctx, integration.UserTypeLogin)
|
||||
CTXIAM = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
|
||||
return m.Run()
|
||||
}())
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_missing_audience_scope(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -74,22 +73,22 @@ func Test_ZITADEL_API_missing_audience_scope(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_missing_authentication(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
createResp, err := Tester.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
createResp, err := Instance.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
Checks: &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{UserId: User.GetUserId()},
|
||||
@@ -97,7 +96,7 @@ func Test_ZITADEL_API_missing_authentication(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -110,24 +109,24 @@ func Test_ZITADEL_API_missing_authentication(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
org := Tester.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_API_MISSING_MFA_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
|
||||
clientID, _ := createClient(t, Instance)
|
||||
org := Instance.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_API_MISSING_MFA_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
|
||||
userID := org.CreatedAdmins[0].GetUserId()
|
||||
Tester.SetUserPassword(CTXIAM, userID, integration.UserPassword, false)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreatePasswordSession(t, CTXLOGIN, userID, integration.UserPassword)
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
Instance.SetUserPassword(CTXIAM, userID, integration.UserPassword, false)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreatePasswordSession(t, CTXLOGIN, userID, integration.UserPassword)
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -140,20 +139,20 @@ func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, userID, armPassword, startTime, changeTime, sessionID)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
// pre check if request would succeed
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, userID, myUserResp.GetUser().GetId())
|
||||
|
||||
// require MFA
|
||||
ctxOrg := metadata.AppendToOutgoingContext(CTXIAM, "x-zitadel-orgid", org.GetOrganizationId())
|
||||
_, err = Tester.Client.Mgmt.AddCustomLoginPolicy(ctxOrg, &mgmt.AddCustomLoginPolicyRequest{
|
||||
_, err = Instance.Client.Mgmt.AddCustomLoginPolicy(ctxOrg, &mgmt.AddCustomLoginPolicyRequest{
|
||||
ForceMfa: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -164,23 +163,23 @@ func Test_ZITADEL_API_missing_mfa_policy(t *testing.T) {
|
||||
retryDuration = time.Until(ctxDeadline)
|
||||
}
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, getErr := Tester.Client.Mgmt.GetLoginPolicy(ctxOrg, &mgmt.GetLoginPolicyRequest{})
|
||||
got, getErr := Instance.Client.Mgmt.GetLoginPolicy(ctxOrg, &mgmt.GetLoginPolicyRequest{})
|
||||
assert.NoError(ttt, getErr)
|
||||
assert.False(ttt, got.GetPolicy().IsDefault)
|
||||
|
||||
}, retryDuration, time.Millisecond*100, "timeout waiting for login policy")
|
||||
|
||||
// now it must fail
|
||||
myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_success(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -193,28 +192,28 @@ func Test_ZITADEL_API_success(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_glob_redirects(t *testing.T) {
|
||||
const redirectURI = "https://my-org-1yfnjl2xj-my-app.vercel.app/api/auth/callback/zitadel"
|
||||
clientID, _ := createClientWithOpts(t, clientOpts{
|
||||
clientID, _ := createClientWithOpts(t, Instance, clientOpts{
|
||||
redirectURI: "https://my-org-*-my-app.vercel.app/api/auth/callback/zitadel",
|
||||
logoutURI: "https://my-org-*-my-app.vercel.app/",
|
||||
devMode: true,
|
||||
})
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -227,23 +226,23 @@ func Test_ZITADEL_API_glob_redirects(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
clientID, _ := createClient(t, Instance)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -256,14 +255,14 @@ func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
// make sure token works
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
|
||||
@@ -274,18 +273,18 @@ func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
|
||||
|
||||
// use invalidated token
|
||||
ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_terminated_session(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -298,14 +297,14 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
||||
|
||||
// make sure token works
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
|
||||
@@ -316,13 +315,13 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) {
|
||||
|
||||
// use token from terminated session
|
||||
ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
clientID, _ := createClient(t, Instance)
|
||||
tests := []struct {
|
||||
name string
|
||||
disable func(userID string) error
|
||||
@@ -330,32 +329,32 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) {
|
||||
{
|
||||
name: "deactivated",
|
||||
disable: func(userID string) error {
|
||||
_, err := Tester.Client.UserV2.DeactivateUser(CTX, &user.DeactivateUserRequest{UserId: userID})
|
||||
_, err := Instance.Client.UserV2.DeactivateUser(CTX, &user.DeactivateUserRequest{UserId: userID})
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "locked",
|
||||
disable: func(userID string) error {
|
||||
_, err := Tester.Client.UserV2.LockUser(CTX, &user.LockUserRequest{UserId: userID})
|
||||
_, err := Instance.Client.UserV2.LockUser(CTX, &user.LockUserRequest{UserId: userID})
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deleted",
|
||||
disable: func(userID string) error {
|
||||
_, err := Tester.Client.UserV2.DeleteUser(CTX, &user.DeleteUserRequest{UserId: userID})
|
||||
_, err := Instance.Client.UserV2.DeleteUser(CTX, &user.DeleteUserRequest{UserId: userID})
|
||||
return err
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
disabledUser := Tester.CreateHumanUser(CTX)
|
||||
Tester.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword, false)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreatePasswordSession(t, CTXLOGIN, disabledUser.GetUserId(), integration.UserPassword)
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
disabledUser := Instance.CreateHumanUser(CTX)
|
||||
Instance.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword, false)
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreatePasswordSession(t, CTXLOGIN, disabledUser.GetUserId(), integration.UserPassword)
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -368,14 +367,14 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) {
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, disabledUser.GetUserId(), armPassword, startTime, changeTime, sessionID)
|
||||
|
||||
// make sure token works
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err := Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, disabledUser.GetUserId(), myUserResp.GetUser().GetId())
|
||||
|
||||
@@ -385,15 +384,15 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) {
|
||||
|
||||
// use token from deactivated user
|
||||
ctx = metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
myUserResp, err = Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
myUserResp, err = Instance.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, myUserResp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createClient(t testing.TB) (clientID, projectID string) {
|
||||
return createClientWithOpts(t, clientOpts{
|
||||
func createClient(t testing.TB, instance *integration.Instance) (clientID, projectID string) {
|
||||
return createClientWithOpts(t, instance, clientOpts{
|
||||
redirectURI: redirectURI,
|
||||
logoutURI: logoutRedirectURI,
|
||||
devMode: false,
|
||||
@@ -406,28 +405,30 @@ type clientOpts struct {
|
||||
devMode bool
|
||||
}
|
||||
|
||||
func createClientWithOpts(t testing.TB, opts clientOpts) (clientID, projectID string) {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
func createClientWithOpts(t testing.TB, instance *integration.Instance, opts clientOpts) (clientID, projectID string) {
|
||||
ctx := instance.WithAuthorization(CTX, integration.UserTypeOrgOwner)
|
||||
|
||||
project, err := instance.CreateProject(ctx)
|
||||
require.NoError(t, err)
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode)
|
||||
app, err := instance.CreateOIDCNativeClient(ctx, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode)
|
||||
require.NoError(t, err)
|
||||
return app.GetClientId(), project.GetId()
|
||||
}
|
||||
|
||||
func createImplicitClient(t testing.TB) string {
|
||||
app, err := Tester.CreateOIDCImplicitFlowClient(CTX, redirectURIImplicit)
|
||||
app, err := Instance.CreateOIDCImplicitFlowClient(CTX, redirectURIImplicit)
|
||||
require.NoError(t, err)
|
||||
return app.GetClientId()
|
||||
}
|
||||
|
||||
func createAuthRequest(t testing.TB, clientID, redirectURI string, scope ...string) string {
|
||||
redURL, err := Tester.CreateOIDCAuthRequest(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
|
||||
func createAuthRequest(t testing.TB, instance *integration.Instance, clientID, redirectURI string, scope ...string) string {
|
||||
redURL, err := instance.CreateOIDCAuthRequest(CTX, clientID, instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, scope...)
|
||||
require.NoError(t, err)
|
||||
return redURL
|
||||
}
|
||||
|
||||
func createAuthRequestImplicit(t testing.TB, clientID, redirectURI string, scope ...string) string {
|
||||
redURL, err := Tester.CreateOIDCAuthRequestImplicit(CTX, clientID, Tester.Users[integration.FirstInstanceUsersKey][integration.Login].ID, redirectURI, scope...)
|
||||
redURL, err := Instance.CreateOIDCAuthRequestImplicit(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, scope...)
|
||||
require.NoError(t, err)
|
||||
return redURL
|
||||
}
|
||||
@@ -437,5 +438,5 @@ func assertOIDCTime(t *testing.T, actual oidc.Time, expected time.Time) {
|
||||
}
|
||||
|
||||
func assertOIDCTimeRange(t *testing.T, actual oidc.Time, expectedStart, expectedEnd time.Time) {
|
||||
assert.WithinRange(t, actual.AsTime(), expectedStart.Add(-1*time.Second), expectedEnd.Add(1*time.Second))
|
||||
assert.WithinRange(t, actual.AsTime(), expectedStart.Add(-10*time.Second), expectedEnd.Add(10*time.Second))
|
||||
}
|
@@ -18,8 +18,10 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_RefreshToken_Status(t *testing.T) {
|
||||
clientID, _ := createClient(t)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
t.Parallel()
|
||||
|
||||
clientID, _ := createClient(t, Instance)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
@@ -19,7 +19,9 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_ClientCredentialsExchange(t *testing.T) {
|
||||
machine, name, clientID, clientSecret, err := Tester.CreateOIDCCredentialsClient(CTX)
|
||||
t.Parallel()
|
||||
|
||||
machine, name, clientID, clientSecret, err := Instance.CreateOIDCCredentialsClient(CTX)
|
||||
require.NoError(t, err)
|
||||
|
||||
type claims struct {
|
||||
@@ -57,7 +59,7 @@ func TestServer_ClientCredentialsExchange(t *testing.T) {
|
||||
name: "machine user without secret error",
|
||||
clientID: func() string {
|
||||
name := gofakeit.Username()
|
||||
_, err := Tester.Client.Mgmt.AddMachineUser(CTX, &management.AddMachineUserRequest{
|
||||
_, err := Instance.Client.Mgmt.AddMachineUser(CTX, &management.AddMachineUserRequest{
|
||||
Name: name,
|
||||
UserName: name,
|
||||
AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT,
|
||||
@@ -99,14 +101,14 @@ func TestServer_ClientCredentialsExchange(t *testing.T) {
|
||||
clientSecret: clientSecret,
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID,
|
||||
domain.OrgIDScope + Tester.Organisation.ID,
|
||||
domain.OrgDomainPrimaryScope + Tester.Organisation.Domain,
|
||||
domain.OrgIDScope + Instance.DefaultOrg.Id,
|
||||
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
wantClaims: claims{
|
||||
resourceOwnerID: Tester.Organisation.ID,
|
||||
resourceOwnerName: Tester.Organisation.Name,
|
||||
resourceOwnerPrimaryDomain: Tester.Organisation.Domain,
|
||||
orgDomain: Tester.Organisation.Domain,
|
||||
resourceOwnerID: Instance.DefaultOrg.Id,
|
||||
resourceOwnerName: Instance.DefaultOrg.Name,
|
||||
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
orgDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -115,10 +117,10 @@ func TestServer_ClientCredentialsExchange(t *testing.T) {
|
||||
clientSecret: clientSecret,
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID,
|
||||
domain.OrgDomainPrimaryScope + Tester.Organisation.Domain,
|
||||
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
|
||||
domain.OrgDomainPrimaryScope + "foo"},
|
||||
wantClaims: claims{
|
||||
orgDomain: Tester.Organisation.Domain,
|
||||
orgDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -126,19 +128,19 @@ func TestServer_ClientCredentialsExchange(t *testing.T) {
|
||||
clientID: clientID,
|
||||
clientSecret: clientSecret,
|
||||
scope: []string{oidc.ScopeOpenID,
|
||||
domain.OrgIDScope + Tester.Organisation.ID,
|
||||
domain.OrgIDScope + Instance.DefaultOrg.Id,
|
||||
domain.OrgIDScope + "foo",
|
||||
},
|
||||
wantClaims: claims{
|
||||
resourceOwnerID: Tester.Organisation.ID,
|
||||
resourceOwnerName: Tester.Organisation.Name,
|
||||
resourceOwnerPrimaryDomain: Tester.Organisation.Domain,
|
||||
resourceOwnerID: Instance.DefaultOrg.Id,
|
||||
resourceOwnerName: Instance.DefaultOrg.Name,
|
||||
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), tt.clientID, tt.clientSecret, redirectURI, tt.scope)
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), tt.clientID, tt.clientSecret, redirectURI, tt.scope)
|
||||
require.NoError(t, err)
|
||||
tokens, err := rp.ClientCredentials(CTX, provider, nil)
|
||||
if tt.wantErr {
|
@@ -26,9 +26,9 @@ import (
|
||||
)
|
||||
|
||||
func setTokenExchangeFeature(t *testing.T, value bool) {
|
||||
iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner)
|
||||
iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
_, err := Tester.Client.FeatureV2.SetInstanceFeatures(iamCTX, &feature.SetInstanceFeaturesRequest{
|
||||
_, err := Instance.Client.FeatureV2.SetInstanceFeatures(iamCTX, &feature.SetInstanceFeaturesRequest{
|
||||
OidcTokenExchange: proto.Bool(value),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -36,19 +36,19 @@ func setTokenExchangeFeature(t *testing.T, value bool) {
|
||||
}
|
||||
|
||||
func resetFeatures(t *testing.T) {
|
||||
iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner)
|
||||
_, err := Tester.Client.FeatureV2.ResetInstanceFeatures(iamCTX, &feature.ResetInstanceFeaturesRequest{})
|
||||
iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
_, err := Instance.Client.FeatureV2.ResetInstanceFeatures(iamCTX, &feature.ResetInstanceFeaturesRequest{})
|
||||
require.NoError(t, err)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
func setImpersonationPolicy(t *testing.T, value bool) {
|
||||
iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner)
|
||||
iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
policy, err := Tester.Client.Admin.GetSecurityPolicy(iamCTX, &admin.GetSecurityPolicyRequest{})
|
||||
policy, err := Instance.Client.Admin.GetSecurityPolicy(iamCTX, &admin.GetSecurityPolicyRequest{})
|
||||
require.NoError(t, err)
|
||||
if policy.GetPolicy().GetEnableImpersonation() != value {
|
||||
_, err = Tester.Client.Admin.SetSecurityPolicy(iamCTX, &admin.SetSecurityPolicyRequest{
|
||||
_, err = Instance.Client.Admin.SetSecurityPolicy(iamCTX, &admin.SetSecurityPolicyRequest{
|
||||
EnableImpersonation: value,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -57,8 +57,8 @@ func setImpersonationPolicy(t *testing.T, value bool) {
|
||||
}
|
||||
|
||||
func createMachineUserPATWithMembership(t *testing.T, roles ...string) (userID, pat string) {
|
||||
iamCTX := Tester.WithAuthorization(CTX, integration.IAMOwner)
|
||||
userID, pat, err := Tester.CreateMachineUserPATWithMembership(iamCTX, roles...)
|
||||
iamCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
userID, pat, err := Instance.CreateMachineUserPATWithMembership(iamCTX, roles...)
|
||||
require.NoError(t, err)
|
||||
return userID, pat
|
||||
}
|
||||
@@ -112,16 +112,18 @@ func refreshTokenVerifier(ctx context.Context, provider rp.RelyingParty, subject
|
||||
}
|
||||
|
||||
func TestServer_TokenExchange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Cleanup(func() {
|
||||
resetFeatures(t)
|
||||
setImpersonationPolicy(t, false)
|
||||
})
|
||||
|
||||
client, keyData, err := Tester.CreateOIDCTokenExchangeClient(CTX)
|
||||
client, keyData, err := Instance.CreateOIDCTokenExchangeClient(CTX)
|
||||
require.NoError(t, err)
|
||||
signer, err := rp.SignerFromKeyFile(keyData)()
|
||||
require.NoError(t, err)
|
||||
exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Tester.OIDCIssuer(), client.GetClientId(), signer)
|
||||
exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Instance.OIDCIssuer(), client.GetClientId(), signer)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(time.Second)
|
||||
@@ -137,9 +139,9 @@ func TestServer_TokenExchange(t *testing.T) {
|
||||
|
||||
patScopes := oidc.SpaceDelimitedArray{"openid", "profile", "urn:zitadel:iam:user:metadata", "urn:zitadel:iam:user:resourceowner"}
|
||||
|
||||
relyingParty, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), client.GetClientId(), "", "", []string{"openid"}, rp.WithJWTProfile(rp.SignerFromKeyFile(keyData)))
|
||||
relyingParty, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), client.GetClientId(), "", "", []string{"openid"}, rp.WithJWTProfile(rp.SignerFromKeyFile(keyData)))
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyData)
|
||||
resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyData)
|
||||
require.NoError(t, err)
|
||||
|
||||
type settings struct {
|
||||
@@ -481,7 +483,7 @@ func TestServer_TokenExchange(t *testing.T) {
|
||||
token, err := crypto.Sign(&oidc.JWTTokenRequest{
|
||||
Issuer: client.GetClientId(),
|
||||
Subject: User.GetUserId(),
|
||||
Audience: oidc.Audience{Tester.OIDCIssuer()},
|
||||
Audience: oidc.Audience{Instance.OIDCIssuer()},
|
||||
ExpiresAt: oidc.FromTime(time.Now().Add(time.Hour)),
|
||||
IssuedAt: oidc.FromTime(time.Now().Add(-time.Second)),
|
||||
}, signer)
|
||||
@@ -559,13 +561,13 @@ func TestServer_TokenExchange(t *testing.T) {
|
||||
// This test tries to call the zitadel API with an impersonated token,
|
||||
// which should fail.
|
||||
func TestImpersonation_API_Call(t *testing.T) {
|
||||
client, keyData, err := Tester.CreateOIDCTokenExchangeClient(CTX)
|
||||
client, keyData, err := Instance.CreateOIDCTokenExchangeClient(CTX)
|
||||
require.NoError(t, err)
|
||||
signer, err := rp.SignerFromKeyFile(keyData)()
|
||||
require.NoError(t, err)
|
||||
exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Tester.OIDCIssuer(), client.GetClientId(), signer)
|
||||
exchanger, err := tokenexchange.NewTokenExchangerJWTProfile(CTX, Instance.OIDCIssuer(), client.GetClientId(), signer)
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyData)
|
||||
resourceServer, err := Instance.CreateResourceServerJWTProfile(CTX, keyData)
|
||||
require.NoError(t, err)
|
||||
|
||||
setTokenExchangeFeature(t, true)
|
||||
@@ -576,15 +578,15 @@ func TestImpersonation_API_Call(t *testing.T) {
|
||||
})
|
||||
|
||||
iamUserID, iamImpersonatorPAT := createMachineUserPATWithMembership(t, "IAM_ADMIN_IMPERSONATOR")
|
||||
iamOwner := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.IAMOwner)
|
||||
iamOwner := Instance.Users.Get(integration.UserTypeIAMOwner)
|
||||
|
||||
// impersonating the IAM owner!
|
||||
resp, err := tokenexchange.ExchangeToken(CTX, exchanger, iamOwner.Token, oidc.AccessTokenType, iamImpersonatorPAT, oidc.AccessTokenType, nil, nil, nil, oidc.AccessTokenType)
|
||||
require.NoError(t, err)
|
||||
accessTokenVerifier(CTX, resourceServer, iamOwner.ID, iamUserID)
|
||||
|
||||
impersonatedCTX := Tester.WithAuthorizationToken(CTX, resp.AccessToken)
|
||||
_, err = Tester.Client.Admin.GetAllowedLanguages(impersonatedCTX, &admin.GetAllowedLanguagesRequest{})
|
||||
impersonatedCTX := integration.WithAuthorizationToken(CTX, resp.AccessToken)
|
||||
_, err = Instance.Client.Admin.GetAllowedLanguages(impersonatedCTX, &admin.GetAllowedLanguagesRequest{})
|
||||
status := status.Convert(err)
|
||||
assert.Equal(t, codes.PermissionDenied, status.Code())
|
||||
assert.Equal(t, "Errors.TokenExchange.Token.NotForAPI (APP-Shi0J)", status.Message())
|
@@ -17,7 +17,9 @@ import (
|
||||
)
|
||||
|
||||
func TestServer_JWTProfile(t *testing.T) {
|
||||
user, name, keyData, err := Tester.CreateOIDCJWTProfileClient(CTX)
|
||||
t.Parallel()
|
||||
|
||||
user, name, keyData, err := Instance.CreateOIDCJWTProfileClient(CTX)
|
||||
require.NoError(t, err)
|
||||
|
||||
type claims struct {
|
||||
@@ -56,14 +58,14 @@ func TestServer_JWTProfile(t *testing.T) {
|
||||
keyData: keyData,
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID,
|
||||
domain.OrgIDScope + Tester.Organisation.ID,
|
||||
domain.OrgDomainPrimaryScope + Tester.Organisation.Domain,
|
||||
domain.OrgIDScope + Instance.DefaultOrg.Id,
|
||||
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
wantClaims: claims{
|
||||
resourceOwnerID: Tester.Organisation.ID,
|
||||
resourceOwnerName: Tester.Organisation.Name,
|
||||
resourceOwnerPrimaryDomain: Tester.Organisation.Domain,
|
||||
orgDomain: Tester.Organisation.Domain,
|
||||
resourceOwnerID: Instance.DefaultOrg.Id,
|
||||
resourceOwnerName: Instance.DefaultOrg.Name,
|
||||
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
orgDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -71,29 +73,29 @@ func TestServer_JWTProfile(t *testing.T) {
|
||||
keyData: keyData,
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID,
|
||||
domain.OrgDomainPrimaryScope + Tester.Organisation.Domain,
|
||||
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
|
||||
domain.OrgDomainPrimaryScope + "foo"},
|
||||
wantClaims: claims{
|
||||
orgDomain: Tester.Organisation.Domain,
|
||||
orgDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid org id filtered",
|
||||
keyData: keyData,
|
||||
scope: []string{oidc.ScopeOpenID,
|
||||
domain.OrgIDScope + Tester.Organisation.ID,
|
||||
domain.OrgIDScope + Instance.DefaultOrg.Id,
|
||||
domain.OrgIDScope + "foo",
|
||||
},
|
||||
wantClaims: claims{
|
||||
resourceOwnerID: Tester.Organisation.ID,
|
||||
resourceOwnerName: Tester.Organisation.Name,
|
||||
resourceOwnerPrimaryDomain: Tester.Organisation.Domain,
|
||||
resourceOwnerID: Instance.DefaultOrg.Id,
|
||||
resourceOwnerName: Instance.DefaultOrg.Name,
|
||||
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tokenSource, err := profile.NewJWTProfileTokenSourceFromKeyFileData(CTX, Tester.OIDCIssuer(), tt.keyData, tt.scope)
|
||||
tokenSource, err := profile.NewJWTProfileTokenSourceFromKeyFileData(CTX, Instance.OIDCIssuer(), tt.keyData, tt.scope)
|
||||
require.NoError(t, err)
|
||||
|
||||
tokens, err := tokenSource.TokenCtx(CTX)
|
||||
@@ -104,7 +106,7 @@ func TestServer_JWTProfile(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokens)
|
||||
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), "", "", redirectURI, tt.scope)
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), "", "", redirectURI, tt.scope)
|
||||
require.NoError(t, err)
|
||||
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, oidc.BearerToken, user.GetUserId(), provider)
|
||||
require.NoError(t, err)
|
@@ -27,9 +27,9 @@ import (
|
||||
// userinfo integration test against a matrix of different feature flags.
|
||||
// This ensure that the response of the different implementations remains the same.
|
||||
func TestServer_UserInfo(t *testing.T) {
|
||||
iamOwnerCTX := Tester.WithAuthorization(CTX, integration.IAMOwner)
|
||||
iamOwnerCTX := Instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
t.Cleanup(func() {
|
||||
_, err := Tester.Client.FeatureV2.ResetInstanceFeatures(iamOwnerCTX, &feature.ResetInstanceFeaturesRequest{})
|
||||
_, err := Instance.Client.FeatureV2.ResetInstanceFeatures(iamOwnerCTX, &feature.ResetInstanceFeaturesRequest{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
tests := []struct {
|
||||
@@ -67,7 +67,7 @@ func TestServer_UserInfo(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := Tester.Client.FeatureV2.SetInstanceFeatures(iamOwnerCTX, &feature.SetInstanceFeaturesRequest{
|
||||
_, err := Instance.Client.FeatureV2.SetInstanceFeatures(iamOwnerCTX, &feature.SetInstanceFeaturesRequest{
|
||||
OidcLegacyIntrospection: &tt.legacy,
|
||||
OidcTriggerIntrospectionProjections: &tt.trigger,
|
||||
WebKey: &tt.webKey,
|
||||
@@ -86,7 +86,7 @@ func testServer_UserInfo(t *testing.T) {
|
||||
roleBar = "bar"
|
||||
)
|
||||
|
||||
clientID, projectID := createClient(t)
|
||||
clientID, projectID := createClient(t, Instance)
|
||||
addProjectRolesGrants(t, User.GetUserId(), projectID, roleFoo, roleBar)
|
||||
|
||||
tests := []struct {
|
||||
@@ -133,21 +133,21 @@ func testServer_UserInfo(t *testing.T) {
|
||||
{
|
||||
name: "project role assertion",
|
||||
prepare: func(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] {
|
||||
_, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
_, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
Id: projectID,
|
||||
Name: fmt.Sprintf("project-%d", time.Now().UnixNano()),
|
||||
ProjectRoleAssertion: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
_, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
Id: projectID,
|
||||
Name: fmt.Sprintf("project-%d", time.Now().UnixNano()),
|
||||
ProjectRoleAssertion: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
resp, err := Tester.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID})
|
||||
resp, err := Instance.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID})
|
||||
require.NoError(t, err)
|
||||
require.True(t, resp.GetProject().GetProjectRoleAssertion(), "project role assertion")
|
||||
|
||||
@@ -157,7 +157,7 @@ func testServer_UserInfo(t *testing.T) {
|
||||
assertions: []func(*testing.T, *oidc.UserInfo){
|
||||
assertUserinfo,
|
||||
func(t *testing.T, ui *oidc.UserInfo) {
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo, roleBar}, []string{Tester.Organisation.ID})
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo, roleBar}, []string{Instance.DefaultOrg.Id})
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -170,7 +170,7 @@ func testServer_UserInfo(t *testing.T) {
|
||||
assertions: []func(*testing.T, *oidc.UserInfo){
|
||||
assertUserinfo,
|
||||
func(t *testing.T, ui *oidc.UserInfo) {
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Tester.Organisation.ID})
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Instance.DefaultOrg.Id})
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -184,14 +184,14 @@ func testServer_UserInfo(t *testing.T) {
|
||||
assertions: []func(*testing.T, *oidc.UserInfo){
|
||||
assertUserinfo,
|
||||
func(t *testing.T, ui *oidc.UserInfo) {
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Tester.Organisation.ID})
|
||||
assertProjectRoleClaims(t, projectID, ui.Claims, true, []string{roleFoo}, []string{Instance.DefaultOrg.Id})
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PAT",
|
||||
prepare: func(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] {
|
||||
user := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.OrgOwner)
|
||||
user := Instance.Users.Get(integration.UserTypeOrgOwner)
|
||||
return &oidc.Tokens[*oidc.IDTokenClaims]{
|
||||
Token: &oauth2.Token{
|
||||
AccessToken: user.Token,
|
||||
@@ -206,11 +206,8 @@ func testServer_UserInfo(t *testing.T) {
|
||||
},
|
||||
assertions: []func(*testing.T, *oidc.UserInfo){
|
||||
func(t *testing.T, ui *oidc.UserInfo) {
|
||||
user := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.OrgOwner)
|
||||
user := Instance.Users.Get(integration.UserTypeOrgOwner)
|
||||
assert.Equal(t, user.ID, ui.Subject)
|
||||
assert.Equal(t, user.PreferredLoginName, ui.PreferredUsername)
|
||||
assert.Equal(t, user.Machine.Name, ui.Name)
|
||||
assert.Equal(t, user.ResourceOwner, ui.Claims[oidc_api.ClaimResourceOwnerID])
|
||||
assert.NotEmpty(t, ui.Claims[oidc_api.ClaimResourceOwnerName])
|
||||
assert.NotEmpty(t, ui.Claims[oidc_api.ClaimResourceOwnerPrimaryDomain])
|
||||
},
|
||||
@@ -220,7 +217,7 @@ func testServer_UserInfo(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tokens := tt.prepare(t, clientID, tt.scope)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
|
||||
if tt.wantErr {
|
||||
@@ -242,17 +239,17 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) {
|
||||
roleFoo = "foo"
|
||||
roleBar = "bar"
|
||||
)
|
||||
clientID, projectID := createClient(t)
|
||||
clientID, projectID := createClient(t, Instance)
|
||||
addProjectRolesGrants(t, User.GetUserId(), projectID, roleFoo, roleBar)
|
||||
grantedOrgID := addProjectOrgGrant(t, User.GetUserId(), projectID, roleFoo, roleBar)
|
||||
|
||||
_, err := Tester.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
_, err := Instance.Client.Mgmt.UpdateProject(CTX, &management.UpdateProjectRequest{
|
||||
Id: projectID,
|
||||
Name: fmt.Sprintf("project-%d", time.Now().UnixNano()),
|
||||
ProjectRoleAssertion: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
resp, err := Tester.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID})
|
||||
resp, err := Instance.Client.Mgmt.GetProjectByID(CTX, &management.GetProjectByIDRequest{Id: projectID})
|
||||
require.NoError(t, err)
|
||||
require.True(t, resp.GetProject().GetProjectRoleAssertion(), "project role assertion")
|
||||
|
||||
@@ -266,7 +263,7 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) {
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID, oidc.ScopeOfflineAccess,
|
||||
},
|
||||
wantRoleOrgIDs: []string{Tester.Organisation.ID, grantedOrgID},
|
||||
wantRoleOrgIDs: []string{Instance.DefaultOrg.Id, grantedOrgID},
|
||||
},
|
||||
{
|
||||
name: "only granted org",
|
||||
@@ -279,24 +276,24 @@ func TestServer_UserInfo_OrgIDRoles(t *testing.T) {
|
||||
name: "only own org",
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID, oidc.ScopeOfflineAccess,
|
||||
domain.OrgRoleIDScope + Tester.Organisation.ID,
|
||||
domain.OrgRoleIDScope + Instance.DefaultOrg.Id,
|
||||
},
|
||||
wantRoleOrgIDs: []string{Tester.Organisation.ID},
|
||||
wantRoleOrgIDs: []string{Instance.DefaultOrg.Id},
|
||||
},
|
||||
{
|
||||
name: "request both orgs",
|
||||
scope: []string{
|
||||
oidc.ScopeOpenID, oidc.ScopeOfflineAccess,
|
||||
domain.OrgRoleIDScope + Tester.Organisation.ID,
|
||||
domain.OrgRoleIDScope + Instance.DefaultOrg.Id,
|
||||
domain.OrgRoleIDScope + grantedOrgID,
|
||||
},
|
||||
wantRoleOrgIDs: []string{Tester.Organisation.ID, grantedOrgID},
|
||||
wantRoleOrgIDs: []string{Instance.DefaultOrg.Id, grantedOrgID},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tokens := getTokens(t, clientID, tt.scope)
|
||||
provider, err := Tester.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
provider, err := Instance.CreateRelyingParty(CTX, clientID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, tokens.IDTokenClaims.Subject, provider)
|
||||
require.NoError(t, err)
|
||||
@@ -312,10 +309,10 @@ func TestServer_UserInfo_Issue6662(t *testing.T) {
|
||||
roleBar = "bar"
|
||||
)
|
||||
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
project, err := Instance.CreateProject(CTX)
|
||||
projectID := project.GetId()
|
||||
require.NoError(t, err)
|
||||
user, _, clientID, clientSecret, err := Tester.CreateOIDCCredentialsClient(CTX)
|
||||
user, _, clientID, clientSecret, err := Instance.CreateOIDCCredentialsClient(CTX)
|
||||
require.NoError(t, err)
|
||||
addProjectRolesGrants(t, user.GetUserId(), projectID, roleFoo, roleBar)
|
||||
|
||||
@@ -324,14 +321,14 @@ func TestServer_UserInfo_Issue6662(t *testing.T) {
|
||||
domain.ProjectIDScope + projectID + domain.AudSuffix,
|
||||
}
|
||||
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Tester.OIDCIssuer(), clientID, clientSecret, redirectURI, scope)
|
||||
provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), clientID, clientSecret, redirectURI, scope)
|
||||
require.NoError(t, err)
|
||||
tokens, err := rp.ClientCredentials(CTX, provider, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, tokens.TokenType, user.GetUserId(), provider)
|
||||
require.NoError(t, err)
|
||||
assertProjectRoleClaims(t, projectID, userinfo.Claims, false, []string{roleFoo}, []string{Tester.Organisation.ID})
|
||||
assertProjectRoleClaims(t, projectID, userinfo.Claims, false, []string{roleFoo}, []string{Instance.DefaultOrg.Id})
|
||||
}
|
||||
|
||||
func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...string) {
|
||||
@@ -343,12 +340,12 @@ func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...stri
|
||||
DisplayName: role,
|
||||
}
|
||||
}
|
||||
_, err := Tester.Client.Mgmt.BulkAddProjectRoles(CTX, &management.BulkAddProjectRolesRequest{
|
||||
_, err := Instance.Client.Mgmt.BulkAddProjectRoles(CTX, &management.BulkAddProjectRolesRequest{
|
||||
ProjectId: projectID,
|
||||
Roles: bulkRoles,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Tester.Client.Mgmt.AddUserGrant(CTX, &management.AddUserGrantRequest{
|
||||
_, err = Instance.Client.Mgmt.AddUserGrant(CTX, &management.AddUserGrantRequest{
|
||||
UserId: userID,
|
||||
ProjectId: projectID,
|
||||
RoleKeys: roles,
|
||||
@@ -359,8 +356,8 @@ func addProjectRolesGrants(t *testing.T, userID, projectID string, roles ...stri
|
||||
// addProjectOrgGrant adds a new organization which will be granted on the projectID with the specified roles.
|
||||
// The userID will be granted in the new organization to the project with the same roles.
|
||||
func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string) (grantedOrgID string) {
|
||||
grantedOrg := Tester.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_GRANTED_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
|
||||
projectGrant, err := Tester.Client.Mgmt.AddProjectGrant(CTX, &management.AddProjectGrantRequest{
|
||||
grantedOrg := Instance.CreateOrganization(CTXIAM, fmt.Sprintf("ZITADEL_GRANTED_%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
|
||||
projectGrant, err := Instance.Client.Mgmt.AddProjectGrant(CTX, &management.AddProjectGrantRequest{
|
||||
ProjectId: projectID,
|
||||
GrantedOrgId: grantedOrg.GetOrganizationId(),
|
||||
RoleKeys: roles,
|
||||
@@ -368,7 +365,7 @@ func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctxOrg := metadata.AppendToOutgoingContext(CTXIAM, "x-zitadel-orgid", grantedOrg.GetOrganizationId())
|
||||
_, err = Tester.Client.Mgmt.AddUserGrant(ctxOrg, &management.AddUserGrantRequest{
|
||||
_, err = Instance.Client.Mgmt.AddUserGrant(ctxOrg, &management.AddUserGrantRequest{
|
||||
UserId: userID,
|
||||
ProjectId: projectID,
|
||||
ProjectGrantId: projectGrant.GetGrantId(),
|
||||
@@ -379,9 +376,9 @@ func addProjectOrgGrant(t *testing.T, userID, projectID string, roles ...string)
|
||||
}
|
||||
|
||||
func getTokens(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc.IDTokenClaims] {
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
authRequestID := createAuthRequest(t, Instance, clientID, redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Instance.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Instance.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
@@ -394,7 +391,7 @@ func getTokens(t *testing.T, clientID string, scope []string) *oidc.Tokens[*oidc
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code, redirectURI)
|
||||
tokens, err := exchangeTokens(t, Instance, clientID, code, redirectURI)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, User.GetUserId(), armPasskey, startTime, changeTime, sessionID)
|
@@ -7,9 +7,10 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||
"github.com/zitadel/oidc/v3/pkg/op"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/feature"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func TestServer_createDiscoveryConfig(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user