diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html index f86c5cec4..c3157e3e0 100644 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html +++ b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html @@ -21,7 +21,7 @@ [configureProvider]="(justCreated$ | async) === ''" [configureTitle]="'DESCRIPTIONS.SETTINGS.IDPS.JWT.TITLE' | translate" [configureDescription]="'DESCRIPTIONS.SETTINGS.IDPS.JWT.DESCRIPTION' | translate" - configureLink="https://zitadel.com/docs/guides/integrate/identity-providers/jwt-idp" + configureLink="https://zitadel.com/docs/guides/integrate/identity-providers/jwt_idp" [autofillLink]="autofillLink$ | async" [activateLink]="activateLink$ | async" [expanded]="!!(expandWhatNow$ | async)" diff --git a/internal/api/grpc/user/v2/integration_test/intent_test.go b/internal/api/grpc/user/v2/integration_test/intent_test.go index bdb1844e4..8ace29cb0 100644 --- a/internal/api/grpc/user/v2/integration_test/intent_test.go +++ b/internal/api/grpc/user/v2/integration_test/intent_test.go @@ -425,8 +425,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oauthIdpID, @@ -476,8 +477,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oauthIdpID, @@ -543,8 +545,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: azureIdpID, @@ -601,8 +604,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: azureIdpID, @@ -657,8 +661,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oidcIdpID, @@ -707,8 +712,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oidcIdpID, diff --git a/internal/api/grpc/user/v2/intent.go b/internal/api/grpc/user/v2/intent.go index 77cc3874b..ddcab672e 100644 --- a/internal/api/grpc/user/v2/intent.go +++ b/internal/api/grpc/user/v2/intent.go @@ -250,7 +250,7 @@ func idpIntentToIDPIntentPb(intent *command.IDPIntentWriteModel, alg crypto.Encr information.Details = intentToDetailsPb(intent) // OAuth / OIDC if intent.IDPIDToken != "" || intent.IDPAccessToken != nil { - information.IdpInformation.Access, err = idpOAuthTokensToPb(intent.IDPIDToken, intent.IDPAccessToken, alg) + information.IdpInformation.Access, err = idpOAuthTokensToPb(intent.IDPIDToken, intent.IDPAccessToken, intent.IDPRefreshToken, alg) if err != nil { return nil, err } @@ -274,7 +274,7 @@ func idpIntentToIDPIntentPb(intent *command.IDPIntentWriteModel, alg crypto.Encr return information, nil } -func idpOAuthTokensToPb(idpIDToken string, idpAccessToken *crypto.CryptoValue, alg crypto.EncryptionAlgorithm) (_ *user.IDPInformation_Oauth, err error) { +func idpOAuthTokensToPb(idpIDToken string, idpAccessToken, idpRefreshToken *crypto.CryptoValue, alg crypto.EncryptionAlgorithm) (_ *user.IDPInformation_Oauth, err error) { var idToken *string if idpIDToken != "" { idToken = &idpIDToken @@ -286,10 +286,19 @@ func idpOAuthTokensToPb(idpIDToken string, idpAccessToken *crypto.CryptoValue, a return nil, err } } + var refreshToken *string + if idpRefreshToken != nil { + decryptedRefreshToken, err := crypto.DecryptString(idpRefreshToken, alg) + if err != nil { + return nil, err + } + refreshToken = &decryptedRefreshToken + } return &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: accessToken, - IdToken: idToken, + AccessToken: accessToken, + RefreshToken: refreshToken, + IdToken: idToken, }, }, nil } diff --git a/internal/api/grpc/user/v2beta/integration_test/user_test.go b/internal/api/grpc/user/v2beta/integration_test/user_test.go index 52e189bfb..c52b91267 100644 --- a/internal/api/grpc/user/v2beta/integration_test/user_test.go +++ b/internal/api/grpc/user/v2beta/integration_test/user_test.go @@ -2299,8 +2299,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oauthIdpID, @@ -2339,8 +2340,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oauthIdpID, @@ -2401,8 +2403,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oidcIdpID, @@ -2439,8 +2442,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) { IdpInformation: &user.IDPInformation{ Access: &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: "accessToken", - IdToken: gu.Ptr("idToken"), + AccessToken: "accessToken", + RefreshToken: gu.Ptr("refreshToken"), + IdToken: gu.Ptr("idToken"), }, }, IdpId: oidcIdpID, diff --git a/internal/api/grpc/user/v2beta/user.go b/internal/api/grpc/user/v2beta/user.go index 6dd848dd4..85cbf49f1 100644 --- a/internal/api/grpc/user/v2beta/user.go +++ b/internal/api/grpc/user/v2beta/user.go @@ -522,7 +522,7 @@ func idpIntentToIDPIntentPb(intent *command.IDPIntentWriteModel, alg crypto.Encr UserId: intent.UserID, } if intent.IDPIDToken != "" || intent.IDPAccessToken != nil { - information.IdpInformation.Access, err = idpOAuthTokensToPb(intent.IDPIDToken, intent.IDPAccessToken, alg) + information.IdpInformation.Access, err = idpOAuthTokensToPb(intent.IDPIDToken, intent.IDPAccessToken, intent.IDPRefreshToken, alg) if err != nil { return nil, err } @@ -547,7 +547,7 @@ func idpIntentToIDPIntentPb(intent *command.IDPIntentWriteModel, alg crypto.Encr return connect.NewResponse(information), nil } -func idpOAuthTokensToPb(idpIDToken string, idpAccessToken *crypto.CryptoValue, alg crypto.EncryptionAlgorithm) (_ *user.IDPInformation_Oauth, err error) { +func idpOAuthTokensToPb(idpIDToken string, idpAccessToken, idpRefreshToken *crypto.CryptoValue, alg crypto.EncryptionAlgorithm) (_ *user.IDPInformation_Oauth, err error) { var idToken *string if idpIDToken != "" { idToken = &idpIDToken @@ -559,10 +559,19 @@ func idpOAuthTokensToPb(idpIDToken string, idpAccessToken *crypto.CryptoValue, a return nil, err } } + var refreshToken *string + if idpRefreshToken != nil { + decryptedRefreshToken, err := crypto.DecryptString(idpRefreshToken, alg) + if err != nil { + return nil, err + } + refreshToken = &decryptedRefreshToken + } return &user.IDPInformation_Oauth{ Oauth: &user.IDPOAuthAccessInformation{ - AccessToken: accessToken, - IdToken: idToken, + AccessToken: accessToken, + RefreshToken: refreshToken, + IdToken: idToken, }, }, nil } diff --git a/internal/command/idp_intent.go b/internal/command/idp_intent.go index 97b460fc3..8b56e02b2 100644 --- a/internal/command/idp_intent.go +++ b/internal/command/idp_intent.go @@ -170,7 +170,7 @@ func (c *Commands) SucceedIDPIntent(ctx context.Context, writeModel *IDPIntentWr if err != nil { return "", err } - accessToken, idToken, err := tokensForSucceededIDPIntent(idpSession, c.idpConfigEncryption) + accessToken, refreshToken, idToken, err := tokensForSucceededIDPIntent(idpSession, c.idpConfigEncryption) if err != nil { return "", err } @@ -186,6 +186,7 @@ func (c *Commands) SucceedIDPIntent(ctx context.Context, writeModel *IDPIntentWr idpUser.GetPreferredUsername(), userID, accessToken, + refreshToken, idToken, idpSession.ExpiresAt(), ) @@ -295,8 +296,9 @@ func (c *Commands) GetIntentWriteModel(ctx context.Context, id, resourceOwner st return writeModel, err } -// tokensForSucceededIDPIntent extracts the oidc.Tokens if available (and encrypts the access_token) for the succeeded event payload -func tokensForSucceededIDPIntent(session idp.Session, encryptionAlg crypto.EncryptionAlgorithm) (*crypto.CryptoValue, string, error) { +// tokensForSucceededIDPIntent extracts the oidc.Tokens if available for the succeeded event payload. +// It also encrypts the access token and refresh token (if set). +func tokensForSucceededIDPIntent(session idp.Session, encryptionAlg crypto.EncryptionAlgorithm) (*crypto.CryptoValue, *crypto.CryptoValue, string, error) { var tokens *oidc.Tokens[*oidc.IDTokenClaims] switch s := session.(type) { case *oauth.Session: @@ -312,11 +314,25 @@ func tokensForSucceededIDPIntent(session idp.Session, encryptionAlg crypto.Encry case *apple.Session: tokens = s.Tokens default: - return nil, "", nil + return nil, nil, "", nil + } + if tokens == nil { + return nil, nil, "", nil } if tokens.Token == nil || tokens.AccessToken == "" { - return nil, tokens.IDToken, nil + return nil, nil, tokens.IDToken, nil } accessToken, err := crypto.Encrypt([]byte(tokens.AccessToken), encryptionAlg) - return accessToken, tokens.IDToken, err + if err != nil { + return nil, nil, tokens.IDToken, err + } + var refreshToken *crypto.CryptoValue + if tokens.RefreshToken != "" { + refreshToken, err = crypto.Encrypt([]byte(tokens.RefreshToken), encryptionAlg) + if err != nil { + return nil, nil, tokens.IDToken, err + } + } + + return accessToken, refreshToken, tokens.IDToken, nil } diff --git a/internal/command/idp_intent_model.go b/internal/command/idp_intent_model.go index 0155114f4..7c9c357ba 100644 --- a/internal/command/idp_intent_model.go +++ b/internal/command/idp_intent_model.go @@ -23,8 +23,9 @@ type IDPIntentWriteModel struct { UserID string LoginHint string - IDPAccessToken *crypto.CryptoValue - IDPIDToken string + IDPAccessToken *crypto.CryptoValue + IDPRefreshToken *crypto.CryptoValue + IDPIDToken string IDPEntryAttributes map[string][]string @@ -131,6 +132,7 @@ func (wm *IDPIntentWriteModel) reduceOAuthSucceededEvent(e *idpintent.SucceededE wm.IDPUserID = e.IDPUserID wm.IDPUserName = e.IDPUserName wm.IDPAccessToken = e.IDPAccessToken + wm.IDPRefreshToken = e.IDPRefreshToken wm.IDPIDToken = e.IDPIDToken wm.State = domain.IDPIntentStateSucceeded wm.succeededAt = e.CreationDate() diff --git a/internal/command/idp_intent_test.go b/internal/command/idp_intent_test.go index 8114b0014..9503548ed 100644 --- a/internal/command/idp_intent_test.go +++ b/internal/command/idp_intent_test.go @@ -1105,6 +1105,12 @@ func TestCommands_SucceedIDPIntent(t *testing.T) { KeyID: "id", Crypted: []byte("accessToken"), }, + &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("refreshToken"), + }, "idToken", time.Time{}, ) @@ -1119,7 +1125,8 @@ func TestCommands_SucceedIDPIntent(t *testing.T) { idpSession: &openid.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", + AccessToken: "accessToken", + RefreshToken: "refreshToken", }, IDToken: "idToken", }, @@ -1501,9 +1508,10 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { encryptionAlg crypto.EncryptionAlgorithm } type res struct { - accessToken *crypto.CryptoValue - idToken string - err error + accessToken *crypto.CryptoValue + refreshToken *crypto.CryptoValue + idToken string + err error } tests := []struct { name string @@ -1517,9 +1525,10 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { crypto.CreateMockEncryptionAlg(gomock.NewController(t)), }, res{ - accessToken: nil, - idToken: "", - err: nil, + accessToken: nil, + refreshToken: nil, + idToken: "", + err: nil, }, }, { @@ -1539,13 +1548,44 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { }(), }, res{ - accessToken: nil, - idToken: "", - err: zerrors.ThrowInternal(nil, "id", "encryption failed"), + accessToken: nil, + refreshToken: nil, + idToken: "", + err: zerrors.ThrowInternal(nil, "id", "encryption failed"), }, }, { "oauth tokens", + args{ + &oauth.Session{ + Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ + Token: &oauth2.Token{ + AccessToken: "accessToken", + RefreshToken: "refreshToken", + }, + }, + }, + crypto.CreateMockEncryptionAlg(gomock.NewController(t)), + }, + res{ + accessToken: &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("accessToken"), + }, + refreshToken: &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("refreshToken"), + }, + idToken: "", + err: nil, + }, + }, + { + "oauth tokens - no refresh token", args{ &oauth.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ @@ -1563,8 +1603,9 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { KeyID: "id", Crypted: []byte("accessToken"), }, - idToken: "", - err: nil, + refreshToken: nil, + idToken: "", + err: nil, }, }, { @@ -1573,7 +1614,8 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { &openid.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", + AccessToken: "accessToken", + RefreshToken: "refreshToken", }, IDToken: "idToken", }, @@ -1587,6 +1629,12 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { KeyID: "id", Crypted: []byte("accessToken"), }, + refreshToken: &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("refreshToken"), + }, idToken: "idToken", err: nil, }, @@ -1602,9 +1650,10 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { crypto.CreateMockEncryptionAlg(gomock.NewController(t)), }, res{ - accessToken: nil, - idToken: "idToken", - err: nil, + accessToken: nil, + refreshToken: nil, + idToken: "idToken", + err: nil, }, }, { @@ -1628,8 +1677,9 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { KeyID: "id", Crypted: []byte("accessToken"), }, - idToken: "", - err: nil, + refreshToken: nil, + idToken: "", + err: nil, }, }, { @@ -1639,7 +1689,8 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { OAuthSession: &oauth.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", + AccessToken: "accessToken", + RefreshToken: "refreshToken", }, IDToken: "idToken", }, @@ -1654,6 +1705,12 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { KeyID: "id", Crypted: []byte("accessToken"), }, + refreshToken: &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("refreshToken"), + }, idToken: "idToken", err: nil, }, @@ -1661,9 +1718,10 @@ func Test_tokensForSucceededIDPIntent(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotAccessToken, gotIDToken, err := tokensForSucceededIDPIntent(tt.args.session, tt.args.encryptionAlg) + gotAccessToken, refreshToken, gotIDToken, err := tokensForSucceededIDPIntent(tt.args.session, tt.args.encryptionAlg) require.ErrorIs(t, err, tt.res.err) assert.Equal(t, tt.res.accessToken, gotAccessToken) + assert.Equal(t, tt.res.refreshToken, refreshToken) assert.Equal(t, tt.res.idToken, gotIDToken) }) } diff --git a/internal/command/session_test.go b/internal/command/session_test.go index 09c136e4e..46d952666 100644 --- a/internal/command/session_test.go +++ b/internal/command/session_test.go @@ -742,6 +742,7 @@ func TestCommands_updateSession(t *testing.T) { "idpUserName", "userID2", nil, + nil, "", time.Now().Add(time.Hour), ), @@ -823,6 +824,7 @@ func TestCommands_updateSession(t *testing.T) { "idpUsername", "userID", nil, + nil, "", time.Now().Add(time.Hour), ), @@ -878,6 +880,7 @@ func TestCommands_updateSession(t *testing.T) { "idpUsername", "userID", nil, + nil, "", time.Now().Add(-time.Hour), ), @@ -928,6 +931,7 @@ func TestCommands_updateSession(t *testing.T) { "idpUsername", "userID", nil, + nil, "", time.Now().Add(time.Hour), ), @@ -1005,6 +1009,7 @@ func TestCommands_updateSession(t *testing.T) { "idpUsername", "", nil, + nil, "", time.Now().Add(time.Hour), ), diff --git a/internal/integration/sink/server.go b/internal/integration/sink/server.go index e8f81d51d..385125fc7 100644 --- a/internal/integration/sink/server.go +++ b/internal/integration/sink/server.go @@ -438,8 +438,9 @@ func createSuccessfulOAuthIntent(ctx context.Context, cmd *command.Commands, req idpSession := &oauth.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", - Expiry: req.Expiry, + AccessToken: "accessToken", + RefreshToken: "refreshToken", + Expiry: req.Expiry, }, IDToken: "idToken", }, @@ -476,8 +477,9 @@ func createSuccessfulAzureADIntent(ctx context.Context, cmd *command.Commands, r idpSession := &oauth.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", - Expiry: req.Expiry, + AccessToken: "accessToken", + RefreshToken: "refreshToken", + Expiry: req.Expiry, }, IDToken: "idToken", }, @@ -508,8 +510,9 @@ func createSuccessfulOIDCIntent(ctx context.Context, cmd *command.Commands, req idpSession := &openid.Session{ Tokens: &oidc.Tokens[*oidc.IDTokenClaims]{ Token: &oauth2.Token{ - AccessToken: "accessToken", - Expiry: req.Expiry, + AccessToken: "accessToken", + RefreshToken: "refreshToken", + Expiry: req.Expiry, }, IDToken: "idToken", }, diff --git a/internal/repository/idpintent/intent.go b/internal/repository/idpintent/intent.go index 91f907781..67f4c0806 100644 --- a/internal/repository/idpintent/intent.go +++ b/internal/repository/idpintent/intent.go @@ -82,9 +82,10 @@ type SucceededEvent struct { IDPUserName string `json:"idpUserName,omitempty"` UserID string `json:"userId,omitempty"` - IDPAccessToken *crypto.CryptoValue `json:"idpAccessToken,omitempty"` - IDPIDToken string `json:"idpIdToken,omitempty"` - ExpiresAt time.Time `json:"expiresAt,omitempty"` + IDPAccessToken *crypto.CryptoValue `json:"idpAccessToken,omitempty"` + IDPRefreshToken *crypto.CryptoValue `json:"idpRefreshToken,omitempty"` + IDPIDToken string `json:"idpIdToken,omitempty"` + ExpiresAt time.Time `json:"expiresAt,omitempty"` } func NewSucceededEvent( @@ -95,6 +96,7 @@ func NewSucceededEvent( idpUserName, userID string, idpAccessToken *crypto.CryptoValue, + idpRefreshToken *crypto.CryptoValue, idpIDToken string, expiresAt time.Time, ) *SucceededEvent { @@ -104,13 +106,14 @@ func NewSucceededEvent( aggregate, SucceededEventType, ), - IDPUser: idpUser, - IDPUserID: idpUserID, - IDPUserName: idpUserName, - UserID: userID, - IDPAccessToken: idpAccessToken, - IDPIDToken: idpIDToken, - ExpiresAt: expiresAt, + IDPUser: idpUser, + IDPUserID: idpUserID, + IDPUserName: idpUserName, + UserID: userID, + IDPAccessToken: idpAccessToken, + IDPRefreshToken: idpRefreshToken, + IDPIDToken: idpIDToken, + ExpiresAt: expiresAt, } } diff --git a/proto/zitadel/user/v2/idp.proto b/proto/zitadel/user/v2/idp.proto index eeb51106a..3dee082ef 100644 --- a/proto/zitadel/user/v2/idp.proto +++ b/proto/zitadel/user/v2/idp.proto @@ -129,8 +129,24 @@ message IDPInformation{ } message IDPOAuthAccessInformation{ - string access_token = 1; - optional string id_token = 2; + // The access token returned by the external identity provider. + string access_token = 1[ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Access token returned by the external identity provider" + } + ]; + // The ID token is only set when it is returned by the external identity provider. + optional string id_token = 2[ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "ID token returned by the external identity provider. Only set if the external identity provider returns an ID token." + } + ]; + // The refresh token is only set when it is returned by the external identity provider. + optional string refresh_token = 3 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Refresh token returned by the external identity provider. Only set if the external identity provider returns a refresh token." + } + ]; } message IDPLDAPAccessInformation{ diff --git a/proto/zitadel/user/v2beta/idp.proto b/proto/zitadel/user/v2beta/idp.proto index 96c34863f..5675c72a6 100644 --- a/proto/zitadel/user/v2beta/idp.proto +++ b/proto/zitadel/user/v2beta/idp.proto @@ -129,8 +129,24 @@ message IDPInformation{ } message IDPOAuthAccessInformation{ - string access_token = 1; - optional string id_token = 2; + // The access token returned by the external identity provider. + string access_token = 1[ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Access token returned by the external identity provider" + } + ]; + // The ID token is only set when it is returned by the external identity provider. + optional string id_token = 2[ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "ID token returned by the external identity provider. Only set if the external identity provider returns an ID token." + } + ]; + // The refresh token is only set when it is returned by the external identity provider. + optional string refresh_token = 3 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Refresh token returned by the external identity provider. Only set if the external identity provider returns a refresh token." + } + ]; } message IDPLDAPAccessInformation{