fix: correct unmarshall of EntraID userinfo when retrieving intent information (#10507)

# Which Problems Are Solved

EntraID userinfo gets incorrectly unmarshalled again in the
`RetrieveIdentityProviderIntent` endpoint.

# How the Problems Are Solved

Correctly use the already available information and not try to marshall
it into a `RawInformation` struct again.

# Additional Changes

None

# Additional Context

Closes https://github.com/zitadel/typescript/issues/578

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
(cherry picked from commit 93ea30ba2e)
This commit is contained in:
Stefan Benz
2025-08-22 07:35:58 +02:00
committed by Livio Spring
parent e3316354b0
commit ec3d79a37b
5 changed files with 213 additions and 12 deletions

View File

@@ -2206,6 +2206,7 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) {
func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
oauthIdpID := Instance.AddGenericOAuthProvider(IamCTX, gofakeit.AppName()).GetId()
azureIdpID := Instance.AddAzureADProvider(IamCTX, gofakeit.AppName()).GetId()
oidcIdpID := Instance.AddGenericOIDCProvider(IamCTX, gofakeit.AppName()).GetId()
samlIdpID := Instance.AddSAMLPostProvider(IamCTX)
ldapIdpID := Instance.AddLDAPProvider(IamCTX)
@@ -2232,22 +2233,32 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
require.NoError(t, err)
// make sure the intent is consumed
Instance.CreateIntentSession(t, IamCTX, intentUser.GetUserId(), successfulConsumedID, consumedToken)
azureADSuccessful, azureADToken, azureADChangeDate, azureADSequence, err := sink.SuccessfulAzureADIntent(Instance.ID(), azureIdpID, "id", "", expiry)
require.NoError(t, err)
azureADSuccessfulWithUserID, azureADWithUserIDToken, azureADWithUserIDChangeDate, azureADWithUserIDSequence, err := sink.SuccessfulAzureADIntent(Instance.ID(), azureIdpID, "id", "user", expiry)
require.NoError(t, err)
oidcSuccessful, oidcToken, oidcChangeDate, oidcSequence, err := sink.SuccessfulOIDCIntent(Instance.ID(), oidcIdpID, "id", "", expiry)
require.NoError(t, err)
oidcSuccessfulWithUserID, oidcWithUserIDToken, oidcWithUserIDChangeDate, oidcWithUserIDSequence, err := sink.SuccessfulOIDCIntent(Instance.ID(), oidcIdpID, "id", "user", expiry)
require.NoError(t, err)
ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence, err := sink.SuccessfulLDAPIntent(Instance.ID(), ldapIdpID, "id", "")
require.NoError(t, err)
ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence, err := sink.SuccessfulLDAPIntent(Instance.ID(), ldapIdpID, "id", "user")
require.NoError(t, err)
samlSuccessfulID, samlToken, samlChangeDate, samlSequence, err := sink.SuccessfulSAMLIntent(Instance.ID(), samlIdpID, "id", "", expiry)
require.NoError(t, err)
samlSuccessfulWithUserID, samlWithUserToken, samlWithUserChangeDate, samlWithUserSequence, err := sink.SuccessfulSAMLIntent(Instance.ID(), samlIdpID, "id", "user", expiry)
require.NoError(t, err)
jwtSuccessfulID, jwtToken, jwtChangeDate, jwtSequence, err := sink.SuccessfulJWTIntent(Instance.ID(), jwtIdPID, "id", "", expiry)
require.NoError(t, err)
jwtSuccessfulWithUserID, jwtWithUserToken, jwtWithUserChangeDate, jwtWithUserSequence, err := sink.SuccessfulJWTIntent(Instance.ID(), jwtIdPID, "id", "user", expiry)
require.NoError(t, err)
type args struct {
ctx context.Context
req *user.RetrieveIdentityProviderIntentRequest
@@ -2392,6 +2403,105 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
},
wantErr: true,
},
{
name: "retrieve successful azure AD intent",
args: args{
CTX,
&user.RetrieveIdentityProviderIntentRequest{
IdpIntentId: azureADSuccessful,
IdpIntentToken: azureADToken,
},
},
want: &user.RetrieveIdentityProviderIntentResponse{
Details: &object.Details{
ChangeDate: timestamppb.New(azureADChangeDate),
ResourceOwner: Instance.ID(),
Sequence: azureADSequence,
},
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Oauth{
Oauth: &user.IDPOAuthAccessInformation{
AccessToken: "accessToken",
IdToken: gu.Ptr("idToken"),
},
},
IdpId: azureIdpID,
UserId: "id",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"id": "id",
"userPrincipalName": "username",
"displayName": "displayname",
"givenName": "firstname",
"surname": "lastname",
"mail": "email@email.com",
})
require.NoError(t, err)
return s
}(),
},
AddHumanUser: &user.AddHumanUserRequest{
Username: gu.Ptr("username"),
Profile: &user.SetHumanProfile{
PreferredLanguage: gu.Ptr("und"),
GivenName: "firstname",
FamilyName: "lastname",
DisplayName: gu.Ptr("displayname"),
},
IdpLinks: []*user.IDPLink{
{IdpId: azureIdpID, UserId: "id", UserName: "username"},
},
Email: &user.SetHumanEmail{
Email: "email@email.com",
Verification: &user.SetHumanEmail_SendCode{SendCode: &user.SendEmailVerificationCode{}},
},
},
},
wantErr: false,
},
{
name: "retrieve successful azure AD intent with user ID",
args: args{
CTX,
&user.RetrieveIdentityProviderIntentRequest{
IdpIntentId: azureADSuccessfulWithUserID,
IdpIntentToken: azureADWithUserIDToken,
},
},
want: &user.RetrieveIdentityProviderIntentResponse{
Details: &object.Details{
ChangeDate: timestamppb.New(azureADWithUserIDChangeDate),
ResourceOwner: Instance.ID(),
Sequence: azureADWithUserIDSequence,
},
UserId: "user",
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Oauth{
Oauth: &user.IDPOAuthAccessInformation{
AccessToken: "accessToken",
IdToken: gu.Ptr("idToken"),
},
},
IdpId: azureIdpID,
UserId: "id",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"id": "id",
"userPrincipalName": "username",
"displayName": "displayname",
"givenName": "firstname",
"surname": "lastname",
"mail": "email@email.com",
})
require.NoError(t, err)
return s
}(),
},
},
wantErr: false,
},
{
name: "retrieve successful oidc intent",
args: args{

View File

@@ -185,7 +185,7 @@ func (s *Server) RetrieveIdentityProviderIntent(ctx context.Context, req *connec
case *jwt.Provider:
idpUser, err = unmarshalIdpUser(intent.IDPUser, jwt.InitUser())
case *azuread.Provider:
idpUser, err = unmarshalRawIdpUser(intent.IDPUser, p.User())
idpUser, err = unmarshalIdpUser(intent.IDPUser, p.User())
case *github.Provider:
idpUser, err = unmarshalIdpUser(intent.IDPUser, &github.User{})
case *gitlab.Provider: