feat: allow glob redirects (#7091)

fixes #5110
This commit is contained in:
Yordis Prieto 2023-12-28 04:25:18 -05:00 committed by GitHub
parent 3483ec470d
commit 9d5d1cf3ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 12 deletions

View File

@ -52,7 +52,7 @@ func TestMain(m *testing.M) {
func TestServer_GetAuthRequest(t *testing.T) { func TestServer_GetAuthRequest(t *testing.T) {
project, err := Tester.CreateProject(CTX) project, err := Tester.CreateProject(CTX)
require.NoError(t, err) require.NoError(t, err)
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
require.NoError(t, err) require.NoError(t, err)
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI) authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
require.NoError(t, err) require.NoError(t, err)
@ -96,7 +96,7 @@ func TestServer_GetAuthRequest(t *testing.T) {
func TestServer_CreateCallback(t *testing.T) { func TestServer_CreateCallback(t *testing.T) {
project, err := Tester.CreateProject(CTX) project, err := Tester.CreateProject(CTX)
require.NoError(t, err) require.NoError(t, err)
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
require.NoError(t, err) require.NoError(t, err)
sessionResp, err := Tester.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{ sessionResp, err := Tester.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{
Checks: &session.Checks{ Checks: &session.Checks{

View File

@ -136,6 +136,20 @@ func (c *Client) IDTokenUserinfoClaimsAssertion() bool {
return c.client.IDTokenUserinfoAssertion return c.client.IDTokenUserinfoAssertion
} }
func (c *Client) RedirectURIGlobs() []string {
if c.DevMode() {
return c.RedirectURIs()
}
return nil
}
func (c *Client) PostLogoutRedirectURIGlobs() []string {
if c.DevMode() {
return c.PostLogoutRedirectURIs()
}
return nil
}
func accessTokenTypeToOIDC(tokenType domain.OIDCTokenType) op.AccessTokenType { func accessTokenTypeToOIDC(tokenType domain.OIDCTokenType) op.AccessTokenType {
switch tokenType { switch tokenType {
case domain.OIDCTokenTypeBearer: case domain.OIDCTokenTypeBearer:

View File

@ -59,7 +59,7 @@ func TestOPStorage_SetUserinfoFromToken(t *testing.T) {
func TestServer_Introspect(t *testing.T) { func TestServer_Introspect(t *testing.T) {
project, err := Tester.CreateProject(CTX) project, err := Tester.CreateProject(CTX)
require.NoError(t, err) require.NoError(t, err)
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
require.NoError(t, err) require.NoError(t, err)
api, err := Tester.CreateAPIClient(CTX, project.GetId()) api, err := Tester.CreateAPIClient(CTX, project.GetId())
require.NoError(t, err) require.NoError(t, err)
@ -158,7 +158,7 @@ func TestServer_VerifyClient(t *testing.T) {
inactiveClient, err := Tester.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) inactiveClient, err := Tester.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
require.NoError(t, err) require.NoError(t, err)
nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
require.NoError(t, err) require.NoError(t, err)
basicWebClient, err := Tester.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId()) basicWebClient, err := Tester.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId())
require.NoError(t, err) require.NoError(t, err)

View File

@ -174,6 +174,40 @@ func Test_ZITADEL_API_success(t *testing.T) {
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId()) 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{
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: authRequestID,
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
Session: &oidc_pb.Session{
SessionId: sessionID,
SessionToken: sessionToken,
},
},
})
require.NoError(t, err)
// code exchange
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
tokens, err := exchangeTokens(t, clientID, code)
require.NoError(t, err)
assertTokens(t, tokens, false)
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
myUserResp, err := Tester.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) { func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
clientID := createClient(t) clientID := createClient(t)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope) authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
@ -257,9 +291,23 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) {
} }
func createClient(t testing.TB) string { func createClient(t testing.TB) string {
return createClientWithOpts(t, clientOpts{
redirectURI: redirectURI,
logoutURI: logoutRedirectURI,
devMode: false,
})
}
type clientOpts struct {
redirectURI string
logoutURI string
devMode bool
}
func createClientWithOpts(t testing.TB, opts clientOpts) string {
project, err := Tester.CreateProject(CTX) project, err := Tester.CreateProject(CTX)
require.NoError(t, err) require.NoError(t, err)
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId()) app, err := Tester.CreateOIDCNativeClient(CTX, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode)
require.NoError(t, err) require.NoError(t, err)
return app.GetClientId() return app.GetClientId()
} }

View File

@ -23,7 +23,7 @@ import (
"github.com/zitadel/zitadel/pkg/grpc/user" "github.com/zitadel/zitadel/pkg/grpc/user"
) )
func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType) (*management.AddOIDCAppResponse, error) { func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType, devMode bool) (*management.AddOIDCAppResponse, error) {
return s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{ return s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{
ProjectId: projectID, ProjectId: projectID,
Name: fmt.Sprintf("app-%d", time.Now().UnixNano()), Name: fmt.Sprintf("app-%d", time.Now().UnixNano()),
@ -34,7 +34,7 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire
AuthMethodType: authMethod, AuthMethodType: authMethod,
PostLogoutRedirectUris: []string{logoutRedirectURI}, PostLogoutRedirectUris: []string{logoutRedirectURI},
Version: app.OIDCVersion_OIDC_VERSION_1_0, Version: app.OIDCVersion_OIDC_VERSION_1_0,
DevMode: false, DevMode: devMode,
AccessTokenType: app.OIDCTokenType_OIDC_TOKEN_TYPE_JWT, AccessTokenType: app.OIDCTokenType_OIDC_TOKEN_TYPE_JWT,
AccessTokenRoleAssertion: false, AccessTokenRoleAssertion: false,
IdTokenRoleAssertion: false, IdTokenRoleAssertion: false,
@ -45,16 +45,16 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire
}) })
} }
func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, devMode bool) (*management.AddOIDCAppResponse, error) {
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE) return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE, devMode)
} }
func (s *Tester) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { func (s *Tester) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC) return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC, false)
} }
func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (client *management.AddOIDCAppResponse, keyData []byte, err error) { func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (client *management.AddOIDCAppResponse, keyData []byte, err error) {
client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT) client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT, false)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -71,7 +71,7 @@ func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logout
} }
func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) { func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID) client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }