Sandor Molnar created KNOX-3529:
-----------------------------------
Summary: Count the per-user token limit separately for each token
type
Key: KNOX-3529
URL: https://issues.apache.org/jira/browse/KNOX-3529
Project: Apache Knox
Issue Type: Improvement
Components: JWT, Server
Affects Versions: 3.0.0, 2.1.0, 2.0.0
Reporter: Sandor Molnar
Assignee: Sandor Molnar
Fix For: 3.1.0
h3. Problem
The per-user token limit ({{knox.token.limit.per.user}}) currently counts every
token stored for a user, regardless of type, except KnoxSSO cookies
({{TokenResource#enforceTokenLimitsAsRequired}}). The token state service is
shared across the whole gateway, so tokens issued by one service (or topology)
count against the limits of all the others.
This causes trouble when a client uses one token type to get another. Example:
- Topology A runs the {{CLIENTID}} service with
{{clientid.knox.token.limit.per.user=100}}. A user creates 10 client
credentials there.
- Topology B runs the {{KNOXTOKEN}} service with
{{knox.token.limit.per.user=150}}. A client exchanges those credentials for
access tokens via {{/oauth/v1/token}}.
- Topology B can mint only 140 access tokens, because the 10 client credentials
count against its limit too. API keys owned by the same user reduce it further.
- With {{knox.token.user.limit.exceeded.action=REMOVE_OLDEST}} it's worse: the
oldest tokens are usually the long-lived client credentials or API keys, so
minting an access token revokes the credential that was used to get it.
Client credentials and API keys are long-lived credentials. Access tokens
issued by {{KNOXTOKEN}} are usually short-lived. Counting them together means
neither limit means what an admin expects.
h3. Proposal
Count tokens only against the limit for their own type. Every stored token
already records its type ({{TokenMetadata.TYPE}}: {{JWT}}, {{CLIENT_ID}},
{{API_KEY}}, {{KNOXSSO_COOKIE}}, ...), and
{{TokenStateService#getTokens(userName)}} already returns that metadata, so no
storage change is needed.
* {{TokenResource}} gets a hook that returns the token types its limit counts.
The default is everything except {{KNOXSSO_COOKIE}}, {{CLIENT_ID}} and
{{API_KEY}} (so {{JWT}}, {{AUTH_CODE}} and {{REFRESH_TOKEN}}).
- {{ClientCredentialsResource}} counts only {{CLIENT_ID}} tokens, and
{{APIKeyResource}} counts only {{API_KEY}} tokens.
- {{enforceTokenLimitsAsRequired}} filters the user's tokens by that hook
before comparing against the limit. {{REMOVE_OLDEST}} then revokes the oldest
token of the same type only.
- Tokens with no {{TYPE}} metadata (stored by older versions) are treated as
{{JWT}}.
This changes what the limit means, so it should be opt-in through a new service
parameter that keeps today's behavior by default:
{code:xml}
<param>
<name>knox.token.limit.per.user.by.type</name>
<value>true</value>
</param>
{code}
h3. KnoxIDF tokens
KnoxIDF auth codes ({{AUTH_CODE}}) and refresh tokens ({{REFRESH_TOKEN}}) stay
in the default count, together with {{JWT}}. They are short-lived and deleted
on use (auth codes are consumed on redemption, refresh tokens on rotation), so
they don't build up the way long-lived client credentials and API keys do.
Excluding them would also leave them with no per-user limit at all.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)