diff --git a/cmd/zitadel/caos_local.sh b/cmd/zitadel/caos_local.sh index 62788aa7d2..6ecc0814af 100755 --- a/cmd/zitadel/caos_local.sh +++ b/cmd/zitadel/caos_local.sh @@ -42,8 +42,8 @@ export CHAT_URL=$(gopass zitadel-secrets/zitadel/dev/google-chat-url) #OIDC export ZITADEL_ISSUER=http://localhost:50002/oauth/v2/ export ZITADEL_ACCOUNTS=http://localhost:50003/login -export ZITADEL_AUTHORIZE=http://localhost:50002/oauth/v2/ -export ZITADEL_OAUTH=http://localhost:50002/oauth/v2/ +export ZITADEL_AUTHORIZE=http://localhost:50002/oauth/v2 +export ZITADEL_OAUTH=http://localhost:50002/oauth/v2 export ZITADEL_CONSOLE=http://localhost:4200 export CAOS_OIDC_DEV=true export ZITADEL_COOKIE_DOMAIN=localhost diff --git a/cmd/zitadel/main.go b/cmd/zitadel/main.go index 4c124e6663..1f8816804b 100644 --- a/cmd/zitadel/main.go +++ b/cmd/zitadel/main.go @@ -121,7 +121,7 @@ func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsReposit } if *oidcEnabled { op := oidc.NewProvider(ctx, conf.API.OIDC, authRepo) - apis.RegisterHandler("/oauth/v2", op.HttpHandler().Handler) + apis.RegisterHandler("/oauth/v2", op.HttpHandler()) } apis.Start(ctx) } diff --git a/go.mod b/go.mod index 742b9752be..99df7808ee 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/aws/aws-sdk-go v1.33.1 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc github.com/caos/logging v0.0.2 - github.com/caos/oidc v0.6.2 + github.com/caos/oidc v0.6.4 github.com/cockroachdb/cockroach-go/v2 v2.0.0 github.com/envoyproxy/protoc-gen-validate v0.4.0 github.com/ghodss/yaml v1.0.0 diff --git a/go.sum b/go.sum index c925974f95..2d2d6cc5e3 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo= github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= -github.com/caos/oidc v0.6.2 h1:ejp6uTepVSlgLoPhXIAqFe8SbCdoxqO4vZv1H4fF0Yk= -github.com/caos/oidc v0.6.2/go.mod h1:ozoi3b+aY33gzdvjz4w90VZShIHGsmDa0goruuV0arQ= +github.com/caos/oidc v0.6.4 h1:BrtKcK004kkJqTBLP73tZat3SXozYMxqZrQ7mDpx+nY= +github.com/caos/oidc v0.6.4/go.mod h1:f3bYdAHhN9WS3VxYgy5c9wgsiJ3qNrek1r7ktgHriDs= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/internal/api/oidc/auth_request.go b/internal/api/oidc/auth_request.go index 0de08181ea..f9437a7b8f 100644 --- a/internal/api/oidc/auth_request.go +++ b/internal/api/oidc/auth_request.go @@ -2,6 +2,7 @@ package oidc import ( "context" + "fmt" "time" "github.com/caos/oidc/pkg/oidc" @@ -10,6 +11,7 @@ import ( "github.com/caos/zitadel/internal/auth_request/model" "github.com/caos/zitadel/internal/errors" + grant_model "github.com/caos/zitadel/internal/usergrant/model" ) func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, userID string) (op.AuthRequest, error) { @@ -54,13 +56,29 @@ func (o *OPStorage) CreateToken(ctx context.Context, authReq op.AuthRequest) (st if err != nil { return "", time.Time{}, err } - resp, err := o.repo.CreateToken(ctx, req.AgentID, req.ApplicationID, req.UserID, req.Audience, req.Request.(*model.AuthRequestOIDC).Scopes, o.defaultAccessTokenLifetime) //PLANNED: lifetime from client + app, err := o.repo.ApplicationByClientID(ctx, req.ApplicationID) + if err != nil { + return "", time.Time{}, err + } + grants, err := o.repo.UserGrantsByProjectAndUserID(app.ProjectID, req.UserID) + scopes := append(req.Request.(*model.AuthRequestOIDC).Scopes, grantsToScopes(grants)...) + resp, err := o.repo.CreateToken(ctx, req.AgentID, req.ApplicationID, req.UserID, req.Audience, scopes, o.defaultAccessTokenLifetime) //PLANNED: lifetime from client if err != nil { return "", time.Time{}, err } return resp.ID, resp.Expiration, nil } +func grantsToScopes(grants []*grant_model.UserGrantView) []string { + scopes := make([]string, 0) + for _, grant := range grants { + for _, role := range grant.RoleKeys { + scopes = append(scopes, fmt.Sprintf("%v:%v", grant.ResourceOwner, role)) + } + } + return scopes +} + func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID string) error { userAgentID, ok := UserAgentIDFromCtx(ctx) if !ok { diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index 5726e86724..afbcb96202 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -79,6 +79,8 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc userInfo.Address.Region = user.Region userInfo.Address.PostalCode = user.PostalCode userInfo.Address.Country = user.Country + default: + userInfo.Authorizations = append(userInfo.Authorizations, scope) } } return userInfo, nil diff --git a/internal/auth/repository/eventsourcing/eventstore/user_grant.go b/internal/auth/repository/eventsourcing/eventstore/user_grant.go index bbb0192d2a..d711e881e1 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/auth/repository/eventsourcing/eventstore/user_grant.go @@ -129,6 +129,14 @@ func (repo *UserGrantRepo) IsIamAdmin(ctx context.Context) (bool, error) { return true, nil } +func (repo *UserGrantRepo) UserGrantsByProjectAndUserID(projectID, userID string) ([]*grant_model.UserGrantView, error) { + grants, err := repo.View.UserGrantsByProjectAndUserID(projectID, userID) + if err != nil { + return nil, err + } + return model.UserGrantsToModel(grants), nil +} + func grantRespToOrgResp(grants *grant_model.UserGrantSearchResponse) *grant_model.ProjectOrgSearchResponse { resp := &grant_model.ProjectOrgSearchResponse{ TotalResult: grants.TotalResult, diff --git a/internal/auth/repository/eventsourcing/view/user_grant.go b/internal/auth/repository/eventsourcing/view/user_grant.go index a2679d779b..081546e576 100644 --- a/internal/auth/repository/eventsourcing/view/user_grant.go +++ b/internal/auth/repository/eventsourcing/view/user_grant.go @@ -27,6 +27,10 @@ func (v *View) UserGrantsByProjectID(projectID string) ([]*model.UserGrantView, return view.UserGrantsByProjectID(v.Db, userGrantTable, projectID) } +func (v *View) UserGrantsByProjectAndUserID(projectID, userID string) ([]*model.UserGrantView, error) { + return view.UserGrantsByProjectAndUserID(v.Db, userGrantTable, projectID, userID) +} + func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([]*model.UserGrantView, int, error) { return view.SearchUserGrants(v.Db, userGrantTable, request) } diff --git a/internal/auth/repository/user_grant.go b/internal/auth/repository/user_grant.go index aeb09ed950..e7a9409cb9 100644 --- a/internal/auth/repository/user_grant.go +++ b/internal/auth/repository/user_grant.go @@ -10,4 +10,5 @@ type UserGrantRepository interface { SearchMyProjectOrgs(ctx context.Context, request *model.UserGrantSearchRequest) (*model.ProjectOrgSearchResponse, error) SearchMyZitadelPermissions(ctx context.Context) ([]string, error) SearchMyProjectPermissions(ctx context.Context) ([]string, error) + UserGrantsByProjectAndUserID(projectID, userID string) ([]*model.UserGrantView, error) } diff --git a/internal/usergrant/repository/view/user_grant_view.go b/internal/usergrant/repository/view/user_grant_view.go index b975f4ebc6..172650caab 100644 --- a/internal/usergrant/repository/view/user_grant_view.go +++ b/internal/usergrant/repository/view/user_grant_view.go @@ -69,6 +69,20 @@ func UserGrantsByProjectID(db *gorm.DB, table, projectID string) ([]*model.UserG return users, nil } +func UserGrantsByProjectAndUserID(db *gorm.DB, table, projectID, userID string) ([]*model.UserGrantView, error) { + users := make([]*model.UserGrantView, 0) + queries := []*grant_model.UserGrantSearchQuery{ + &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyProjectID, Value: projectID, Method: global_model.SearchMethodEquals}, + &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyUserID, Value: userID, Method: global_model.SearchMethodEquals}, + } + query := repository.PrepareSearchQuery(table, model.UserGrantSearchRequest{Queries: queries}) + _, err := query(db, &users) + if err != nil { + return nil, err + } + return users, nil +} + func UserGrantsByProjectIDAndRole(db *gorm.DB, table, projectID, roleKey string) ([]*model.UserGrantView, error) { users := make([]*model.UserGrantView, 0) queries := []*grant_model.UserGrantSearchQuery{