mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Add claims design (#119)
This commit is contained in:
parent
5429f8a6c0
commit
764b96323c
159
designs/claims.rst
Normal file
159
designs/claims.rst
Normal file
|
@ -0,0 +1,159 @@
|
|||
Claims Design
|
||||
-------------
|
||||
|
||||
Claims are a way of associating privileges to sessions, to scope and limit access of an identity.
|
||||
This can be based on what credentials were used to authenticate, by the user requesting claims
|
||||
for a session, or by time limiting claims.
|
||||
|
||||
These tend to fall into three major categories
|
||||
|
||||
Default Interactive Claims
|
||||
--------------------------
|
||||
|
||||
When an identity authenticates they are given a set of claims associated to their interactive
|
||||
login. This could include the ability to trigger a claim request or to view personal details.
|
||||
|
||||
Static Application Claims (or lack of)
|
||||
--------------------------------------
|
||||
|
||||
Static application passwords (IE a device imap/smtp password) should have a claim to "email"
|
||||
but not to read personal data and shouldn't be able to change passwords etc.
|
||||
|
||||
Ephemeral Claims
|
||||
----------------
|
||||
|
||||
These are permissions that are limited in time - they *must* be requested and generally require
|
||||
re-authentication with a subset of credentials. This can include the ability to alter ones own
|
||||
account or time limiting admins ability to alter other accounts.
|
||||
|
||||
Detailed Design
|
||||
---------------
|
||||
|
||||
As a result of these scenarios this leads to the following required observations.
|
||||
|
||||
* Claims must be associated to the credentials of the account
|
||||
* Possible claims that could be assigned derive from membership to a group
|
||||
* Claims must be understood by access controls of the server
|
||||
* Claims must be present in user auth tokens for end applications to be able to verify
|
||||
* Two types of claims exist - ephemeral and static
|
||||
|
||||
This leads to a pseudo design such as:
|
||||
|
||||
name: claim_email
|
||||
claim_name: email
|
||||
member: account_1
|
||||
|
||||
name: claim_unused
|
||||
claim_name: unused
|
||||
|
||||
name: claim_interactive
|
||||
claim_name: interactive
|
||||
member: account_1
|
||||
|
||||
name: claim_alter_self
|
||||
claim_name: alter_self
|
||||
claim_lifetime: 300 # seconds
|
||||
member: account_1
|
||||
|
||||
name: account_1
|
||||
...
|
||||
primary_credential: {
|
||||
type: password|webauthn|password+webauthn
|
||||
claims: [ claim_alter_self, claim_interactive ]
|
||||
}
|
||||
application_credentialn: {
|
||||
name: iphone imap password
|
||||
type: generated_password
|
||||
claims: [ claim_email ]
|
||||
}
|
||||
|
||||
When we authenticate with the email password, because there is no lifetime this becomes a static
|
||||
claim:
|
||||
|
||||
UserAuthToken {
|
||||
name: account_1
|
||||
claims: [ email ]
|
||||
}
|
||||
|
||||
If we authenticate with the primary credential, the static claims are initially issued:
|
||||
|
||||
UserAuthToken {
|
||||
name; account_1
|
||||
claims: [ interactive ]
|
||||
}
|
||||
|
||||
To have the "alter_self" claim, we must perform an auth-request-claim operation which re-verifies
|
||||
a credential. This is a subset of the Auth operation
|
||||
|
||||
auth-request-claim ----> verify aci of request (are you interactive? )
|
||||
<---- return challenge
|
||||
send password/cred ----> verify credential
|
||||
<---- update UAT with ephemeral claim
|
||||
|
||||
Then the UserAuthToken would be:
|
||||
|
||||
UserAuthToken {
|
||||
name; account_1
|
||||
claims: [ interactive, alter_self(expire_at_time) ]
|
||||
}
|
||||
|
||||
This means:
|
||||
|
||||
* Consuming applications need to verify the claim list
|
||||
* They need te verify the claim's expiry times.
|
||||
|
||||
For kanidm, to use claims in access controls, these must become filterable elements. On
|
||||
UAT to Entry as part of the event conversion we will perform
|
||||
|
||||
load entry to member
|
||||
for each claim in UAT:
|
||||
if claim is not expired
|
||||
alter memory entry -> add claim
|
||||
|
||||
ACP's can then have filters such as:
|
||||
|
||||
Eq('claim', 'alter_self')
|
||||
|
||||
|
||||
Questions
|
||||
---------
|
||||
|
||||
We should only be able to request claims on interactive (primary) credential sessions. How should
|
||||
we mark this? I think the UAT needs to retain "what credential id" was used to authenticate, and then
|
||||
emit this to the entry so that it can also be filtered on to determine primary vs application cred.
|
||||
|
||||
Claim and other generated attrs must be system protected, even though they have to exist in schema
|
||||
for filter verification. This likely needs to be added to system_protected plugin to prevent claims
|
||||
from being added to any entry type.
|
||||
|
||||
Once a claim is dynamically added to the entry it must move to a new state that prevents reserialisation to the DB.
|
||||
|
||||
|
||||
Trust Considerations
|
||||
--------------------
|
||||
|
||||
Claims should not be replicated, and are auth-silo specific. This is because
|
||||
trusts as designed are about account and group sharing, rather than about detailed privilege or
|
||||
resource granting in the trusting domain.
|
||||
|
||||
Because claims should be associated to groups, we can also apply account pw policy to groups.
|
||||
|
||||
This means that at the very least we have to consider replication of credential metadata though
|
||||
so that the trusting domain can assign the claims somewhere (this metadata will be needed for
|
||||
account cred policy and group membership later anyway). For example:
|
||||
|
||||
spn: claire@domainb
|
||||
class: [trustedaccount, object]
|
||||
trustedcredential: [ name, id, claims ]
|
||||
|
||||
This way when the account authenticates to the trusting domain, because the credential ID that was
|
||||
used is in the UAT, this allows the trusting domain to inspect what credential was used, and to
|
||||
be able to assign it's domain local claims to the session. This could then have a similar work
|
||||
flow when ephemeral claims are needed.
|
||||
|
||||
mental note: because groups will define account policy, when a trusted account is a member of a group
|
||||
and it doesn't meet that groups account policy requirements, it should be listed in the uat as
|
||||
a rejected group so that we can easily diagnose when an account is insufficient to receive that group
|
||||
or that claim as a result. This may affect how we treat memberof on the session though when
|
||||
we do UAT to entry. An argument could be made to strip the memberofs when they are in the rejected
|
||||
list ...
|
Loading…
Reference in a new issue