Project: CyberArk Conjur (Provisioning / Key Management)
File: aud_claim_support.md

+ + + + + + - |Link | |-| | | | | | | According the claim: The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected. In the general case, the "aud" value is an array of case- sensitive strings, each containing a StringOrURI value. In the special case when the JWT has one audience, the "aud" value MAY be a single case-sensitive string containing a StringOrURI value. The interpretation of audience values is generally application specific. Use of this claim is OPTIONAL. At the moment `authn-jwt` supports only a "special case" means `aud` can be a single string value defined using host's annotation. Our goal is to support general case when "aud" is an array. There are two possible solutions for the issue: Keep `aud` as a host annotation and to check that annotation value is in the claim value array Proc: Non breaking change for sure Introduces general `includes` check for annotations and array claims Extra Small EE (1) Cons: Bad UX - as far as `aud` defines possible recipients of the token it very likely that it will be the same value for all hosts of the same authenticator service id Bad security - as far as `aud` defines possible recipients of the token it's recommended to control its value at authenticator level rather at the host one We already know that its wrong direction. Following this way will require future behaviour change means it will happen never. Remarks: `aud` can be enforced and can be mapped Define `aud` as an authenticator variable `audience` Proc: Better UX - `aud` value will be defined once for each authenticator service Better security - `aud` value is controlled in centralized way A step to right direction. Later or sooner `aud` will became a part of authenticator configuration Cons: Small EE (3) May be a breaking change (may be not) see Backward compatibility section Remark: `aud` can not be enforced and mapped as `iss` `aud` behaves as mandatory once the variable exists Limitations: `audience` variable supports single value Chosen option: Option 2 - `audience` variable at authenticator level Conjur admin or other person is able to define jwt authenticator will load authenticator policy like: ```yaml !policy id: conjur/authn-jwt/serviceId body: !webservice !variable id: token-app-property !variable id: audience ``` `token-app-property` and `audience` variables are populated. Let's assume, for example, that `audience` value is `conjur`. Once `audiece` variable exists each JWT should contain `conjur` value as the `aud` claim value or in `aud` claim array and `aud` claim is mandatory in the token. All changes are under `app/domain/authentication/authnjwt/restrictionvalidators` path. Add new class `ValidateIncludesRestriction` that will validate that restriction value (came from annotation) includes into an array fetched from

Modify `ValidateRestrictionsOneToOne` class to refer a type of fetched restriction: If the type is an array - call `ValidateIncludesRestriction` validate function. Otherwise call default `=` (equals) statement. The solution is general for all array typed claims in the token. Changes under `app/domain/authentication/authnjwt/validateand_decode` path. Add new class `FetchAudienceValue` that will fetch and check the value if exists. Change `FetchJwtClaimsToValidate` class to treat `aud` as mandatory claim if the variable exists. Change `GetVerificationOptionByJwtClaim` class to support verification options for `aud` that will be validated by 3rd party (exactly like issuer). Changes under `app/domain/authentication/authn_jwt` path. Change `ValidateStatus` class to depend and call `FetchAudienceValue`. `FetchAudienceValue` fetches and validates value of `audience` variable. If variable does not exists returns nothing. If variable is defined but not populated throws an error. If variable is defined and populated but has an invalid value throws an exception. Validation criteria are: non empty string `FetchJwtClaimsToValidate` calls `FetchAudienceValue` If value is not empty: Add `aud` to mandatory claims list Add claim and it's value to claims to validate list `GetVerificationOptionByJwtClaim` for `aud` claim return the next verification options `{ aud: claimvalue, verifyaud: true }` `ValidateStatus` calls `FetchAudienceValue` during status verification In general it's interesting question what's effect of each variable on authenticator's performance The solution is backward compatible. Array is not supported either way today. The solution is backward compatible. Array is not supported either way today. We don't need to take any additional action: like today we're not preventing from user to create `exp`, `iss` and etc. annotations. `aud` claim can not be enforced and can not be mapped. In gcp `aud` is working as `token-app-property`. The design does not break this functionality if we will want to use `authn-jwt` instead of `authn-gcp` Conjur Open Source/Enterprise Conjur Open Source `audience` variable is defined in the authenitcator policy | Audience value | JWT | Result | |--|--|--| | Aud is empty | Does not matter | 401 | | Aud has a valid value | No `aud` | 401 | | Aud has a valid value | `aud` has different single value | 401 | | Aud has a valid value | `aud` has the same single value | 200 | | Aud has a valid value | `aud` is an array without the value | 401 | | Aud has a valid value | `aud` is an array with the value | 200 | | Audience value | Result | |--|--| | Aud is empty | Error | | Aud has a valid value | 200 | | Scenario | Log message | |--|--| | FetchJwtClaimsToValidate | "Fetching `audience` value" | | FetchJwtClaimsToValidate | "Fetched `audience` value {value}" | TBD Solution designed is approved Test plan is reviewed Acceptance criteria have been met Tests are implemented according to test plan The behaviour is documented in Conjur Open Source and Enterprise All relevant components are released | Persona | Name | |--|-| | Team leader | | | Product owner | | | System architect | | | Security architect | | | QA architect | |