mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-13 21:40:45 +00:00
perf(oidc): optimize the introspection endpoint (#6909)
* get key by id and cache them
* userinfo from events for v2 tokens
* improve keyset caching
* concurrent token and client checks
* client and project in single query
* logging and otel
* drop owner_removed column on apps and authN tables
* userinfo and project roles in go routines
* get oidc user info from projections and add actions
* add avatar URL
* some cleanup
* pull oidc work branch
* remove storage from server
* add config flag for experimental introspection
* legacy introspection flag
* drop owner_removed column on user projections
* drop owner_removed column on useer_metadata
* query userinfo unit test
* query introspection client test
* add user_grants to the userinfo query
* handle PAT scopes
* bring triggers back
* test instance keys query
* add userinfo unit tests
* unit test keys
* go mod tidy
* solve some bugs
* fix missing preferred login name
* do not run triggers in go routines, they seem to deadlock
* initialize the trigger handlers late with a sync.OnceValue
* Revert "do not run triggers in go routines, they seem to deadlock"
This reverts commit 2a03da2127.
* add missing translations
* chore: update go version for linting
* pin oidc version
* parse a global time location for query test
* fix linter complains
* upgrade go lint
* fix more linting issues
---------
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
23
internal/query/embed/introspection_client_by_id.sql
Normal file
23
internal/query/embed/introspection_client_by_id.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
with config as (
|
||||
select app_id, client_id, client_secret
|
||||
from projections.apps6_api_configs
|
||||
where instance_id = $1
|
||||
and client_id = $2
|
||||
union
|
||||
select app_id, client_id, client_secret
|
||||
from projections.apps6_oidc_configs
|
||||
where instance_id = $1
|
||||
and client_id = $2
|
||||
),
|
||||
keys as (
|
||||
select identifier as client_id, json_object_agg(id, encode(public_key, 'base64')) as public_keys
|
||||
from projections.authn_keys2
|
||||
where $3 = true -- when argument is false, don't waste time on trying to query for keys.
|
||||
and instance_id = $1
|
||||
and identifier = $2
|
||||
and expiration > current_timestamp
|
||||
group by identifier
|
||||
)
|
||||
select config.client_id, config.client_secret, apps.project_id, keys.public_keys from config
|
||||
join projections.apps6 apps on apps.id = config.app_id
|
||||
left join keys on keys.client_id = config.client_id;
|
||||
92
internal/query/embed/userinfo_by_id.sql
Normal file
92
internal/query/embed/userinfo_by_id.sql
Normal file
@@ -0,0 +1,92 @@
|
||||
-- deallocate q;
|
||||
-- prepare q (text, text, text[]) as
|
||||
|
||||
with usr as (
|
||||
select u.id, u.creation_date, u.change_date, u.sequence, u.state, u.resource_owner, u.username, n.login_name as preferred_login_name
|
||||
from projections.users9 u
|
||||
left join projections.login_names3 n on u.id = n.user_id and u.instance_id = n.instance_id
|
||||
where u.id = $1
|
||||
and u.instance_id = $2
|
||||
and n.is_primary = true
|
||||
),
|
||||
human as (
|
||||
select $1 as user_id, row_to_json(r) as human from (
|
||||
select first_name, last_name, nick_name, display_name, avatar_key, email, is_email_verified, phone, is_phone_verified
|
||||
from projections.users9_humans
|
||||
where user_id = $1
|
||||
and instance_id = $2
|
||||
) r
|
||||
),
|
||||
machine as (
|
||||
select $1 as user_id, row_to_json(r) as machine from (
|
||||
select name, description
|
||||
from projections.users9_machines
|
||||
where user_id = $1
|
||||
and instance_id = $2
|
||||
) r
|
||||
),
|
||||
-- find the user's metadata
|
||||
metadata as (
|
||||
select json_agg(row_to_json(r)) as metadata from (
|
||||
select creation_date, change_date, sequence, resource_owner, key, encode(value, 'base64') as value
|
||||
from projections.user_metadata5
|
||||
where user_id = $1
|
||||
and instance_id = $2
|
||||
) r
|
||||
),
|
||||
-- get all user grants, needed for the orgs query
|
||||
user_grants as (
|
||||
select id, grant_id, state, creation_date, change_date, sequence, user_id, roles, resource_owner, project_id
|
||||
from projections.user_grants3
|
||||
where user_id = $1
|
||||
and instance_id = $2
|
||||
and project_id = any($3)
|
||||
),
|
||||
-- filter all orgs we are interested in.
|
||||
orgs as (
|
||||
select id, name, primary_domain
|
||||
from projections.orgs1
|
||||
where id in (
|
||||
select resource_owner from user_grants
|
||||
union
|
||||
select resource_owner from usr
|
||||
)
|
||||
and instance_id = $2
|
||||
),
|
||||
-- find the user's org
|
||||
user_org as (
|
||||
select row_to_json(r) as organization from (
|
||||
select name, primary_domain
|
||||
from orgs o
|
||||
join usr u on o.id = u.resource_owner
|
||||
) r
|
||||
),
|
||||
-- join user grants to orgs, projects and user
|
||||
grants as (
|
||||
select json_agg(row_to_json(r)) as grants from (
|
||||
select g.*,
|
||||
o.name as org_name, o.primary_domain as org_primary_domain,
|
||||
p.name as project_name, u.resource_owner as user_resource_owner
|
||||
from user_grants g
|
||||
left join orgs o on o.id = g.resource_owner
|
||||
left join projections.projects4 p on p.id = g.project_id
|
||||
left join usr u on u.id = g.user_id
|
||||
where p.instance_id = $2
|
||||
) r
|
||||
)
|
||||
-- build the final result JSON
|
||||
select json_build_object(
|
||||
'user', (
|
||||
select row_to_json(r) as usr from (
|
||||
select u.*, h.human, m.machine
|
||||
from usr u
|
||||
left join human h on u.id = h.user_id
|
||||
left join machine m on u.id = m.user_id
|
||||
) r
|
||||
),
|
||||
'org', (select organization from user_org),
|
||||
'metadata', (select metadata from metadata),
|
||||
'user_grants', (select grants from grants)
|
||||
);
|
||||
|
||||
-- execute q('231965491734773762','230690539048009730', '{"236645808328409090","240762134579904514"}')
|
||||
Reference in New Issue
Block a user