feat: actions v2 for functions (#9420)

# Which Problems Are Solved

Actions v2 are not executed in different functions, as provided by the
actions v1.

# How the Problems Are Solved

Add functionality to call actions v2 through OIDC and SAML logic to
complement tokens and SAMLResponses.

# Additional Changes

- Corrected testing for retrieved intent information
- Added testing for IDP types
- Corrected handling of context for issuer in SAML logic

# Additional Context

- Closes #7247 
- Dependent on https://github.com/zitadel/saml/pull/97
- docs for migration are done in separate issue:
https://github.com/zitadel/zitadel/issues/9456

---------

Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
This commit is contained in:
Stefan Benz
2025-03-04 12:09:30 +01:00
committed by GitHub
parent d9d8339813
commit 0c87a96e2c
29 changed files with 1964 additions and 380 deletions

View File

@@ -27,6 +27,7 @@ import (
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/idp/providers/ldap"
"github.com/zitadel/zitadel/internal/idp/providers/oauth"
openid "github.com/zitadel/zitadel/internal/idp/providers/oidc"
"github.com/zitadel/zitadel/internal/idp/providers/saml"
)
@@ -65,6 +66,24 @@ func SuccessfulOAuthIntent(instanceID, idpID, idpUserID, userID string) (string,
return resp.IntentID, resp.Token, resp.ChangeDate, resp.Sequence, nil
}
func SuccessfulOIDCIntent(instanceID, idpID, idpUserID, userID string) (string, string, time.Time, uint64, error) {
u := url.URL{
Scheme: "http",
Host: host,
Path: successfulIntentOIDCPath(),
}
resp, err := callIntent(u.String(), &SuccessfulIntentRequest{
InstanceID: instanceID,
IDPID: idpID,
IDPUserID: idpUserID,
UserID: userID,
})
if err != nil {
return "", "", time.Time{}, uint64(0), err
}
return resp.IntentID, resp.Token, resp.ChangeDate, resp.Sequence, nil
}
func SuccessfulSAMLIntent(instanceID, idpID, idpUserID, userID string) (string, string, time.Time, uint64, error) {
u := url.URL{
Scheme: "http",
@@ -119,6 +138,7 @@ func StartServer(commands *command.Commands) (close func()) {
router.HandleFunc(rootPath(ch), fwd.receiveHandler)
router.HandleFunc(subscribePath(ch), fwd.subscriptionHandler)
router.HandleFunc(successfulIntentOAuthPath(), successfulIntentHandler(commands, createSuccessfulOAuthIntent))
router.HandleFunc(successfulIntentOIDCPath(), successfulIntentHandler(commands, createSuccessfulOIDCIntent))
router.HandleFunc(successfulIntentSAMLPath(), successfulIntentHandler(commands, createSuccessfulSAMLIntent))
router.HandleFunc(successfulIntentLDAPPath(), successfulIntentHandler(commands, createSuccessfulLDAPIntent))
}
@@ -159,6 +179,10 @@ func successfulIntentOAuthPath() string {
return path.Join(successfulIntentPath(), "/", "oauth")
}
func successfulIntentOIDCPath() string {
return path.Join(successfulIntentPath(), "/", "oidc")
}
func successfulIntentSAMLPath() string {
return path.Join(successfulIntentPath(), "/", "saml")
}
@@ -334,6 +358,41 @@ func createIntent(ctx context.Context, cmd *command.Commands, instanceID, idpID
}
func createSuccessfulOAuthIntent(ctx context.Context, cmd *command.Commands, req *SuccessfulIntentRequest) (*SuccessfulIntentResponse, error) {
intentID, err := createIntent(ctx, cmd, req.InstanceID, req.IDPID)
if err != nil {
return nil, err
}
writeModel, err := cmd.GetIntentWriteModel(ctx, intentID, req.InstanceID)
if err != nil {
return nil, err
}
idAttribute := "id"
idpUser := oauth.NewUserMapper(idAttribute)
idpUser.RawInfo = map[string]interface{}{
idAttribute: req.IDPUserID,
"preferred_username": "username",
}
idpSession := &oauth.Session{
Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{
Token: &oauth2.Token{
AccessToken: "accessToken",
},
IDToken: "idToken",
},
}
token, err := cmd.SucceedIDPIntent(ctx, writeModel, idpUser, idpSession, req.UserID)
if err != nil {
return nil, err
}
return &SuccessfulIntentResponse{
intentID,
token,
writeModel.ChangeDate,
writeModel.ProcessedSequence,
}, nil
}
func createSuccessfulOIDCIntent(ctx context.Context, cmd *command.Commands, req *SuccessfulIntentRequest) (*SuccessfulIntentResponse, error) {
intentID, err := createIntent(ctx, cmd, req.InstanceID, req.IDPID)
writeModel, err := cmd.GetIntentWriteModel(ctx, intentID, req.InstanceID)
idpUser := openid.NewUser(