mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 03:57:32 +00:00
fix(app): move queries to query package (#2612)
* fix: move queries to query package * fix(auth): switch project role requests to query pkg * refactor: delete unused project role code * remove repo * implement sql queries * fix(database): oidc config change type to int2 * fix(queries): implement app queries * refactor: simplify code * fix: correct app query * Update app.go * fix token check * fix mock * test: app prepares * test: oidc compliance * test: OIDCOriginAllowList * fix: converter * resolve unsupported oidc version Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -47,7 +47,7 @@ type API struct {
|
||||
type health interface {
|
||||
Health(ctx context.Context) error
|
||||
IamByID(ctx context.Context) (*iam_model.IAM, error)
|
||||
VerifierClientID(ctx context.Context, appName string) (string, error)
|
||||
VerifierClientID(ctx context.Context, appName string) (string, string, error)
|
||||
}
|
||||
|
||||
type auth interface {
|
||||
@@ -159,7 +159,7 @@ func handleValidate(checks []ValidationFunction) func(w http.ResponseWriter, r *
|
||||
}
|
||||
|
||||
func (a *API) handleClientID(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := a.health.VerifierClientID(r.Context(), "Zitadel Console")
|
||||
id, _, err := a.health.VerifierClientID(r.Context(), "Zitadel Console")
|
||||
if err != nil {
|
||||
http_util.MarshalJSON(w, nil, err, http.StatusPreconditionFailed)
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@ type testVerifier struct {
|
||||
memberships []*Membership
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, string, string, error) {
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID, projectID string) (string, string, string, string, string, error) {
|
||||
return "userID", "agentID", "clientID", "de", "orgID", nil
|
||||
}
|
||||
func (v *testVerifier) SearchMyMemberships(ctx context.Context) ([]*Membership, error) {
|
||||
@@ -30,8 +30,8 @@ func (v *testVerifier) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifierClientID(ctx context.Context, appName string) (string, error) {
|
||||
return "clientID", nil
|
||||
func (v *testVerifier) VerifierClientID(ctx context.Context, appName string) (string, string, error) {
|
||||
return "clientID", "projectID", nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) CheckOrgFeatures(context.Context, string, ...string) error {
|
||||
|
@@ -20,8 +20,8 @@ type TokenVerifier struct {
|
||||
}
|
||||
|
||||
type authZRepo interface {
|
||||
VerifyAccessToken(ctx context.Context, token, verifierClientID string) (userID, agentID, clientID, prefLang, resourceOwner string, err error)
|
||||
VerifierClientID(ctx context.Context, name string) (clientID string, err error)
|
||||
VerifyAccessToken(ctx context.Context, token, verifierClientID, projectID string) (userID, agentID, clientID, prefLang, resourceOwner string, err error)
|
||||
VerifierClientID(ctx context.Context, name string) (clientID, projectID string, err error)
|
||||
SearchMyMemberships(ctx context.Context) ([]*Membership, error)
|
||||
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
||||
ExistsOrg(ctx context.Context, orgID string) error
|
||||
@@ -33,17 +33,18 @@ func Start(authZRepo authZRepo) (v *TokenVerifier) {
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID, prefLang, resourceOwner string, err error) {
|
||||
verifierClientID, err := v.clientIDFromMethod(ctx, method)
|
||||
verifierClientID, projectID, err := v.clientIDAndProjectIDFromMethod(ctx, method)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", err
|
||||
}
|
||||
userID, agentID, clientID, prefLang, resourceOwner, err = v.authZRepo.VerifyAccessToken(ctx, token, verifierClientID)
|
||||
userID, agentID, clientID, prefLang, resourceOwner, err = v.authZRepo.VerifyAccessToken(ctx, token, verifierClientID, projectID)
|
||||
return userID, clientID, agentID, prefLang, resourceOwner, err
|
||||
}
|
||||
|
||||
type client struct {
|
||||
id string
|
||||
name string
|
||||
id string
|
||||
projectID string
|
||||
name string
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) RegisterServer(appName, methodPrefix string, mappings MethodMapping) {
|
||||
@@ -64,28 +65,28 @@ func prefixFromMethod(method string) (string, bool) {
|
||||
return parts[1], true
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (_ string, err error) {
|
||||
func (v *TokenVerifier) clientIDAndProjectIDFromMethod(ctx context.Context, method string) (clientID, projectID string, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
prefix, ok := prefixFromMethod(method)
|
||||
if !ok {
|
||||
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-GRD2Q", "Errors.Internal")
|
||||
return "", "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-GRD2Q", "Errors.Internal")
|
||||
}
|
||||
app, ok := v.clients.Load(prefix)
|
||||
if !ok {
|
||||
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-G2qrh", "Errors.Internal")
|
||||
return "", "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-G2qrh", "Errors.Internal")
|
||||
}
|
||||
c := app.(*client)
|
||||
if c.id != "" {
|
||||
return c.id, nil
|
||||
return c.id, c.projectID, nil
|
||||
}
|
||||
c.id, err = v.authZRepo.VerifierClientID(ctx, c.name)
|
||||
c.id, c.projectID, err = v.authZRepo.VerifierClientID(ctx, c.name)
|
||||
if err != nil {
|
||||
return "", caos_errs.ThrowPermissionDenied(err, "AUTHZ-ptTIF2", "Errors.Internal")
|
||||
return "", "", caos_errs.ThrowPermissionDenied(err, "AUTHZ-ptTIF2", "Errors.Internal")
|
||||
}
|
||||
v.clients.Store(prefix, c)
|
||||
return c.id, nil
|
||||
return c.id, c.projectID, nil
|
||||
}
|
||||
func (v *TokenVerifier) SearchMyMemberships(ctx context.Context) (_ []*Membership, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) GetAppByID(ctx context.Context, req *mgmt_pb.GetAppByIDRequest) (*mgmt_pb.GetAppByIDResponse, error) {
|
||||
app, err := s.project.ApplicationByID(ctx, req.ProjectId, req.AppId)
|
||||
app, err := s.query.AppByProjectAndAppID(ctx, req.ProjectId, req.AppId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -26,16 +26,16 @@ func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*m
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domains, err := s.project.SearchApplications(ctx, queries)
|
||||
apps, err := s.query.SearchApps(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ListAppsResponse{
|
||||
Result: project_grpc.AppsToPb(domains.Result),
|
||||
Result: project_grpc.AppsToPb(apps.Apps),
|
||||
Details: object_grpc.ToListDetails(
|
||||
domains.TotalResult,
|
||||
domains.Sequence,
|
||||
domains.Timestamp,
|
||||
apps.Count,
|
||||
apps.Sequence,
|
||||
apps.Timestamp,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
@@ -196,16 +196,16 @@ func (s *Server) ListAppKeys(ctx context.Context, req *mgmt_pb.ListAppKeysReques
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domains, err := s.project.SearchClientKeys(ctx, queries)
|
||||
keys, err := s.project.SearchClientKeys(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.ListAppKeysResponse{
|
||||
Result: authn_grpc.KeyViewsToPb(domains.Result),
|
||||
Result: authn_grpc.KeyViewsToPb(keys.Result),
|
||||
Details: object_grpc.ToListDetails(
|
||||
domains.TotalResult,
|
||||
domains.Sequence,
|
||||
domains.Timestamp,
|
||||
keys.TotalResult,
|
||||
keys.Sequence,
|
||||
keys.Timestamp,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
@@ -9,25 +9,27 @@ import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
key_model "github.com/caos/zitadel/internal/key/model"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
func ListAppsRequestToModel(req *mgmt_pb.ListAppsRequest) (*proj_model.ApplicationSearchRequest, error) {
|
||||
func ListAppsRequestToModel(req *mgmt_pb.ListAppsRequest) (*query.AppSearchQueries, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
queries, err := app_grpc.AppQueriesToModel(req.Queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queries = append(queries, &proj_model.ApplicationSearchQuery{
|
||||
Key: proj_model.AppSearchKeyProjectID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: req.ProjectId,
|
||||
})
|
||||
return &proj_model.ApplicationSearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
projectQuery, err := query.NewAppProjectIDSearchQuery(req.ProjectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queries = append(queries, projectQuery)
|
||||
return &query.AppSearchQueries{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
//SortingColumn: //TODO: sorting
|
||||
Queries: queries,
|
||||
}, nil
|
||||
|
@@ -7,11 +7,12 @@ import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
app_pb "github.com/caos/zitadel/pkg/grpc/app"
|
||||
message_pb "github.com/caos/zitadel/pkg/grpc/message"
|
||||
)
|
||||
|
||||
func AppsToPb(apps []*proj_model.ApplicationView) []*app_pb.App {
|
||||
func AppsToPb(apps []*query.App) []*app_pb.App {
|
||||
a := make([]*app_pb.App, len(apps))
|
||||
for i, app := range apps {
|
||||
a[i] = AppToPb(app)
|
||||
@@ -19,7 +20,7 @@ func AppsToPb(apps []*proj_model.ApplicationView) []*app_pb.App {
|
||||
return a
|
||||
}
|
||||
|
||||
func AppToPb(app *proj_model.ApplicationView) *app_pb.App {
|
||||
func AppToPb(app *query.App) *app_pb.App {
|
||||
return &app_pb.App{
|
||||
Id: app.ID,
|
||||
Details: object_grpc.ToViewDetailsPb(app.Sequence, app.CreationDate, app.ChangeDate, app.ResourceOwner),
|
||||
@@ -29,68 +30,68 @@ func AppToPb(app *proj_model.ApplicationView) *app_pb.App {
|
||||
}
|
||||
}
|
||||
|
||||
func AppConfigToPb(app *proj_model.ApplicationView) app_pb.AppConfig {
|
||||
if app.IsOIDC {
|
||||
return AppOIDCConfigToPb(app)
|
||||
func AppConfigToPb(app *query.App) app_pb.AppConfig {
|
||||
if app.OIDCConfig != nil {
|
||||
return AppOIDCConfigToPb(app.OIDCConfig)
|
||||
}
|
||||
return AppAPIConfigToPb(app)
|
||||
return AppAPIConfigToPb(app.APIConfig)
|
||||
}
|
||||
|
||||
func AppOIDCConfigToPb(app *proj_model.ApplicationView) *app_pb.App_OidcConfig {
|
||||
func AppOIDCConfigToPb(app *query.OIDCApp) *app_pb.App_OidcConfig {
|
||||
return &app_pb.App_OidcConfig{
|
||||
OidcConfig: &app_pb.OIDCConfig{
|
||||
RedirectUris: app.OIDCRedirectUris,
|
||||
ResponseTypes: OIDCResponseTypesFromModel(app.OIDCResponseTypes),
|
||||
GrantTypes: OIDCGrantTypesFromModel(app.OIDCGrantTypes),
|
||||
AppType: OIDCApplicationTypeToPb(domain.OIDCApplicationType(app.OIDCApplicationType)),
|
||||
ClientId: app.OIDCClientID,
|
||||
AuthMethodType: OIDCAuthMethodTypeToPb(domain.OIDCAuthMethodType(app.OIDCAuthMethodType)),
|
||||
PostLogoutRedirectUris: app.OIDCPostLogoutRedirectUris,
|
||||
Version: OIDCVersionToPb(domain.OIDCVersion(app.OIDCVersion)),
|
||||
NoneCompliant: app.NoneCompliant,
|
||||
RedirectUris: app.RedirectURIs,
|
||||
ResponseTypes: OIDCResponseTypesFromModel(app.ResponseTypes),
|
||||
GrantTypes: OIDCGrantTypesFromModel(app.GrantTypes),
|
||||
AppType: OIDCApplicationTypeToPb(app.AppType),
|
||||
ClientId: app.ClientID,
|
||||
AuthMethodType: OIDCAuthMethodTypeToPb(app.AuthMethodType),
|
||||
PostLogoutRedirectUris: app.PostLogoutRedirectURIs,
|
||||
Version: OIDCVersionToPb(domain.OIDCVersion(app.Version)),
|
||||
NoneCompliant: len(app.ComplianceProblems) != 0,
|
||||
ComplianceProblems: ComplianceProblemsToLocalizedMessages(app.ComplianceProblems),
|
||||
DevMode: app.DevMode,
|
||||
AccessTokenType: oidcTokenTypeToPb(domain.OIDCTokenType(app.AccessTokenType)),
|
||||
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
|
||||
IdTokenRoleAssertion: app.IDTokenRoleAssertion,
|
||||
IdTokenUserinfoAssertion: app.IDTokenUserinfoAssertion,
|
||||
DevMode: app.IsDevMode,
|
||||
AccessTokenType: oidcTokenTypeToPb(app.AccessTokenType),
|
||||
AccessTokenRoleAssertion: app.AssertAccessTokenRole,
|
||||
IdTokenRoleAssertion: app.AssertIDTokenRole,
|
||||
IdTokenUserinfoAssertion: app.AssertIDTokenUserinfo,
|
||||
ClockSkew: durationpb.New(app.ClockSkew),
|
||||
AdditionalOrigins: app.AdditionalOrigins,
|
||||
AllowedOrigins: app.OriginAllowList,
|
||||
AllowedOrigins: app.AllowedOrigins,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AppAPIConfigToPb(app *proj_model.ApplicationView) app_pb.AppConfig {
|
||||
func AppAPIConfigToPb(app *query.APIApp) app_pb.AppConfig {
|
||||
return &app_pb.App_ApiConfig{
|
||||
ApiConfig: &app_pb.APIConfig{
|
||||
ClientId: app.OIDCClientID,
|
||||
ClientId: app.ClientID,
|
||||
ClientSecret: "", //TODO: remove from proto
|
||||
AuthMethodType: APIAuthMethodeTypeToPb(domain.APIAuthMethodType(app.OIDCAuthMethodType)),
|
||||
AuthMethodType: APIAuthMethodeTypeToPb(app.AuthMethodType),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AppStateToPb(state proj_model.AppState) app_pb.AppState {
|
||||
func AppStateToPb(state domain.AppState) app_pb.AppState {
|
||||
switch state {
|
||||
case proj_model.AppStateActive:
|
||||
case domain.AppStateActive:
|
||||
return app_pb.AppState_APP_STATE_ACTIVE
|
||||
case proj_model.AppStateInactive:
|
||||
case domain.AppStateInactive:
|
||||
return app_pb.AppState_APP_STATE_INACTIVE
|
||||
default:
|
||||
return app_pb.AppState_APP_STATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func OIDCResponseTypesFromModel(responseTypes []proj_model.OIDCResponseType) []app_pb.OIDCResponseType {
|
||||
func OIDCResponseTypesFromModel(responseTypes []domain.OIDCResponseType) []app_pb.OIDCResponseType {
|
||||
oidcResponseTypes := make([]app_pb.OIDCResponseType, len(responseTypes))
|
||||
for i, responseType := range responseTypes {
|
||||
switch responseType {
|
||||
case proj_model.OIDCResponseTypeCode:
|
||||
case domain.OIDCResponseTypeCode:
|
||||
oidcResponseTypes[i] = app_pb.OIDCResponseType_OIDC_RESPONSE_TYPE_CODE
|
||||
case proj_model.OIDCResponseTypeIDToken:
|
||||
case domain.OIDCResponseTypeIDToken:
|
||||
oidcResponseTypes[i] = app_pb.OIDCResponseType_OIDC_RESPONSE_TYPE_ID_TOKEN
|
||||
case proj_model.OIDCResponseTypeIDTokenToken:
|
||||
case domain.OIDCResponseTypeIDTokenToken:
|
||||
oidcResponseTypes[i] = app_pb.OIDCResponseType_OIDC_RESPONSE_TYPE_ID_TOKEN_TOKEN
|
||||
}
|
||||
}
|
||||
@@ -98,7 +99,7 @@ func OIDCResponseTypesFromModel(responseTypes []proj_model.OIDCResponseType) []a
|
||||
}
|
||||
|
||||
func OIDCResponseTypesToDomain(responseTypes []app_pb.OIDCResponseType) []domain.OIDCResponseType {
|
||||
if responseTypes == nil || len(responseTypes) == 0 {
|
||||
if len(responseTypes) == 0 {
|
||||
return []domain.OIDCResponseType{domain.OIDCResponseTypeCode}
|
||||
}
|
||||
oidcResponseTypes := make([]domain.OIDCResponseType, len(responseTypes))
|
||||
@@ -115,15 +116,15 @@ func OIDCResponseTypesToDomain(responseTypes []app_pb.OIDCResponseType) []domain
|
||||
return oidcResponseTypes
|
||||
}
|
||||
|
||||
func OIDCGrantTypesFromModel(grantTypes []proj_model.OIDCGrantType) []app_pb.OIDCGrantType {
|
||||
func OIDCGrantTypesFromModel(grantTypes []domain.OIDCGrantType) []app_pb.OIDCGrantType {
|
||||
oidcGrantTypes := make([]app_pb.OIDCGrantType, len(grantTypes))
|
||||
for i, grantType := range grantTypes {
|
||||
switch grantType {
|
||||
case proj_model.OIDCGrantTypeAuthorizationCode:
|
||||
case domain.OIDCGrantTypeAuthorizationCode:
|
||||
oidcGrantTypes[i] = app_pb.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE
|
||||
case proj_model.OIDCGrantTypeImplicit:
|
||||
case domain.OIDCGrantTypeImplicit:
|
||||
oidcGrantTypes[i] = app_pb.OIDCGrantType_OIDC_GRANT_TYPE_IMPLICIT
|
||||
case proj_model.OIDCGrantTypeRefreshToken:
|
||||
case domain.OIDCGrantTypeRefreshToken:
|
||||
oidcGrantTypes[i] = app_pb.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN
|
||||
}
|
||||
}
|
||||
@@ -272,8 +273,8 @@ func APIAuthMethodTypeToDomain(authType app_pb.APIAuthMethodType) domain.APIAuth
|
||||
}
|
||||
}
|
||||
|
||||
func AppQueriesToModel(queries []*app_pb.AppQuery) (_ []*proj_model.ApplicationSearchQuery, err error) {
|
||||
q := make([]*proj_model.ApplicationSearchQuery, len(queries))
|
||||
func AppQueriesToModel(queries []*app_pb.AppQuery) (q []query.SearchQuery, err error) {
|
||||
q = make([]query.SearchQuery, len(queries))
|
||||
for i, query := range queries {
|
||||
q[i], err = AppQueryToModel(query)
|
||||
if err != nil {
|
||||
@@ -283,10 +284,10 @@ func AppQueriesToModel(queries []*app_pb.AppQuery) (_ []*proj_model.ApplicationS
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func AppQueryToModel(query *app_pb.AppQuery) (*proj_model.ApplicationSearchQuery, error) {
|
||||
switch q := query.Query.(type) {
|
||||
func AppQueryToModel(appQuery *app_pb.AppQuery) (query.SearchQuery, error) {
|
||||
switch q := appQuery.Query.(type) {
|
||||
case *app_pb.AppQuery_NameQuery:
|
||||
return AppQueryNameToModel(q.NameQuery), nil
|
||||
return query.NewAppNameSearchQuery(object_grpc.TextMethodToQuery(q.NameQuery.Method), q.NameQuery.Name)
|
||||
default:
|
||||
return nil, errors.ThrowInvalidArgument(nil, "APP-Add46", "List.Query.Invalid")
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ var (
|
||||
|
||||
type verifierMock struct{}
|
||||
|
||||
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, string, string, error) {
|
||||
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID, projectID string) (string, string, string, string, string, error) {
|
||||
return "", "", "", "", "", nil
|
||||
}
|
||||
func (v *verifierMock) SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) {
|
||||
@@ -34,8 +34,8 @@ func (v *verifierMock) ProjectIDAndOriginsByClientID(ctx context.Context, client
|
||||
func (v *verifierMock) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
return nil
|
||||
}
|
||||
func (v *verifierMock) VerifierClientID(ctx context.Context, appName string) (string, error) {
|
||||
return "", nil
|
||||
func (v *verifierMock) VerifierClientID(ctx context.Context, appName string) (string, string, error) {
|
||||
return "", "", nil
|
||||
}
|
||||
func (v *verifierMock) CheckOrgFeatures(context.Context, string, ...string) error {
|
||||
return nil
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/api/http/middleware"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
grant_model "github.com/caos/zitadel/internal/usergrant/model"
|
||||
@@ -26,15 +25,20 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest
|
||||
if !ok {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
|
||||
}
|
||||
app, err := o.repo.ApplicationByClientID(ctx, req.ClientID)
|
||||
projectID, err := o.query.ProjectIDFromOIDCClientID(ctx, req.ClientID)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-AEG4d", "Errors.Internal")
|
||||
}
|
||||
req.Scopes, err = o.assertProjectRoleScopes(app, req.Scopes)
|
||||
project, err := o.query.ProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-w4wIn", "Errors.Internal")
|
||||
}
|
||||
req.Scopes, err = o.assertProjectRoleScopes(project, req.Scopes)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-Gqrfg", "Errors.Internal")
|
||||
}
|
||||
authRequest := CreateAuthRequestToBusiness(ctx, req, userAgentID, userID)
|
||||
//TODO: ensure splitting of command and query side durring auth request and login refactoring
|
||||
resp, err := o.repo.CreateAuthRequest(ctx, authRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -205,8 +209,8 @@ func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err e
|
||||
return o.repo.GetKeySet(ctx)
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertProjectRoleScopes(app *proj_model.ApplicationView, scopes []string) ([]string, error) {
|
||||
if !app.ProjectRoleAssertion {
|
||||
func (o *OPStorage) assertProjectRoleScopes(project *query.Project, scopes []string) ([]string, error) {
|
||||
if !project.ProjectRoleAssertion {
|
||||
return scopes, nil
|
||||
}
|
||||
for _, scope := range scopes {
|
||||
@@ -214,7 +218,7 @@ func (o *OPStorage) assertProjectRoleScopes(app *proj_model.ApplicationView, sco
|
||||
return scopes, nil
|
||||
}
|
||||
}
|
||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(app.ProjectID)
|
||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(project.ID)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
||||
}
|
||||
|
@@ -12,11 +12,10 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/http"
|
||||
"github.com/caos/zitadel/internal/auth_request/model"
|
||||
authreq_model "github.com/caos/zitadel/internal/auth_request/model"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
user_model "github.com/caos/zitadel/internal/user/model"
|
||||
@@ -37,11 +36,11 @@ const (
|
||||
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Client, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
client, err := o.repo.ApplicationByClientID(ctx, id)
|
||||
client, err := o.query.AppByOIDCClientID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if client.State != proj_model.AppStateActive {
|
||||
if client.State != domain.AppStateActive {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sdaGg", "client is not active")
|
||||
}
|
||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(client.ProjectID)
|
||||
@@ -125,11 +124,11 @@ func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo oidc.User
|
||||
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
||||
}
|
||||
if token.ApplicationID != "" {
|
||||
app, err := o.repo.ApplicationByClientID(ctx, token.ApplicationID)
|
||||
app, err := o.query.AppByOIDCClientID(ctx, token.ApplicationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if origin != "" && !http.IsOriginAllowed(app.OriginAllowList, origin) {
|
||||
if origin != "" && !http.IsOriginAllowed(app.OIDCConfig.AllowedOrigins, origin) {
|
||||
return errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
|
||||
}
|
||||
}
|
||||
@@ -202,8 +201,8 @@ func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.Use
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
|
||||
}
|
||||
if strings.HasPrefix(scope, model.OrgDomainPrimaryScope) {
|
||||
userInfo.AppendClaims(model.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, model.OrgDomainPrimaryScope))
|
||||
if strings.HasPrefix(scope, authreq_model.OrgDomainPrimaryScope) {
|
||||
userInfo.AppendClaims(authreq_model.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, authreq_model.OrgDomainPrimaryScope))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,12 +224,12 @@ func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection
|
||||
if err != nil {
|
||||
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
||||
}
|
||||
app, err := o.repo.ApplicationByClientID(ctx, clientID)
|
||||
projectID, err := o.query.ProjectIDFromOIDCClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return errors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
|
||||
}
|
||||
for _, aud := range token.Audience {
|
||||
if aud == clientID || aud == app.ProjectID {
|
||||
if aud == clientID || aud == projectID {
|
||||
err := o.SetUserinfoFromScopes(ctx, introspection, token.UserID, clientID, token.Scopes)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -266,8 +265,8 @@ func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clie
|
||||
}
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
|
||||
} else if strings.HasPrefix(scope, model.OrgDomainPrimaryScope) {
|
||||
claims = appendClaim(claims, model.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, model.OrgDomainPrimaryScope))
|
||||
} else if strings.HasPrefix(scope, authreq_model.OrgDomainPrimaryScope) {
|
||||
claims = appendClaim(claims, authreq_model.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, authreq_model.OrgDomainPrimaryScope))
|
||||
}
|
||||
}
|
||||
if len(roles) == 0 || clientID == "" {
|
||||
@@ -284,11 +283,11 @@ func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clie
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID string, requestedRoles []string) (map[string]map[string]string, error) {
|
||||
app, err := o.repo.ApplicationByClientID(ctx, applicationID)
|
||||
projectID, err := o.query.ProjectIDFromOIDCClientID(ctx, applicationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grants, err := o.repo.UserGrantsByProjectAndUserID(app.ProjectID, userID)
|
||||
grants, err := o.repo.UserGrantsByProjectAndUserID(projectID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -8,24 +8,25 @@ import (
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
|
||||
authreq_model "github.com/caos/zitadel/internal/auth_request/model"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
*model.ApplicationView
|
||||
app *query.App
|
||||
defaultLoginURL string
|
||||
defaultAccessTokenLifetime time.Duration
|
||||
defaultIdTokenLifetime time.Duration
|
||||
allowedScopes []string
|
||||
}
|
||||
|
||||
func ClientFromBusiness(app *model.ApplicationView, defaultLoginURL string, defaultAccessTokenLifetime, defaultIdTokenLifetime time.Duration, allowedScopes []string) (op.Client, error) {
|
||||
if !app.IsOIDC {
|
||||
func ClientFromBusiness(app *query.App, defaultLoginURL string, defaultAccessTokenLifetime, defaultIdTokenLifetime time.Duration, allowedScopes []string) (op.Client, error) {
|
||||
if app.OIDCConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "OIDC-d5bhD", "client is not a proper oidc application")
|
||||
}
|
||||
return &Client{
|
||||
ApplicationView: app,
|
||||
app: app,
|
||||
defaultLoginURL: defaultLoginURL,
|
||||
defaultAccessTokenLifetime: defaultAccessTokenLifetime,
|
||||
defaultIdTokenLifetime: defaultIdTokenLifetime,
|
||||
@@ -34,15 +35,15 @@ func ClientFromBusiness(app *model.ApplicationView, defaultLoginURL string, defa
|
||||
}
|
||||
|
||||
func (c *Client) ApplicationType() op.ApplicationType {
|
||||
return op.ApplicationType(c.OIDCApplicationType)
|
||||
return op.ApplicationType(c.app.OIDCConfig.AppType)
|
||||
}
|
||||
|
||||
func (c *Client) AuthMethod() oidc.AuthMethod {
|
||||
return authMethodToOIDC(c.OIDCAuthMethodType)
|
||||
return authMethodToOIDC(c.app.OIDCConfig.AuthMethodType)
|
||||
}
|
||||
|
||||
func (c *Client) GetID() string {
|
||||
return c.OIDCClientID
|
||||
return c.app.OIDCConfig.ClientID
|
||||
}
|
||||
|
||||
func (c *Client) LoginURL(id string) string {
|
||||
@@ -50,28 +51,28 @@ func (c *Client) LoginURL(id string) string {
|
||||
}
|
||||
|
||||
func (c *Client) RedirectURIs() []string {
|
||||
return c.OIDCRedirectUris
|
||||
return c.app.OIDCConfig.RedirectURIs
|
||||
}
|
||||
|
||||
func (c *Client) PostLogoutRedirectURIs() []string {
|
||||
return c.OIDCPostLogoutRedirectUris
|
||||
return c.app.OIDCConfig.PostLogoutRedirectURIs
|
||||
}
|
||||
|
||||
func (c *Client) ResponseTypes() []oidc.ResponseType {
|
||||
return responseTypesToOIDC(c.OIDCResponseTypes)
|
||||
return responseTypesToOIDC(c.app.OIDCConfig.ResponseTypes)
|
||||
}
|
||||
|
||||
func (c *Client) GrantTypes() []oidc.GrantType {
|
||||
return grantTypesToOIDC(c.OIDCGrantTypes)
|
||||
return grantTypesToOIDC(c.app.OIDCConfig.GrantTypes)
|
||||
}
|
||||
|
||||
func (c *Client) DevMode() bool {
|
||||
return c.ApplicationView.DevMode
|
||||
return c.app.OIDCConfig.IsDevMode
|
||||
}
|
||||
|
||||
func (c *Client) RestrictAdditionalIdTokenScopes() func(scopes []string) []string {
|
||||
return func(scopes []string) []string {
|
||||
if c.IDTokenRoleAssertion {
|
||||
if c.app.OIDCConfig.AssertIDTokenRole {
|
||||
return scopes
|
||||
}
|
||||
return removeScopeWithPrefix(scopes, ScopeProjectRolePrefix)
|
||||
@@ -80,7 +81,7 @@ func (c *Client) RestrictAdditionalIdTokenScopes() func(scopes []string) []strin
|
||||
|
||||
func (c *Client) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string {
|
||||
return func(scopes []string) []string {
|
||||
if c.AccessTokenRoleAssertion {
|
||||
if c.app.OIDCConfig.AssertAccessTokenRole {
|
||||
return scopes
|
||||
}
|
||||
return removeScopeWithPrefix(scopes, ScopeProjectRolePrefix)
|
||||
@@ -96,7 +97,7 @@ func (c *Client) IDTokenLifetime() time.Duration {
|
||||
}
|
||||
|
||||
func (c *Client) AccessTokenType() op.AccessTokenType {
|
||||
return accessTokenTypeToOIDC(c.ApplicationView.AccessTokenType)
|
||||
return accessTokenTypeToOIDC(c.app.OIDCConfig.AccessTokenType)
|
||||
}
|
||||
|
||||
func (c *Client) IsScopeAllowed(scope string) bool {
|
||||
@@ -124,40 +125,40 @@ func (c *Client) IsScopeAllowed(scope string) bool {
|
||||
}
|
||||
|
||||
func (c *Client) ClockSkew() time.Duration {
|
||||
return c.ApplicationView.ClockSkew
|
||||
return c.app.OIDCConfig.ClockSkew
|
||||
}
|
||||
|
||||
func (c *Client) IDTokenUserinfoClaimsAssertion() bool {
|
||||
return c.ApplicationView.IDTokenUserinfoAssertion
|
||||
return c.app.OIDCConfig.AssertIDTokenUserinfo
|
||||
}
|
||||
|
||||
func accessTokenTypeToOIDC(tokenType model.OIDCTokenType) op.AccessTokenType {
|
||||
func accessTokenTypeToOIDC(tokenType domain.OIDCTokenType) op.AccessTokenType {
|
||||
switch tokenType {
|
||||
case model.OIDCTokenTypeBearer:
|
||||
case domain.OIDCTokenTypeBearer:
|
||||
return op.AccessTokenTypeBearer
|
||||
case model.OIDCTokenTypeJWT:
|
||||
case domain.OIDCTokenTypeJWT:
|
||||
return op.AccessTokenTypeJWT
|
||||
default:
|
||||
return op.AccessTokenTypeBearer
|
||||
}
|
||||
}
|
||||
|
||||
func authMethodToOIDC(authType model.OIDCAuthMethodType) oidc.AuthMethod {
|
||||
func authMethodToOIDC(authType domain.OIDCAuthMethodType) oidc.AuthMethod {
|
||||
switch authType {
|
||||
case model.OIDCAuthMethodTypeBasic:
|
||||
case domain.OIDCAuthMethodTypeBasic:
|
||||
return oidc.AuthMethodBasic
|
||||
case model.OIDCAuthMethodTypePost:
|
||||
case domain.OIDCAuthMethodTypePost:
|
||||
return oidc.AuthMethodPost
|
||||
case model.OIDCAuthMethodTypeNone:
|
||||
case domain.OIDCAuthMethodTypeNone:
|
||||
return oidc.AuthMethodNone
|
||||
case model.OIDCAuthMethodTypePrivateKeyJWT:
|
||||
case domain.OIDCAuthMethodTypePrivateKeyJWT:
|
||||
return oidc.AuthMethodPrivateKeyJWT
|
||||
default:
|
||||
return oidc.AuthMethodBasic
|
||||
}
|
||||
}
|
||||
|
||||
func responseTypesToOIDC(responseTypes []model.OIDCResponseType) []oidc.ResponseType {
|
||||
func responseTypesToOIDC(responseTypes []domain.OIDCResponseType) []oidc.ResponseType {
|
||||
oidcTypes := make([]oidc.ResponseType, len(responseTypes))
|
||||
for i, t := range responseTypes {
|
||||
oidcTypes[i] = responseTypeToOIDC(t)
|
||||
@@ -165,20 +166,20 @@ func responseTypesToOIDC(responseTypes []model.OIDCResponseType) []oidc.Response
|
||||
return oidcTypes
|
||||
}
|
||||
|
||||
func responseTypeToOIDC(responseType model.OIDCResponseType) oidc.ResponseType {
|
||||
func responseTypeToOIDC(responseType domain.OIDCResponseType) oidc.ResponseType {
|
||||
switch responseType {
|
||||
case model.OIDCResponseTypeCode:
|
||||
case domain.OIDCResponseTypeCode:
|
||||
return oidc.ResponseTypeCode
|
||||
case model.OIDCResponseTypeIDTokenToken:
|
||||
case domain.OIDCResponseTypeIDTokenToken:
|
||||
return oidc.ResponseTypeIDToken
|
||||
case model.OIDCResponseTypeIDToken:
|
||||
case domain.OIDCResponseTypeIDToken:
|
||||
return oidc.ResponseTypeIDTokenOnly
|
||||
default:
|
||||
return oidc.ResponseTypeCode
|
||||
}
|
||||
}
|
||||
|
||||
func grantTypesToOIDC(grantTypes []model.OIDCGrantType) []oidc.GrantType {
|
||||
func grantTypesToOIDC(grantTypes []domain.OIDCGrantType) []oidc.GrantType {
|
||||
oidcTypes := make([]oidc.GrantType, len(grantTypes))
|
||||
for i, t := range grantTypes {
|
||||
oidcTypes[i] = grantTypeToOIDC(t)
|
||||
@@ -186,13 +187,13 @@ func grantTypesToOIDC(grantTypes []model.OIDCGrantType) []oidc.GrantType {
|
||||
return oidcTypes
|
||||
}
|
||||
|
||||
func grantTypeToOIDC(grantType model.OIDCGrantType) oidc.GrantType {
|
||||
func grantTypeToOIDC(grantType domain.OIDCGrantType) oidc.GrantType {
|
||||
switch grantType {
|
||||
case model.OIDCGrantTypeAuthorizationCode:
|
||||
case domain.OIDCGrantTypeAuthorizationCode:
|
||||
return oidc.GrantTypeCode
|
||||
case model.OIDCGrantTypeImplicit:
|
||||
case domain.OIDCGrantTypeImplicit:
|
||||
return oidc.GrantTypeImplicit
|
||||
case model.OIDCGrantTypeRefreshToken:
|
||||
case domain.OIDCGrantTypeRefreshToken:
|
||||
return oidc.GrantTypeRefreshToken
|
||||
default:
|
||||
return oidc.GrantTypeCode
|
||||
|
Reference in New Issue
Block a user