feat(api): allow specifying access token type for user of type machine (#11599)

# Which Problems Are Solved

The user service v2 didn't allow the specify or change the access token
type for users of type machine and referred to using the management API,
which in return was already deprecated and linked to the user service.

# How the Problems Are Solved

Added a possibility to specify the access token type in the creation and
update request.

# Additional Changes

None

# Additional Context

- closes #10850
- requires backport to v4.x

---------

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Livio Spring
2026-02-19 05:05:19 +00:00
committed by GitHub
co-authored by Copilot
parent a31e435491
commit e41b70b1e3
6 changed files with 176 additions and 18 deletions
@@ -3639,6 +3639,28 @@ func TestServer_CreateUser_And_Compare(t *testing.T) {
},
}
},
}, {
name: "machine access token type jwt",
testCase: func(runId string) testCase {
return testCase{
args: args{
ctx: OrgCTX,
req: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "donald",
AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT,
},
},
},
},
assert: func(t *testing.T, createResponse *user.CreateUserResponse, getResponse *user.GetUserByIDResponse) {
assert.Equal(t, user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, getResponse.GetUser().GetMachine().GetAccessTokenType())
},
}
},
}}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -4308,6 +4330,35 @@ func TestServer_UpdateUser_And_Compare(t *testing.T) {
},
}
},
}, {
name: "machine accessTokenType",
testCase: func(runId string) testCase {
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "Donald",
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{
AccessTokenType: gu.Ptr(user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT),
},
},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse) {
assert.Equal(t, user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, getResponse.GetUser().GetMachine().GetAccessTokenType())
},
}
},
}}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+22 -5
View File
@@ -17,7 +17,7 @@ func (s *Server) createUserTypeMachine(ctx context.Context, machinePb *user.Crea
Username: userName,
Name: machinePb.Name,
Description: machinePb.GetDescription(),
AccessTokenType: domain.OIDCTokenTypeBearer,
AccessTokenType: accessTokenTypeToDomain(machinePb.GetAccessTokenType()),
ObjectRoot: models.ObjectRoot{
ResourceOwner: orgId,
AggregateID: userId,
@@ -51,10 +51,27 @@ func (s *Server) updateUserTypeMachine(ctx context.Context, machinePb *user.Upda
}
func updateMachineUserToCommand(userId string, userName *string, machine *user.UpdateUserRequest_Machine) *command.ChangeMachine {
var accessTokenType *domain.OIDCTokenType
if machine.AccessTokenType != nil {
tokenType := accessTokenTypeToDomain(*machine.AccessTokenType)
accessTokenType = &tokenType
}
return &command.ChangeMachine{
ID: userId,
Username: userName,
Name: machine.Name,
Description: machine.Description,
ID: userId,
Username: userName,
Name: machine.Name,
Description: machine.Description,
AccessTokenType: accessTokenType,
}
}
func accessTokenTypeToDomain(accessTokenType user.AccessTokenType) domain.OIDCTokenType {
switch accessTokenType {
case user.AccessTokenType_ACCESS_TOKEN_TYPE_BEARER:
return domain.OIDCTokenTypeBearer
case user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT:
return domain.OIDCTokenTypeJWT
default:
return domain.OIDCTokenTypeBearer
}
}
+9 -6
View File
@@ -9,6 +9,7 @@ import (
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
)
@@ -40,15 +41,17 @@ func Test_patchMachineUserToCommand(t *testing.T) {
userId: "userId",
userName: gu.Ptr("userName"),
machine: &user.UpdateUserRequest_Machine{
Name: gu.Ptr("name"),
Description: gu.Ptr("description"),
Name: gu.Ptr("name"),
Description: gu.Ptr("description"),
AccessTokenType: gu.Ptr(user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT),
},
},
want: &command.ChangeMachine{
ID: "userId",
Username: gu.Ptr("userName"),
Name: gu.Ptr("name"),
Description: gu.Ptr("description"),
ID: "userId",
Username: gu.Ptr("userName"),
Name: gu.Ptr("name"),
Description: gu.Ptr("description"),
AccessTokenType: gu.Ptr(domain.OIDCTokenTypeJWT),
},
}}
for _, tt := range tests {