mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 11:04:25 +00:00
fix(oidc): return clients without instance settings (#7036)
This commit is contained in:
parent
fb235d7ea1
commit
2e505f40f9
@ -927,6 +927,12 @@ func (s *Server) VerifyClient(ctx context.Context, r *op.Request[op.ClientCreden
|
|||||||
if client.State != domain.AppStateActive {
|
if client.State != domain.AppStateActive {
|
||||||
return nil, oidc.ErrInvalidClient().WithDescription("client is not active")
|
return nil, oidc.ErrInvalidClient().WithDescription("client is not active")
|
||||||
}
|
}
|
||||||
|
if client.Settings == nil {
|
||||||
|
client.Settings = &query.OIDCSettings{
|
||||||
|
AccessTokenLifetime: s.defaultAccessTokenLifetime,
|
||||||
|
IdTokenLifetime: s.defaultIdTokenLifetime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch client.AuthMethodType {
|
switch client.AuthMethodType {
|
||||||
case domain.OIDCAuthMethodTypeBasic, domain.OIDCAuthMethodTypePost:
|
case domain.OIDCAuthMethodTypeBasic, domain.OIDCAuthMethodTypePost:
|
||||||
|
@ -92,11 +92,11 @@ func (c *Client) RestrictAdditionalAccessTokenScopes() func(scopes []string) []s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AccessTokenLifetime() time.Duration {
|
func (c *Client) AccessTokenLifetime() time.Duration {
|
||||||
return c.client.AccessTokenLifetime
|
return c.client.Settings.AccessTokenLifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) IDTokenLifetime() time.Duration {
|
func (c *Client) IDTokenLifetime() time.Duration {
|
||||||
return c.client.IDTokenLifetime
|
return c.client.Settings.IdTokenLifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AccessTokenType() op.AccessTokenType {
|
func (c *Client) AccessTokenType() op.AccessTokenType {
|
||||||
|
@ -122,19 +122,21 @@ func NewServer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
server := &Server{
|
server := &Server{
|
||||||
LegacyServer: op.NewLegacyServer(provider, endpoints(config.CustomEndpoints)),
|
LegacyServer: op.NewLegacyServer(provider, endpoints(config.CustomEndpoints)),
|
||||||
features: config.Features,
|
features: config.Features,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
query: query,
|
query: query,
|
||||||
command: command,
|
command: command,
|
||||||
keySet: newKeySet(context.TODO(), time.Hour, query.GetActivePublicKeyByID),
|
keySet: newKeySet(context.TODO(), time.Hour, query.GetActivePublicKeyByID),
|
||||||
defaultLoginURL: fmt.Sprintf("%s%s?%s=", login.HandlerPrefix, login.EndpointLogin, login.QueryAuthRequestID),
|
defaultLoginURL: fmt.Sprintf("%s%s?%s=", login.HandlerPrefix, login.EndpointLogin, login.QueryAuthRequestID),
|
||||||
defaultLoginURLV2: config.DefaultLoginURLV2,
|
defaultLoginURLV2: config.DefaultLoginURLV2,
|
||||||
defaultLogoutURLV2: config.DefaultLogoutURLV2,
|
defaultLogoutURLV2: config.DefaultLogoutURLV2,
|
||||||
fallbackLogger: fallbackLogger,
|
defaultAccessTokenLifetime: config.DefaultAccessTokenLifetime,
|
||||||
hashAlg: crypto.NewBCrypt(10), // as we are only verifying in oidc, the cost is already part of the hash string and the config here is irrelevant.
|
defaultIdTokenLifetime: config.DefaultIdTokenLifetime,
|
||||||
signingKeyAlgorithm: config.SigningKeyAlgorithm,
|
fallbackLogger: fallbackLogger,
|
||||||
assetAPIPrefix: assets.AssetAPI(externalSecure),
|
hashAlg: crypto.NewBCrypt(10), // as we are only verifying in oidc, the cost is already part of the hash string and the config here is irrelevant.
|
||||||
|
signingKeyAlgorithm: config.SigningKeyAlgorithm,
|
||||||
|
assetAPIPrefix: assets.AssetAPI(externalSecure),
|
||||||
}
|
}
|
||||||
metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount}
|
metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount}
|
||||||
server.Handler = op.RegisterLegacyServer(server, op.WithHTTPMiddleware(
|
server.Handler = op.RegisterLegacyServer(server, op.WithHTTPMiddleware(
|
||||||
|
@ -3,6 +3,7 @@ package oidc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||||
@ -27,9 +28,11 @@ type Server struct {
|
|||||||
command *command.Commands
|
command *command.Commands
|
||||||
keySet *keySetCache
|
keySet *keySetCache
|
||||||
|
|
||||||
defaultLoginURL string
|
defaultLoginURL string
|
||||||
defaultLoginURLV2 string
|
defaultLoginURLV2 string
|
||||||
defaultLogoutURLV2 string
|
defaultLogoutURLV2 string
|
||||||
|
defaultAccessTokenLifetime time.Duration
|
||||||
|
defaultIdTokenLifetime time.Duration
|
||||||
|
|
||||||
fallbackLogger *slog.Logger
|
fallbackLogger *slog.Logger
|
||||||
hashAlg crypto.HashAlgorithm
|
hashAlg crypto.HashAlgorithm
|
||||||
|
@ -29,18 +29,18 @@ keys as (
|
|||||||
group by identifier
|
group by identifier
|
||||||
),
|
),
|
||||||
settings as (
|
settings as (
|
||||||
select instance_id, access_token_lifetime, id_token_lifetime
|
select instance_id, json_build_object('access_token_lifetime', access_token_lifetime, 'id_token_lifetime', id_token_lifetime) as settings
|
||||||
from projections.oidc_settings2
|
from projections.oidc_settings2
|
||||||
where aggregate_id = $1
|
where aggregate_id = $1
|
||||||
and instance_id = $1
|
and instance_id = $1
|
||||||
)
|
)
|
||||||
|
|
||||||
select row_to_json(r) as client from (
|
select row_to_json(r) as client from (
|
||||||
select c.*, r.project_role_keys, k.public_keys, s.access_token_lifetime, s.id_token_lifetime
|
select c.*, r.project_role_keys, k.public_keys, s.settings
|
||||||
from client c
|
from client c
|
||||||
left join roles r on r.project_id = c.project_id
|
left join roles r on r.project_id = c.project_id
|
||||||
left join keys k on k.client_id = c.client_id
|
left join keys k on k.client_id = c.client_id
|
||||||
join settings s on s.instance_id = s.instance_id
|
left join settings s on s.instance_id = s.instance_id
|
||||||
) r;
|
) r;
|
||||||
|
|
||||||
--execute q('230690539048009730', '236647088211951618@tests', true);
|
--execute q('230690539048009730', '236647088211951618@tests', true);
|
@ -37,8 +37,7 @@ type OIDCClient struct {
|
|||||||
PublicKeys map[string][]byte `json:"public_keys,omitempty"`
|
PublicKeys map[string][]byte `json:"public_keys,omitempty"`
|
||||||
ProjectID string `json:"project_id,omitempty"`
|
ProjectID string `json:"project_id,omitempty"`
|
||||||
ProjectRoleKeys []string `json:"project_role_keys,omitempty"`
|
ProjectRoleKeys []string `json:"project_role_keys,omitempty"`
|
||||||
AccessTokenLifetime time.Duration `json:"access_token_lifetime,omitempty"`
|
Settings *OIDCSettings `json:"settings,omitempty"`
|
||||||
IDTokenLifetime time.Duration `json:"id_token_lifetime,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed embed/oidc_client_by_id.sql
|
//go:embed embed/oidc_client_by_id.sql
|
||||||
|
@ -24,6 +24,8 @@ var (
|
|||||||
testdataOidcClientPublic string
|
testdataOidcClientPublic string
|
||||||
//go:embed testdata/oidc_client_secret.json
|
//go:embed testdata/oidc_client_secret.json
|
||||||
testdataOidcClientSecret string
|
testdataOidcClientSecret string
|
||||||
|
//go:embed testdata/oidc_client_no_settings.json
|
||||||
|
testdataOidcClientNoSettings string
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestQueries_GetOIDCClientByID(t *testing.T) {
|
func TestQueries_GetOIDCClientByID(t *testing.T) {
|
||||||
@ -81,8 +83,10 @@ low2kyJov38V4Uk2I8kuXpLcnrpw5Tio2ooiUE27b0vHZqBKOei9Uo88qCrn3EKx
|
|||||||
ProjectID: "236645808328409090",
|
ProjectID: "236645808328409090",
|
||||||
PublicKeys: map[string][]byte{"236647201860747266": []byte(pubkey)},
|
PublicKeys: map[string][]byte{"236647201860747266": []byte(pubkey)},
|
||||||
ProjectRoleKeys: []string{"role1", "role2"},
|
ProjectRoleKeys: []string{"role1", "role2"},
|
||||||
AccessTokenLifetime: 43200000000000,
|
Settings: &OIDCSettings{
|
||||||
IDTokenLifetime: 43200000000000,
|
AccessTokenLifetime: 43200000000000,
|
||||||
|
IdTokenLifetime: 43200000000000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -110,8 +114,10 @@ low2kyJov38V4Uk2I8kuXpLcnrpw5Tio2ooiUE27b0vHZqBKOei9Uo88qCrn3EKx
|
|||||||
PublicKeys: nil,
|
PublicKeys: nil,
|
||||||
ProjectID: "236645808328409090",
|
ProjectID: "236645808328409090",
|
||||||
ProjectRoleKeys: []string{"role1", "role2"},
|
ProjectRoleKeys: []string{"role1", "role2"},
|
||||||
AccessTokenLifetime: 43200000000000,
|
Settings: &OIDCSettings{
|
||||||
IDTokenLifetime: 43200000000000,
|
AccessTokenLifetime: 43200000000000,
|
||||||
|
IdTokenLifetime: 43200000000000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -143,8 +149,43 @@ low2kyJov38V4Uk2I8kuXpLcnrpw5Tio2ooiUE27b0vHZqBKOei9Uo88qCrn3EKx
|
|||||||
PublicKeys: nil,
|
PublicKeys: nil,
|
||||||
ProjectID: "236645808328409090",
|
ProjectID: "236645808328409090",
|
||||||
ProjectRoleKeys: []string{"role1", "role2"},
|
ProjectRoleKeys: []string{"role1", "role2"},
|
||||||
AccessTokenLifetime: 43200000000000,
|
Settings: &OIDCSettings{
|
||||||
IDTokenLifetime: 43200000000000,
|
AccessTokenLifetime: 43200000000000,
|
||||||
|
IdTokenLifetime: 43200000000000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no oidc settings",
|
||||||
|
mock: mockQuery(expQuery, cols, []driver.Value{testdataOidcClientNoSettings}, "instanceID", "clientID", true),
|
||||||
|
want: &OIDCClient{
|
||||||
|
InstanceID: "239520764275982338",
|
||||||
|
AppID: "239520764276441090",
|
||||||
|
State: domain.AppStateActive,
|
||||||
|
ClientID: "239520764779364354@zitadel",
|
||||||
|
ClientSecret: nil,
|
||||||
|
RedirectURIs: []string{
|
||||||
|
"http://test2-qucuh5.localhost:9000/ui/console/auth/callback",
|
||||||
|
"http://test.localhost.com:9000/ui/console/auth/callback"},
|
||||||
|
ResponseTypes: []domain.OIDCResponseType{0},
|
||||||
|
GrantTypes: []domain.OIDCGrantType{0},
|
||||||
|
ApplicationType: domain.OIDCApplicationTypeUserAgent,
|
||||||
|
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||||
|
PostLogoutRedirectURIs: []string{
|
||||||
|
"http://test2-qucuh5.localhost:9000/ui/console/signedout",
|
||||||
|
"http://test.localhost.com:9000/ui/console/signedout",
|
||||||
|
},
|
||||||
|
IsDevMode: true,
|
||||||
|
AccessTokenType: domain.OIDCTokenTypeBearer,
|
||||||
|
AccessTokenRoleAssertion: false,
|
||||||
|
IDTokenRoleAssertion: false,
|
||||||
|
IDTokenUserinfoAssertion: false,
|
||||||
|
ClockSkew: 0,
|
||||||
|
AdditionalOrigins: nil,
|
||||||
|
PublicKeys: nil,
|
||||||
|
ProjectID: "239520764276178946",
|
||||||
|
ProjectRoleKeys: nil,
|
||||||
|
Settings: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -69,10 +69,10 @@ type OIDCSettings struct {
|
|||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
Sequence uint64
|
Sequence uint64
|
||||||
|
|
||||||
AccessTokenLifetime time.Duration
|
AccessTokenLifetime time.Duration `json:"access_token_lifetime,omitempty"`
|
||||||
IdTokenLifetime time.Duration
|
IdTokenLifetime time.Duration `json:"id_token_lifetime,omitempty"`
|
||||||
RefreshTokenIdleExpiration time.Duration
|
RefreshTokenIdleExpiration time.Duration `json:"refresh_token_idle_expiration,omitempty"`
|
||||||
RefreshTokenExpiration time.Duration
|
RefreshTokenExpiration time.Duration `json:"refresh_token_expiration,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) (settings *OIDCSettings, err error) {
|
func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) (settings *OIDCSettings, err error) {
|
||||||
|
6
internal/query/testdata/oidc_client_jwt.json
vendored
6
internal/query/testdata/oidc_client_jwt.json
vendored
@ -22,6 +22,8 @@
|
|||||||
"public_keys": {
|
"public_keys": {
|
||||||
"236647201860747266": "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFB\nT0NBUThBTUlJQkNnS0NBUUVBMnVmQUwxYjcyYkl5MWFyK1dzNmIKR29oSkpRRkI3ZGZSYXBEcWVx\nTThVa3A2Q1ZkUHpxL3BPejF2aUFxNTB5eldaSnJ5Risyd3NoRkFLR0Y5QTIvQgoyWWY5YkpYUFov\nS2JrRnJZVDNOVHZZRGt2bGFTVGw5bU1uenJVMjlzNDhGMVBUV0tmQitDM2FNc09FRzFCdWZWCnM2\nM3FGNG5yRVBqU2JobGpJY285RlpxNFhwcEl6aE1RMGZEZEEvK1h5Z0NKcXZ1YUwwTGliTTFLcmxV\nZG51NzEKWWVraFNKakVQbnZPaXNYSWs0SVh5d29HSU93dGp4a0R2Tkl0UXZhTVZsZHI0L2tiNnV2\nYmdkV3dxNUV3QlpYcQpsb3cya3lKb3YzOFY0VWsySThrdVhwTGNucnB3NVRpbzJvb2lVRTI3YjB2\nSFpxQktPZWk5VW84OHFDcm4zRUt4CjZRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0t\nLS0K"
|
"236647201860747266": "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFB\nT0NBUThBTUlJQkNnS0NBUUVBMnVmQUwxYjcyYkl5MWFyK1dzNmIKR29oSkpRRkI3ZGZSYXBEcWVx\nTThVa3A2Q1ZkUHpxL3BPejF2aUFxNTB5eldaSnJ5Risyd3NoRkFLR0Y5QTIvQgoyWWY5YkpYUFov\nS2JrRnJZVDNOVHZZRGt2bGFTVGw5bU1uenJVMjlzNDhGMVBUV0tmQitDM2FNc09FRzFCdWZWCnM2\nM3FGNG5yRVBqU2JobGpJY285RlpxNFhwcEl6aE1RMGZEZEEvK1h5Z0NKcXZ1YUwwTGliTTFLcmxV\nZG51NzEKWWVraFNKakVQbnZPaXNYSWs0SVh5d29HSU93dGp4a0R2Tkl0UXZhTVZsZHI0L2tiNnV2\nYmdkV3dxNUV3QlpYcQpsb3cya3lKb3YzOFY0VWsySThrdVhwTGNucnB3NVRpbzJvb2lVRTI3YjB2\nSFpxQktPZWk5VW84OHFDcm4zRUt4CjZRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0t\nLS0K"
|
||||||
},
|
},
|
||||||
"access_token_lifetime": 43200000000000,
|
"settings": {
|
||||||
"id_token_lifetime": 43200000000000
|
"access_token_lifetime": 43200000000000,
|
||||||
|
"id_token_lifetime": 43200000000000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
30
internal/query/testdata/oidc_client_no_settings.json
vendored
Normal file
30
internal/query/testdata/oidc_client_no_settings.json
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"instance_id": "239520764275982338",
|
||||||
|
"app_id": "239520764276441090",
|
||||||
|
"client_id": "239520764779364354@zitadel",
|
||||||
|
"client_secret": null,
|
||||||
|
"redirect_uris": [
|
||||||
|
"http://test2-qucuh5.localhost:9000/ui/console/auth/callback",
|
||||||
|
"http://test.localhost.com:9000/ui/console/auth/callback"
|
||||||
|
],
|
||||||
|
"response_types": [0],
|
||||||
|
"grant_types": [0],
|
||||||
|
"application_type": 1,
|
||||||
|
"auth_method_type": 2,
|
||||||
|
"post_logout_redirect_uris": [
|
||||||
|
"http://test2-qucuh5.localhost:9000/ui/console/signedout",
|
||||||
|
"http://test.localhost.com:9000/ui/console/signedout"
|
||||||
|
],
|
||||||
|
"is_dev_mode": true,
|
||||||
|
"access_token_type": 0,
|
||||||
|
"access_token_role_assertion": false,
|
||||||
|
"id_token_role_assertion": false,
|
||||||
|
"id_token_userinfo_assertion": false,
|
||||||
|
"clock_skew": 0,
|
||||||
|
"additional_origins": null,
|
||||||
|
"project_id": "239520764276178946",
|
||||||
|
"state": 1,
|
||||||
|
"project_role_keys": null,
|
||||||
|
"public_keys": null,
|
||||||
|
"settings": null
|
||||||
|
}
|
@ -20,6 +20,8 @@
|
|||||||
"state": 1,
|
"state": 1,
|
||||||
"project_role_keys": ["role1", "role2"],
|
"project_role_keys": ["role1", "role2"],
|
||||||
"public_keys": null,
|
"public_keys": null,
|
||||||
"access_token_lifetime": 43200000000000,
|
"settings": {
|
||||||
"id_token_lifetime": 43200000000000
|
"access_token_lifetime": 43200000000000,
|
||||||
|
"id_token_lifetime": 43200000000000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
"state": 1,
|
"state": 1,
|
||||||
"project_role_keys": ["role1", "role2"],
|
"project_role_keys": ["role1", "role2"],
|
||||||
"public_keys": null,
|
"public_keys": null,
|
||||||
"access_token_lifetime": 43200000000000,
|
"settings": {
|
||||||
"id_token_lifetime": 43200000000000
|
"access_token_lifetime": 43200000000000,
|
||||||
|
"id_token_lifetime": 43200000000000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user