fix: set refresh token in the RetrieveIdentityIntentResponse (#11613)

# Which Problems Are Solved

This PR adds support for storing and retrieving refresh tokens from
external identity providers during the IDP intent flow.

# How the Problems Are Solved

* Updated `idp.proto` (v2 and v2beta): added an optional `refresh_token`
field to `IDPOAuthAccessInformation`, which, in turn, is used in
`RetrieveIdentityProviderIntentResponse`
* Added the `IDPRefreshToken` field to the IDP intent `SucceededEvent`
struct, and updated the corresponding constructor to set the refresh
token
* Added the `IDPRefreshToken` field to `IDPIntentWriteModel`, and
updated `reduceOAuthSucceededEvent` to populate refresh token from
events
* Updated `tokensForSucceededIDPIntent` function to extract and encrypt
the refresh token from IDP session, if set
* Updated `idpOAuthTokensToPb` function to decrypt refresh token before
returning to clients
* Updated unit and integration tests

# Additional Changes
Updated the link to the JWT IDP docs linked in the Console

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/11047
This commit is contained in:
Gayathri Vijayan
2026-02-19 06:06:30 +00:00
committed by GitHub
parent a5a5b65931
commit 6ad1ef859b
13 changed files with 224 additions and 77 deletions
@@ -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)"
@@ -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,
+13 -4
View File
@@ -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
}
@@ -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,
+13 -4
View File
@@ -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
}
+22 -6
View File
@@ -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
}
+4 -2
View File
@@ -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()
+78 -20
View File
@@ -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)
})
}
+5
View File
@@ -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),
),
+9 -6
View File
@@ -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",
},
+13 -10
View File
@@ -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,
}
}
+18 -2
View File
@@ -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{
+18 -2
View File
@@ -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{