This is a big chunk of the OIDC feature's business logic. A new IFederatedCredentialEvaluator is added which takes a list of federated credential policies and a bearer token and evaluates which trust policy, if any matches the given bearer token.
This is a read-only operation. The creation of the short-lived API key will be performed at a higher level.
There are two main parts of the logic.
First, find the issuer of the bearer token and validate it using the appropriate, issuer-specific validation routine. This step can be summarized as "Is this a valid token, issued by an expected issuer?". This is done no matter the policies provided. to reduce the amount of information leaked about policies in our DB.
Second, if the token is valid, the code checks the claims in the token against the given polices. For the short term, this is checking if the tid and oid claims in a policy match the token.
For a future phase where we accept GitHub Actions tokens, the first step will be enhanced with GitHub OIDC signature validation and step 2 will validate against some expected build context provided by the user (e.g. is the token coming from an expected repository and branch). This is not part of the PR but I wanted to give a taste for how this code will expand in the future as we federate with more IdPs.
The returned EvaluatedFederatedCredentialPolicies is the result pattern because there are several error modes that should be handled differently, but gracefully. This is opposed to throwing different flavored exceptions, Generally, there is "bad token", "no matching policy", and "matching policy". The "bad token" state shows a helpful error message because it is unrelated to any specific policy. This eases debugging for the user. The "unauthorized" state will not show a detailed error message because we don't want to leak information about what policies the user has or doesn't have.
The caller of this new method will fetch the policies for a given user and call this method to find a matching policy if any.
Progress on https://github.com/NuGet/NuGetGallery/issues/10212. Depends on https://github.com/NuGet/NuGetGallery/pull/10268.
This is a big chunk of the OIDC feature's business logic. A new
IFederatedCredentialEvaluator
is added which takes a list of federated credential policies and a bearer token and evaluates which trust policy, if any matches the given bearer token.This is a read-only operation. The creation of the short-lived API key will be performed at a higher level.
There are two main parts of the logic.
First, find the issuer of the bearer token and validate it using the appropriate, issuer-specific validation routine. This step can be summarized as "Is this a valid token, issued by an expected issuer?". This is done no matter the policies provided. to reduce the amount of information leaked about policies in our DB.
Second, if the token is valid, the code checks the claims in the token against the given polices. For the short term, this is checking if the
tid
andoid
claims in a policy match the token.For a future phase where we accept GitHub Actions tokens, the first step will be enhanced with GitHub OIDC signature validation and step 2 will validate against some expected build context provided by the user (e.g. is the token coming from an expected repository and branch). This is not part of the PR but I wanted to give a taste for how this code will expand in the future as we federate with more IdPs.
The returned
EvaluatedFederatedCredentialPolicies
is the result pattern because there are several error modes that should be handled differently, but gracefully. This is opposed to throwing different flavored exceptions, Generally, there is "bad token", "no matching policy", and "matching policy". The "bad token" state shows a helpful error message because it is unrelated to any specific policy. This eases debugging for the user. The "unauthorized" state will not show a detailed error message because we don't want to leak information about what policies the user has or doesn't have.The caller of this new method will fetch the policies for a given user and call this method to find a matching policy if any.