wip: Multiple principals for a Subject #1317
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Related issue(s)
closes #921
Checklist
Background
In heimdall the term
Subject
is defined to represent the source of a request which is created upon successful authentication. This way, aSubject
may be any entity, such as a person, a service, or something else. Until now, aSubject
was represented by the following JSON schemawith
ID
being a unique identifier of the subject andAttributes
representing a dictionary of attributes related to the authenticated subject. These attributes could be for examples claims from a JWT used to authenticate the subject.This abstraction was enough for long time. But it has its drawbacks. In a real life a user wanting accessing an API, may use for example a laptop equipped with a client certificate from which the actual request is sent to the aforesaid API. It can be an IoT device, like e.g. a heating system, an end customer is using. It may even be an environment to which a user should authenticate first. In all these cases, we're actually talking about different and complementing authentication aspects related to the same request, but representing different entities (like a user and a device).
Reasoning, why not going for new authorizer types instead
It would simply lead to code bloating and potentially to a lot of duplication as for each authenticator, there would be a need for an authorizer doing the same thing.
Description
NOTE: This PR is in a very early stage. The text below describes the current ideas which might change over time (see also the history of this PR description) or during the implementation.
For the above said reasons, this PR introduces the following changes:
It refactors the
Subject
object to support multiplePrincipals
(the different entities mentioned above). That way theSubject
becomes an object holding the different authenticated principals, each having at least anID
andData
attributes. Starting with refactor!: Subject has been made immutable #1487 theSubject
object has been made immutable. This behavior applies to thePrinipal
objects as well.This way, a
Principal
is very similar to the oldSubject
and can be represented by the following JSON schema:The new
Subject
is then just an object in sense of a JSON object.With
<principal name ...>
being thePrincipal
entries representing theSubject
. Even it does not have anID
property any more, it has a newID()
andAttributes()
functions, which returns the theID
, respectively theAttributes
of thedefault
principal - the principal, which has been created by an authentication stage marked accordingly (see below).Since authenticators do now create principals and populate a Subject with them, the
subject
property of all authenticators have been renamed toprincipal
(BREAKING CHANGE).The semantics of the authentication stage have been updated. Previously, when multiple authenticators were specified, subsequent ones would only execute if the preceding authenticator either failed and allowed fallback (via the
allow_fallback_on_error
property set totrue
) or was not responsible for the provided authentication data in the request. However, sinceallow_fallback_on_error
pertains to pipeline behavior rather than authenticator behavior, this property has been removed from individual authenticators (BREAKING CHANGE).Instead, a new optional
group
property has been introduced at the authenticator step level. This property enables grouping multiple authenticators, with the semantics within a group being OR-based and between the groups AND-based. This means that exactly one authenticator in a group must succeed. Subsequent authenticators in the group are only executed if the preceding one was either not responsible or failed. The group's name determines the principal created by that group. Definition of multiple groups is possible as well, and if thegroup
property is not specified, the authenticator step defaults to the "default" group. Here some examples:group
is used here. This pipeline basically implements functionality, which is already possible todaySubject
will contain adefault
principal and adevice
principal similar to what is shown belowObviously, if groups are not defined, the behavior is exactly as it was before this PR.
All of that slightly affects how subject related data can be accessed. Here are two examples highlighting the differences.
Old
New
Examples
With that in place, one can now chain and combine multiple authentication mechanisms. Here examples for the implementation of the requirements described in #921.
Access to a staging environment. Only project members should be able to access the services (via e.g. a browser) to see and test the new deployed features. There is also an IAM in the staging environment itself which manages the "customers". So, the first IAM manages the access to the environment . The
X-Env-JWT
header certifies that the request has been routed through an authorized gateway (so access to the environment was legitimate). And the second IAM represents the actual users of the services deployed. Here, theAuthorization
header represents the user and describes its permissions through the scope claimwith the
jwt_env_authenticator
being configured to extract the token from theAuthorization
header and thejwt_user_authenticator
being configured to extract the token from theX-Env-JWT
header.This example indicates that the two mechanisms referenced in the above steps are pretty much the same. The only difference would be the configuration of the
jwt_source
, which extracts the token from different headers. this duplication is a tradeoff between simplicity in the rules and duplication in the config. Reconfiguration of thejwt_source
in a pipeline step was however never possible before. Opening it to the pipeline steps is possible, would however introduce a source for errors.Verification that the request came over a specific intermediary. Depending on the path the request took, the gateway issues an additional token, e.g. X-Caller-ID, which is then present in addition to the token in the Authorization header.
Current PR Status
In a very early stage. The changes implemented so far is the update of the
Subject
to let it be a map ofPrincipal
objects and have the code compilable.