mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 13:07:46 +00:00
feat: actions context information add clientID (#10339)
# Which Problems Are Solved There is no information contained in the context info sent to Actions v2. # How the Problems Are Solved Add application information to the context information sent to Actions v2, to give more information about the execution. # Additional Changes None # Additional Context Closes #9377
This commit is contained in:
@@ -605,7 +605,7 @@ func TestServer_ExecutionTargetPreUserinfo(t *testing.T) {
|
||||
{Key: "added", Value: "value"},
|
||||
},
|
||||
}
|
||||
return expectPreUserinfoExecution(ctx, t, instance, req, response)
|
||||
return expectPreUserinfoExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -630,7 +630,7 @@ func TestServer_ExecutionTargetPreUserinfo(t *testing.T) {
|
||||
"addedLog",
|
||||
},
|
||||
}
|
||||
return expectPreUserinfoExecution(ctx, t, instance, req, response)
|
||||
return expectPreUserinfoExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -655,7 +655,7 @@ func TestServer_ExecutionTargetPreUserinfo(t *testing.T) {
|
||||
{Key: "key", Value: []byte("value")},
|
||||
},
|
||||
}
|
||||
return expectPreUserinfoExecution(ctx, t, instance, req, response)
|
||||
return expectPreUserinfoExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -692,7 +692,7 @@ func TestServer_ExecutionTargetPreUserinfo(t *testing.T) {
|
||||
{Key: "added3", Value: "value3"},
|
||||
},
|
||||
}
|
||||
return expectPreUserinfoExecution(ctx, t, instance, req, response)
|
||||
return expectPreUserinfoExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -755,7 +755,7 @@ func TestServer_ExecutionTargetPreUserinfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func expectPreUserinfoExecution(ctx context.Context, t *testing.T, instance *integration.Instance, req *oidc_pb.CreateCallbackRequest, response *oidc_api.ContextInfoResponse) (string, func()) {
|
||||
func expectPreUserinfoExecution(ctx context.Context, t *testing.T, instance *integration.Instance, clientID string, req *oidc_pb.CreateCallbackRequest, response *oidc_api.ContextInfoResponse) (string, func()) {
|
||||
userEmail := gofakeit.Email()
|
||||
userPhone := "+41" + gofakeit.Phone()
|
||||
userResp := instance.CreateHumanUserVerified(ctx, instance.DefaultOrg.Id, userEmail, userPhone)
|
||||
@@ -767,7 +767,7 @@ func expectPreUserinfoExecution(ctx context.Context, t *testing.T, instance *int
|
||||
SessionToken: sessionResp.GetSessionToken(),
|
||||
},
|
||||
}
|
||||
expectedContextInfo := contextInfoForUserOIDC(instance, "function/preuserinfo", userResp, userEmail, userPhone)
|
||||
expectedContextInfo := contextInfoForUserOIDC(instance, "function/preuserinfo", clientID, userResp, userEmail, userPhone)
|
||||
|
||||
targetURL, closeF, _, _ := integration.TestServerCall(expectedContextInfo, 0, http.StatusOK, response)
|
||||
|
||||
@@ -845,7 +845,7 @@ func getAccessTokenClaims(ctx context.Context, t *testing.T, instance *integrati
|
||||
return claims
|
||||
}
|
||||
|
||||
func contextInfoForUserOIDC(instance *integration.Instance, function string, userResp *user.AddHumanUserResponse, email, phone string) *oidc_api.ContextInfo {
|
||||
func contextInfoForUserOIDC(instance *integration.Instance, function string, clientID string, userResp *user.AddHumanUserResponse, email, phone string) *oidc_api.ContextInfo {
|
||||
return &oidc_api.ContextInfo{
|
||||
Function: function,
|
||||
UserInfo: &oidc.UserInfo{
|
||||
@@ -878,6 +878,9 @@ func contextInfoForUserOIDC(instance *integration.Instance, function string, use
|
||||
},
|
||||
},
|
||||
UserMetadata: nil,
|
||||
Application: &oidc_api.ContextInfoApplication{
|
||||
ClientID: clientID,
|
||||
},
|
||||
Org: &query.UserInfoOrg{
|
||||
ID: instance.DefaultOrg.GetId(),
|
||||
Name: instance.DefaultOrg.GetName(),
|
||||
@@ -918,7 +921,7 @@ func TestServer_ExecutionTargetPreAccessToken(t *testing.T) {
|
||||
{Key: "added1", Value: "value"},
|
||||
},
|
||||
}
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, req, response)
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -943,7 +946,7 @@ func TestServer_ExecutionTargetPreAccessToken(t *testing.T) {
|
||||
"addedLog",
|
||||
},
|
||||
}
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, req, response)
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -968,7 +971,7 @@ func TestServer_ExecutionTargetPreAccessToken(t *testing.T) {
|
||||
{Key: "key", Value: []byte("value")},
|
||||
},
|
||||
}
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, req, response)
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -1005,7 +1008,7 @@ func TestServer_ExecutionTargetPreAccessToken(t *testing.T) {
|
||||
{Key: "added3", Value: "value3"},
|
||||
},
|
||||
}
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, req, response)
|
||||
return expectPreAccessTokenExecution(ctx, t, instance, client.GetClientId(), req, response)
|
||||
},
|
||||
req: &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: func() string {
|
||||
@@ -1060,7 +1063,7 @@ func TestServer_ExecutionTargetPreAccessToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func expectPreAccessTokenExecution(ctx context.Context, t *testing.T, instance *integration.Instance, req *oidc_pb.CreateCallbackRequest, response *oidc_api.ContextInfoResponse) (string, func()) {
|
||||
func expectPreAccessTokenExecution(ctx context.Context, t *testing.T, instance *integration.Instance, clientID string, req *oidc_pb.CreateCallbackRequest, response *oidc_api.ContextInfoResponse) (string, func()) {
|
||||
userEmail := gofakeit.Email()
|
||||
userPhone := "+41" + gofakeit.Phone()
|
||||
userResp := instance.CreateHumanUserVerified(ctx, instance.DefaultOrg.Id, userEmail, userPhone)
|
||||
@@ -1072,7 +1075,7 @@ func expectPreAccessTokenExecution(ctx context.Context, t *testing.T, instance *
|
||||
SessionToken: sessionResp.GetSessionToken(),
|
||||
},
|
||||
}
|
||||
expectedContextInfo := contextInfoForUserOIDC(instance, "function/preaccesstoken", userResp, userEmail, userPhone)
|
||||
expectedContextInfo := contextInfoForUserOIDC(instance, "function/preaccesstoken", clientID, userResp, userEmail, userPhone)
|
||||
|
||||
targetURL, closeF, _, _ := integration.TestServerCall(expectedContextInfo, 0, http.StatusOK, response)
|
||||
|
||||
|
@@ -100,6 +100,7 @@ func (s *Server) Introspect(ctx context.Context, r *op.Request[op.IntrospectionR
|
||||
token.userID,
|
||||
token.scope,
|
||||
client.projectID,
|
||||
client.clientID,
|
||||
client.projectRoleAssertion,
|
||||
true,
|
||||
true,
|
||||
|
@@ -31,7 +31,7 @@ for example the v2 code exchange and refresh token.
|
||||
*/
|
||||
|
||||
func (s *Server) accessTokenResponseFromSession(ctx context.Context, client op.Client, session *command.OIDCSession, state, projectID string, projectRoleAssertion, accessTokenRoleAssertion, idTokenRoleAssertion, userInfoAssertion bool) (_ *oidc.AccessTokenResponse, err error) {
|
||||
getUserInfo := s.getUserInfo(session.UserID, projectID, projectRoleAssertion, userInfoAssertion, session.Scope)
|
||||
getUserInfo := s.getUserInfo(session.UserID, projectID, client.GetID(), projectRoleAssertion, userInfoAssertion, session.Scope)
|
||||
getSigner := s.getSignerOnce()
|
||||
|
||||
resp := &oidc.AccessTokenResponse{
|
||||
@@ -113,8 +113,8 @@ type userInfoFunc func(ctx context.Context, roleAssertion bool, triggerType doma
|
||||
|
||||
// getUserInfo returns a function which retrieves userinfo from the database once.
|
||||
// However, each time, role claims are asserted and also action flows will trigger.
|
||||
func (s *Server) getUserInfo(userID, projectID string, projectRoleAssertion, userInfoAssertion bool, scope []string) userInfoFunc {
|
||||
userInfo := s.userInfo(userID, scope, projectID, projectRoleAssertion, userInfoAssertion, false)
|
||||
func (s *Server) getUserInfo(userID, projectID, clientID string, projectRoleAssertion, userInfoAssertion bool, scope []string) userInfoFunc {
|
||||
userInfo := s.userInfo(userID, scope, projectID, clientID, projectRoleAssertion, userInfoAssertion, false)
|
||||
return func(ctx context.Context, roleAssertion bool, triggerType domain.TriggerType) (*oidc.UserInfo, error) {
|
||||
return userInfo(ctx, roleAssertion, triggerType)
|
||||
}
|
||||
|
@@ -218,7 +218,7 @@ func validateTokenExchangeAudience(requestedAudience, subjectAudience, actorAudi
|
||||
// Both tokens may point to the same object (subjectToken) in case of a regular Token Exchange.
|
||||
// When the subject and actor Tokens point to different objects, the new tokens will be for impersonation / delegation.
|
||||
func (s *Server) createExchangeTokens(ctx context.Context, tokenType oidc.TokenType, client *Client, subjectToken, actorToken *exchangeToken, audience, scopes []string) (_ *oidc.TokenExchangeResponse, err error) {
|
||||
getUserInfo := s.getUserInfo(subjectToken.userID, client.client.ProjectID, client.client.ProjectRoleAssertion, client.IDTokenUserinfoClaimsAssertion(), scopes)
|
||||
getUserInfo := s.getUserInfo(subjectToken.userID, client.client.ProjectID, client.GetID(), client.client.ProjectRoleAssertion, client.IDTokenUserinfoClaimsAssertion(), scopes)
|
||||
getSigner := s.getSignerOnce()
|
||||
|
||||
resp := &oidc.TokenExchangeResponse{
|
||||
|
@@ -54,6 +54,7 @@ func (s *Server) UserInfo(ctx context.Context, r *op.Request[oidc.UserInfoReques
|
||||
token.userID,
|
||||
token.scope,
|
||||
projectID,
|
||||
token.clientID,
|
||||
assertion,
|
||||
true,
|
||||
false,
|
||||
@@ -86,6 +87,7 @@ func (s *Server) userInfo(
|
||||
userID string,
|
||||
scope []string,
|
||||
projectID string,
|
||||
clientID string,
|
||||
projectRoleAssertion, userInfoAssertion, currentProjectOnly bool,
|
||||
) func(ctx context.Context, roleAssertion bool, triggerType domain.TriggerType) (_ *oidc.UserInfo, err error) {
|
||||
var (
|
||||
@@ -120,7 +122,7 @@ func (s *Server) userInfo(
|
||||
Claims: maps.Clone(rawUserInfo.Claims),
|
||||
}
|
||||
assertRoles(projectID, qu, roleAudience, requestedRoles, roleAssertion, userInfo)
|
||||
return userInfo, s.userinfoFlows(ctx, qu, userInfo, triggerType)
|
||||
return userInfo, s.userinfoFlows(ctx, qu, userInfo, triggerType, clientID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +287,8 @@ func setUserInfoRoleClaims(userInfo *oidc.UserInfo, roles *projectsRoles) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) userinfoFlows(ctx context.Context, qu *query.OIDCUserInfo, userInfo *oidc.UserInfo, triggerType domain.TriggerType) (err error) {
|
||||
//nolint:gocognit
|
||||
func (s *Server) userinfoFlows(ctx context.Context, qu *query.OIDCUserInfo, userInfo *oidc.UserInfo, triggerType domain.TriggerType, clientID string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
@@ -319,6 +322,13 @@ func (s *Server) userinfoFlows(ctx context.Context, qu *query.OIDCUserInfo, user
|
||||
}
|
||||
}),
|
||||
),
|
||||
actions.SetFields("application",
|
||||
actions.SetFields("getClientId", func(c *actions.FieldConfig) interface{} {
|
||||
return func(goja.FunctionCall) goja.Value {
|
||||
return c.Runtime.ToValue(clientID)
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -427,6 +437,7 @@ func (s *Server) userinfoFlows(ctx context.Context, qu *query.OIDCUserInfo, user
|
||||
User: qu.User,
|
||||
UserMetadata: qu.Metadata,
|
||||
Org: qu.Org,
|
||||
Application: &ContextInfoApplication{ClientID: clientID},
|
||||
UserGrants: qu.UserGrants,
|
||||
}
|
||||
|
||||
@@ -463,13 +474,17 @@ func (s *Server) userinfoFlows(ctx context.Context, qu *query.OIDCUserInfo, user
|
||||
}
|
||||
|
||||
type ContextInfo struct {
|
||||
Function string `json:"function,omitempty"`
|
||||
UserInfo *oidc.UserInfo `json:"userinfo,omitempty"`
|
||||
User *query.User `json:"user,omitempty"`
|
||||
UserMetadata []query.UserMetadata `json:"user_metadata,omitempty"`
|
||||
Org *query.UserInfoOrg `json:"org,omitempty"`
|
||||
UserGrants []query.UserGrant `json:"user_grants,omitempty"`
|
||||
Response *ContextInfoResponse `json:"response,omitempty"`
|
||||
Function string `json:"function,omitempty"`
|
||||
UserInfo *oidc.UserInfo `json:"userinfo,omitempty"`
|
||||
User *query.User `json:"user,omitempty"`
|
||||
UserMetadata []query.UserMetadata `json:"user_metadata,omitempty"`
|
||||
Org *query.UserInfoOrg `json:"org,omitempty"`
|
||||
UserGrants []query.UserGrant `json:"user_grants,omitempty"`
|
||||
Application *ContextInfoApplication `json:"application,omitempty"`
|
||||
Response *ContextInfoResponse `json:"response,omitempty"`
|
||||
}
|
||||
type ContextInfoApplication struct {
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
}
|
||||
|
||||
type ContextInfoResponse struct {
|
||||
|
Reference in New Issue
Block a user