feat: add ability to customize session duration of clients (#1641)

This commit is contained in:
Elias Schneider
2026-08-03 23:23:29 +02:00
committed by GitHub
parent 1238bf0f37
commit 5d43c4aaeb
28 changed files with 752 additions and 77 deletions
+9 -3
View File
@@ -32,8 +32,8 @@ const (
GrantTypeDeviceCode = "urn:ietf:params:oauth:grant-type:device_code"
GrantTypeClientCredentials = "client_credentials"
AccessTokenDuration = time.Hour
RefreshTokenDuration = 30 * 24 * time.Hour // 30 days
AccessTokenDuration = time.Duration(model.DefaultAccessTokenDurationMinutes) * time.Minute
RefreshTokenDuration = time.Duration(model.DefaultRefreshTokenDurationMinutes) * time.Minute
)
type OidcService struct {
@@ -148,7 +148,9 @@ func (s *OidcService) CreateClient(ctx context.Context, input dto.OidcClientCrea
Base: model.Base{
ID: input.ID,
},
CreatedByID: new(userID),
CreatedByID: new(userID),
AccessTokenDurationMinutes: model.DefaultAccessTokenDurationMinutes,
RefreshTokenDurationMinutes: model.DefaultRefreshTokenDurationMinutes,
}
updateOIDCClientModelFromDto(&client, &input.OidcClientUpdateDto)
@@ -213,6 +215,8 @@ func (s *OidcService) UpdateClient(ctx context.Context, clientID string, input d
"SkipConsent",
"LaunchURL",
"IsGroupRestricted",
"AccessTokenDurationMinutes",
"RefreshTokenDurationMinutes",
).
Updates(&client).Error
} else {
@@ -253,6 +257,8 @@ func updateOIDCClientModelFromDto(client *model.OidcClient, input *dto.OidcClien
client.SkipConsent = input.SkipConsent
client.LaunchURL = input.LaunchURL
client.IsGroupRestricted = input.IsGroupRestricted
client.AccessTokenDurationMinutes = input.AccessTokenDurationMinutes
client.RefreshTokenDurationMinutes = input.RefreshTokenDurationMinutes
// Preserve fields that are sourced from the client metadata document
if client.IsMetadataDocument() {
+25 -9
View File
@@ -528,9 +528,11 @@ func TestOidcService_CreateClient_withDescription(t *testing.T) {
description := "A test client description"
input := dto.OidcClientCreateDto{
OidcClientUpdateDto: dto.OidcClientUpdateDto{
Name: "Test Client",
Description: description,
CallbackURLs: []string{"https://example.com/callback"},
Name: "Test Client",
Description: description,
CallbackURLs: []string{"https://example.com/callback"},
AccessTokenDurationMinutes: model.DefaultAccessTokenDurationMinutes,
RefreshTokenDurationMinutes: model.DefaultRefreshTokenDurationMinutes,
},
}
@@ -552,8 +554,10 @@ func TestOidcService_CreateClient_withoutDescription(t *testing.T) {
input := dto.OidcClientCreateDto{
OidcClientUpdateDto: dto.OidcClientUpdateDto{
Name: "Test Client",
CallbackURLs: []string{"https://example.com/callback"},
Name: "Test Client",
CallbackURLs: []string{"https://example.com/callback"},
AccessTokenDurationMinutes: model.DefaultAccessTokenDurationMinutes,
RefreshTokenDurationMinutes: model.DefaultRefreshTokenDurationMinutes,
},
}
@@ -606,9 +610,11 @@ func TestOidcService_UpdateClient_description(t *testing.T) {
// Update with a description
description := "Updated description"
input := dto.OidcClientUpdateDto{
Name: "Test Client",
Description: description,
CallbackURLs: []string{"https://example.com/callback"},
Name: "Test Client",
Description: description,
CallbackURLs: []string{"https://example.com/callback"},
AccessTokenDurationMinutes: model.DefaultAccessTokenDurationMinutes,
RefreshTokenDurationMinutes: model.DefaultRefreshTokenDurationMinutes,
}
_, err = s.UpdateClient(t.Context(), client.ID, input)
@@ -654,6 +660,8 @@ func TestOidcService_UpdateClient_CIMDPreservesMetadataFields(t *testing.T) {
require.NoError(t, db.Create(&client).Error)
launchURL := "https://app.example.com"
accessDuration := int64(2 * 60)
refreshDuration := int64(7 * 24 * 60)
input := dto.OidcClientUpdateDto{
Name: "Overridden Client",
Description: "Locally managed description",
@@ -666,6 +674,8 @@ func TestOidcService_UpdateClient_CIMDPreservesMetadataFields(t *testing.T) {
SkipConsent: true,
LaunchURL: &launchURL,
IsGroupRestricted: true,
AccessTokenDurationMinutes: accessDuration,
RefreshTokenDurationMinutes: refreshDuration,
Credentials: dto.OidcClientCredentialsDto{
FederatedIdentities: []dto.OidcClientFederatedIdentityDto{{
Issuer: "https://override.example.com",
@@ -691,6 +701,8 @@ func TestOidcService_UpdateClient_CIMDPreservesMetadataFields(t *testing.T) {
assert.Equal(t, input.SkipConsent, fetched.SkipConsent)
assert.Equal(t, input.LaunchURL, fetched.LaunchURL)
assert.Equal(t, input.IsGroupRestricted, fetched.IsGroupRestricted)
assert.Equal(t, accessDuration, fetched.AccessTokenDurationMinutes)
assert.Equal(t, refreshDuration, fetched.RefreshTokenDurationMinutes)
}
func TestOidcService_UpdateClient_CIMDDoesNotOverwriteConcurrentMetadataRefresh(t *testing.T) {
@@ -715,7 +727,11 @@ func TestOidcService_UpdateClient_CIMDDoesNotOverwriteConcurrentMetadataRefresh(
END;
`).Error)
input := dto.OidcClientUpdateDto{Description: "Locally managed description"}
input := dto.OidcClientUpdateDto{
Description: "Locally managed description",
AccessTokenDurationMinutes: model.DefaultAccessTokenDurationMinutes,
RefreshTokenDurationMinutes: model.DefaultRefreshTokenDurationMinutes,
}
_, err = s.UpdateClient(t.Context(), client.ID, input)
require.NoError(t, err)