feat: App API v2 (#10077)

# Which Problems Are Solved

This PR *partially* addresses #9450 . Specifically, it implements the
resource based API for the apps. APIs for app keys ARE not part of this
PR.

# How the Problems Are Solved

- `CreateApplication`, `PatchApplication` (update) and
`RegenerateClientSecret` endpoints are now unique for all app types:
API, SAML and OIDC apps.
  - All new endpoints have integration tests
  - All new endpoints are using permission checks V2

# Additional Changes

- The `ListApplications` endpoint allows to do sorting (see protobuf for
details) and filtering by app type (see protobuf).
- SAML and OIDC update endpoint can now receive requests for partial
updates

# Additional Context

Partially addresses #9450
This commit is contained in:
Marco A.
2025-06-27 17:25:44 +02:00
committed by GitHub
parent 016676e1dc
commit 2691dae2b6
48 changed files with 6845 additions and 603 deletions

View File

@@ -29,7 +29,7 @@ func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*m
if err != nil {
return nil, err
}
apps, err := s.query.SearchApps(ctx, queries, false)
apps, err := s.query.SearchApps(ctx, queries, nil)
if err != nil {
return nil, err
}
@@ -125,7 +125,7 @@ func (s *Server) AddAPIApp(ctx context.Context, req *mgmt_pb.AddAPIAppRequest) (
}
func (s *Server) UpdateApp(ctx context.Context, req *mgmt_pb.UpdateAppRequest) (*mgmt_pb.UpdateAppResponse, error) {
details, err := s.command.ChangeApplication(ctx, req.ProjectId, UpdateAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
details, err := s.command.UpdateApplicationName(ctx, req.ProjectId, UpdateAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
@@ -139,7 +139,7 @@ func (s *Server) UpdateOIDCAppConfig(ctx context.Context, req *mgmt_pb.UpdateOID
if err != nil {
return nil, err
}
config, err := s.command.ChangeOIDCApplication(ctx, oidcApp, authz.GetCtxData(ctx).OrgID)
config, err := s.command.UpdateOIDCApplication(ctx, oidcApp, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
@@ -157,7 +157,7 @@ func (s *Server) UpdateSAMLAppConfig(ctx context.Context, req *mgmt_pb.UpdateSAM
if err != nil {
return nil, err
}
config, err := s.command.ChangeSAMLApplication(ctx, samlApp, authz.GetCtxData(ctx).OrgID)
config, err := s.command.UpdateSAMLApplication(ctx, samlApp, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
@@ -171,7 +171,7 @@ func (s *Server) UpdateSAMLAppConfig(ctx context.Context, req *mgmt_pb.UpdateSAM
}
func (s *Server) UpdateAPIAppConfig(ctx context.Context, req *mgmt_pb.UpdateAPIAppConfigRequest) (*mgmt_pb.UpdateAPIAppConfigResponse, error) {
config, err := s.command.ChangeAPIApplication(ctx, UpdateAPIAppConfigRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
config, err := s.command.UpdateAPIApplication(ctx, UpdateAPIAppConfigRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}

View File

@@ -4,6 +4,8 @@ import (
"context"
"time"
"github.com/muhlemmer/gu"
"github.com/zitadel/zitadel/internal/api/authz"
authn_grpc "github.com/zitadel/zitadel/internal/api/grpc/authn"
"github.com/zitadel/zitadel/internal/api/grpc/object"
@@ -46,24 +48,24 @@ func AddOIDCAppRequestToDomain(req *mgmt_pb.AddOIDCAppRequest) (*domain.OIDCApp,
AggregateID: req.ProjectId,
},
AppName: req.Name,
OIDCVersion: app_grpc.OIDCVersionToDomain(req.Version),
OIDCVersion: gu.Ptr(app_grpc.OIDCVersionToDomain(req.Version)),
RedirectUris: req.RedirectUris,
ResponseTypes: app_grpc.OIDCResponseTypesToDomain(req.ResponseTypes),
GrantTypes: app_grpc.OIDCGrantTypesToDomain(req.GrantTypes),
ApplicationType: app_grpc.OIDCApplicationTypeToDomain(req.AppType),
AuthMethodType: app_grpc.OIDCAuthMethodTypeToDomain(req.AuthMethodType),
ApplicationType: gu.Ptr(app_grpc.OIDCApplicationTypeToDomain(req.AppType)),
AuthMethodType: gu.Ptr(app_grpc.OIDCAuthMethodTypeToDomain(req.AuthMethodType)),
PostLogoutRedirectUris: req.PostLogoutRedirectUris,
DevMode: req.DevMode,
AccessTokenType: app_grpc.OIDCTokenTypeToDomain(req.AccessTokenType),
AccessTokenRoleAssertion: req.AccessTokenRoleAssertion,
IDTokenRoleAssertion: req.IdTokenRoleAssertion,
IDTokenUserinfoAssertion: req.IdTokenUserinfoAssertion,
ClockSkew: req.ClockSkew.AsDuration(),
DevMode: gu.Ptr(req.GetDevMode()),
AccessTokenType: gu.Ptr(app_grpc.OIDCTokenTypeToDomain(req.AccessTokenType)),
AccessTokenRoleAssertion: gu.Ptr(req.GetAccessTokenRoleAssertion()),
IDTokenRoleAssertion: gu.Ptr(req.GetIdTokenRoleAssertion()),
IDTokenUserinfoAssertion: gu.Ptr(req.GetIdTokenUserinfoAssertion()),
ClockSkew: gu.Ptr(req.GetClockSkew().AsDuration()),
AdditionalOrigins: req.AdditionalOrigins,
SkipNativeAppSuccessPage: req.SkipNativeAppSuccessPage,
BackChannelLogoutURI: req.GetBackChannelLogoutUri(),
LoginVersion: loginVersion,
LoginBaseURI: loginBaseURI,
SkipNativeAppSuccessPage: gu.Ptr(req.GetSkipNativeAppSuccessPage()),
BackChannelLogoutURI: gu.Ptr(req.GetBackChannelLogoutUri()),
LoginVersion: gu.Ptr(loginVersion),
LoginBaseURI: gu.Ptr(loginBaseURI),
}, nil
}
@@ -78,9 +80,9 @@ func AddSAMLAppRequestToDomain(req *mgmt_pb.AddSAMLAppRequest) (*domain.SAMLApp,
},
AppName: req.Name,
Metadata: req.GetMetadataXml(),
MetadataURL: req.GetMetadataUrl(),
LoginVersion: loginVersion,
LoginBaseURI: loginBaseURI,
MetadataURL: gu.Ptr(req.GetMetadataUrl()),
LoginVersion: gu.Ptr(loginVersion),
LoginBaseURI: gu.Ptr(loginBaseURI),
}, nil
}
@@ -114,20 +116,20 @@ func UpdateOIDCAppConfigRequestToDomain(app *mgmt_pb.UpdateOIDCAppConfigRequest)
RedirectUris: app.RedirectUris,
ResponseTypes: app_grpc.OIDCResponseTypesToDomain(app.ResponseTypes),
GrantTypes: app_grpc.OIDCGrantTypesToDomain(app.GrantTypes),
ApplicationType: app_grpc.OIDCApplicationTypeToDomain(app.AppType),
AuthMethodType: app_grpc.OIDCAuthMethodTypeToDomain(app.AuthMethodType),
ApplicationType: gu.Ptr(app_grpc.OIDCApplicationTypeToDomain(app.AppType)),
AuthMethodType: gu.Ptr(app_grpc.OIDCAuthMethodTypeToDomain(app.AuthMethodType)),
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
DevMode: app.DevMode,
AccessTokenType: app_grpc.OIDCTokenTypeToDomain(app.AccessTokenType),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IDTokenRoleAssertion: app.IdTokenRoleAssertion,
IDTokenUserinfoAssertion: app.IdTokenUserinfoAssertion,
ClockSkew: app.ClockSkew.AsDuration(),
DevMode: gu.Ptr(app.GetDevMode()),
AccessTokenType: gu.Ptr(app_grpc.OIDCTokenTypeToDomain(app.AccessTokenType)),
AccessTokenRoleAssertion: gu.Ptr(app.GetAccessTokenRoleAssertion()),
IDTokenRoleAssertion: gu.Ptr(app.GetIdTokenRoleAssertion()),
IDTokenUserinfoAssertion: gu.Ptr(app.GetIdTokenUserinfoAssertion()),
ClockSkew: gu.Ptr(app.GetClockSkew().AsDuration()),
AdditionalOrigins: app.AdditionalOrigins,
SkipNativeAppSuccessPage: app.SkipNativeAppSuccessPage,
BackChannelLogoutURI: app.BackChannelLogoutUri,
LoginVersion: loginVersion,
LoginBaseURI: loginBaseURI,
SkipNativeAppSuccessPage: gu.Ptr(app.GetSkipNativeAppSuccessPage()),
BackChannelLogoutURI: gu.Ptr(app.GetBackChannelLogoutUri()),
LoginVersion: gu.Ptr(loginVersion),
LoginBaseURI: gu.Ptr(loginBaseURI),
}, nil
}
@@ -142,9 +144,9 @@ func UpdateSAMLAppConfigRequestToDomain(app *mgmt_pb.UpdateSAMLAppConfigRequest)
},
AppID: app.AppId,
Metadata: app.GetMetadataXml(),
MetadataURL: app.GetMetadataUrl(),
LoginVersion: loginVersion,
LoginBaseURI: loginBaseURI,
MetadataURL: gu.Ptr(app.GetMetadataUrl()),
LoginVersion: gu.Ptr(loginVersion),
LoginBaseURI: gu.Ptr(loginBaseURI),
}, nil
}