fix: add userID to intent responses (#6566)

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz 2023-09-25 07:21:50 +02:00 committed by GitHub
parent 689655a50d
commit 2823678eb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 228 additions and 4 deletions

View File

@ -172,8 +172,14 @@ func (s *Server) startLDAPIntent(ctx context.Context, idpID string, ldapCredenti
return nil, err
}
return &user.StartIdentityProviderIntentResponse{
Details: object.DomainToDetailsPb(details),
NextStep: &user.StartIdentityProviderIntentResponse_IdpIntent{IdpIntent: &user.IDPIntent{IdpIntentId: intentWriteModel.AggregateID, IdpIntentToken: token}},
Details: object.DomainToDetailsPb(details),
NextStep: &user.StartIdentityProviderIntentResponse_IdpIntent{
IdpIntent: &user.IDPIntent{
IdpIntentId: intentWriteModel.AggregateID,
IdpIntentToken: token,
UserId: userID,
},
},
}, nil
}
@ -256,6 +262,7 @@ func idpIntentToIDPIntentPb(intent *command.IDPIntentWriteModel, alg crypto.Encr
UserName: intent.IDPUserName,
RawInformation: rawInformation,
},
UserId: intent.UserID,
}
if intent.IDPIDToken != "" || intent.IDPAccessToken != nil {
information.IdpInformation.Access, err = idpOAuthTokensToPb(intent.IDPIDToken, intent.IDPAccessToken, alg)

View File

@ -694,7 +694,9 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
idpID := Tester.AddGenericOAuthProvider(t)
intentID := Tester.CreateIntent(t, idpID)
successfulID, token, changeDate, sequence := Tester.CreateSuccessfulOAuthIntent(t, idpID, "", "id")
successfulWithUserID, WithUsertoken, WithUserchangeDate, WithUsersequence := Tester.CreateSuccessfulOAuthIntent(t, idpID, "user", "id")
ldapSuccessfulID, ldapToken, ldapChangeDate, ldapSequence := Tester.CreateSuccessfulLDAPIntent(t, idpID, "", "id")
ldapSuccessfulWithUserID, ldapWithUserToken, ldapWithUserChangeDate, ldapWithUserSequence := Tester.CreateSuccessfulLDAPIntent(t, idpID, "user", "id")
type args struct {
ctx context.Context
req *user.RetrieveIdentityProviderIntentRequest
@ -764,6 +766,44 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
},
wantErr: false,
},
{
name: "retrieve successful intent with linked user",
args: args{
CTX,
&user.RetrieveIdentityProviderIntentRequest{
IdpIntentId: successfulWithUserID,
IdpIntentToken: WithUsertoken,
},
},
want: &user.RetrieveIdentityProviderIntentResponse{
Details: &object.Details{
ChangeDate: timestamppb.New(WithUserchangeDate),
ResourceOwner: Tester.Organisation.ID,
Sequence: WithUsersequence,
},
UserId: "user",
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Oauth{
Oauth: &user.IDPOAuthAccessInformation{
AccessToken: "accessToken",
IdToken: gu.Ptr("idToken"),
},
},
IdpId: idpID,
UserId: "id",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"sub": "id",
"preferred_username": "username",
})
require.NoError(t, err)
return s
}(),
},
},
wantErr: false,
},
{
name: "retrieve successful ldap intent",
args: args{
@ -809,6 +849,52 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
},
wantErr: false,
},
{
name: "retrieve successful ldap intent with linked user",
args: args{
CTX,
&user.RetrieveIdentityProviderIntentRequest{
IdpIntentId: ldapSuccessfulWithUserID,
IdpIntentToken: ldapWithUserToken,
},
},
want: &user.RetrieveIdentityProviderIntentResponse{
Details: &object.Details{
ChangeDate: timestamppb.New(ldapWithUserChangeDate),
ResourceOwner: Tester.Organisation.ID,
Sequence: ldapWithUserSequence,
},
UserId: "user",
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Ldap{
Ldap: &user.IDPLDAPAccessInformation{
Attributes: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"id": []interface{}{"id"},
"username": []interface{}{"username"},
"language": []interface{}{"en"},
})
require.NoError(t, err)
return s
}(),
},
},
IdpId: idpID,
UserId: "id",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"id": "id",
"preferredUsername": "username",
"preferredLanguage": "en",
})
require.NoError(t, err)
return s
}(),
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -84,9 +84,65 @@ func Test_idpIntentToIDPIntentPb(t *testing.T) {
resp: nil,
err: caos_errs.ThrowInternal(nil, "id", "invalid key id"),
},
}, {
"successful oauth",
args{
intent: &command.IDPIntentWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: "intentID",
ProcessedSequence: 123,
ResourceOwner: "ro",
InstanceID: "instanceID",
ChangeDate: time.Date(2019, 4, 1, 1, 1, 1, 1, time.Local),
},
IDPID: "idpID",
IDPUser: []byte(`{"userID": "idpUserID", "username": "username"}`),
IDPUserID: "idpUserID",
IDPUserName: "username",
IDPAccessToken: &crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("accessToken"),
},
IDPIDToken: "idToken",
UserID: "",
State: domain.IDPIntentStateSucceeded,
},
alg: decryption(nil),
},
res{
resp: &user.RetrieveIdentityProviderIntentResponse{
Details: &object_pb.Details{
Sequence: 123,
ChangeDate: timestamppb.New(time.Date(2019, 4, 1, 1, 1, 1, 1, time.Local)),
ResourceOwner: "ro",
},
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Oauth{
Oauth: &user.IDPOAuthAccessInformation{
AccessToken: "accessToken",
IdToken: gu.Ptr("idToken"),
},
},
IdpId: "idpID",
UserId: "idpUserID",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"userID": "idpUserID",
"username": "username",
})
require.NoError(t, err)
return s
}(),
},
},
err: nil,
},
},
{
"successful oauth",
"successful oauth with linked user",
args{
intent: &command.IDPIntentWriteModel{
WriteModel: eventstore.WriteModel{
@ -138,11 +194,72 @@ func Test_idpIntentToIDPIntentPb(t *testing.T) {
return s
}(),
},
UserId: "userID",
},
err: nil,
},
}, {
"successful ldap",
args{
intent: &command.IDPIntentWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: "intentID",
ProcessedSequence: 123,
ResourceOwner: "ro",
InstanceID: "instanceID",
ChangeDate: time.Date(2019, 4, 1, 1, 1, 1, 1, time.Local),
},
IDPID: "idpID",
IDPUser: []byte(`{"userID": "idpUserID", "username": "username"}`),
IDPUserID: "idpUserID",
IDPUserName: "username",
IDPEntryAttributes: map[string][]string{
"id": {"idpUserID"},
"firstName": {"firstname1", "firstname2"},
"lastName": {"lastname"},
},
UserID: "",
State: domain.IDPIntentStateSucceeded,
},
},
res{
resp: &user.RetrieveIdentityProviderIntentResponse{
Details: &object_pb.Details{
Sequence: 123,
ChangeDate: timestamppb.New(time.Date(2019, 4, 1, 1, 1, 1, 1, time.Local)),
ResourceOwner: "ro",
},
IdpInformation: &user.IDPInformation{
Access: &user.IDPInformation_Ldap{
Ldap: &user.IDPLDAPAccessInformation{
Attributes: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"id": []interface{}{"idpUserID"},
"firstName": []interface{}{"firstname1", "firstname2"},
"lastName": []interface{}{"lastname"},
})
require.NoError(t, err)
return s
}(),
},
},
IdpId: "idpID",
UserId: "idpUserID",
UserName: "username",
RawInformation: func() *structpb.Struct {
s, err := structpb.NewStruct(map[string]interface{}{
"userID": "idpUserID",
"username": "username",
})
require.NoError(t, err)
return s
}(),
},
},
err: nil,
},
}, {
"successful ldap with linked user",
args{
intent: &command.IDPIntentWriteModel{
WriteModel: eventstore.WriteModel{
@ -198,6 +315,7 @@ func Test_idpIntentToIDPIntentPb(t *testing.T) {
return s
}(),
},
UserId: "userID",
},
err: nil,
},

View File

@ -57,7 +57,7 @@ message IDPIntent {
description: "ID of the IDP intent"
min_length: 1;
max_length: 200;
example: "\"163840776835432705=\"";
example: "\"163840776835432705\"";
}
];
string idp_intent_token = 2 [
@ -68,6 +68,13 @@ message IDPIntent {
example: "\"SJKL3ioIDpo342ioqw98fjp3sdf32wahb=\"";
}
];
string user_id = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID of the ZITADEL user if external user already linked"
max_length: 200;
example: "\"163840776835432345\"";
}
];
}
message IDPInformation{

View File

@ -1159,6 +1159,12 @@ message RetrieveIdentityProviderIntentRequest{
message RetrieveIdentityProviderIntentResponse{
zitadel.object.v2beta.Details details = 1;
IDPInformation idp_information = 2;
string user_id = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID of the user in ZITADEL if external user is linked"
example: "\"163840776835432345\"";
}
];
}
message AddIDPLinkRequest{