Skip to content

Conversation

@seantleonard
Copy link
Contributor

@seantleonard seantleonard commented Oct 20, 2022

Why This Change

Closes #844

When a request reaches the policy processing stage of authorization, the request fails when a mismatch exists between the claim value type present in the access token and the field value type on the database object referenced in an authorization policy.

Example

Given the database authorization policy:

"policy": {
  "database": "@claims.SeriesId eq @item.series_id"
}

Given the access token payload where the claim 'SeriesId' has a value type of string:

{  
  "claims": [{
    "typ": "SeriesId",
    "val": "10000"
  }]
}

and given the database object field's value type referenced by the policy text @item.series_id is integer.

A HTTP 400 Bad Request error is return with the message
A binary operator with incompatible types was detected. Found operand types 'Edm.String' and 'Edm.Int32' for operator kind 'Equal'.

What is this change?

For authorization policy processing only, this change introduces a custom ODataUriParser extension Microsoft Dev Blog Example which attempts to typecast the value present in the access token claim to the type of the database(EDM model) object field, prior to OData filter parsing. The custom extension attempts to match the database type because the predicate, added to the database query as a result of processing an authorization policy, should utilize the correct value type or the query will fail.

Cases:

  1. Developer writes policy where token claim is compared to various database fields of various types. We must attempt to cast to the matching value type when performing directive replacement in the database policy string.
  • token: RoomID (string) => database: RoomID (int)
  • token: RoomID (string) => database: ClassRoomNumber (string)
  1. Developer writes policy where a token claim fails casting to database field value type.
    token: IsAdmin (bool) => database: IsAdmin (integer)

JSON data types covered in this change via http://json-schema.org/understanding-json-schema/reference/type.html

  • string
  • number
  • integer
  • object
  • array
  • boolean
  • null

When a claim fails typecasting to the database field value type, the request will still fail with (tbd which one)

  • HTTP 400 Bad Request - technically this is a bad request, but the user can't change an access token's claim value types.
  • HTTP 403 Forbidden - User can't change request params, it is up to token issue to update claim value type. Authorization fails.

How is this tested?

  • Added integration tests (which utilize config file, not full request pipeline) to test how new custom resolver handles type conversions for authorization policies.

Sample Request(s)

  • REST Request
    Modify Authentication config to be Static Web Apps:
      "authentication": {
        "provider": "StaticWebApps"
      }

Modify Book entity config to contain a new role

"permissions": [
        {
          "role": "swa-claims-valuetype",
          "actions": [
            "create",
            {
              "action": "read",
              "fields": {
                "include": [ "*" ]
              },
              "policy": {
                "database": "@item.publisher_id eq @claims.pubID"
              }
            },
            "delete"
          ]
        }
]

In Postman create a GET request for URL: https://localhost:5001/api/Book
Set Headers:
X-MS-CLIENT-PRINCIPAL:

eyAgCiAgImlkZW50aXR5UHJvdmlkZXIiOiAidGVzdCIsCiAgInVzZXJJZCI6ICIxMjM0NSIsCiAgInVzZXJEZXRhaWxzIjogImpvaG5AY29udG9zby5jb20iLAogICJ1c2VyUm9sZXMiOiBbInN3YS1jbGFpbXMtdmFsdWV0eXBlIl0sCiAgImNsYWltcyI6IFt7CiAgICAidHlwIjogInB1YklEIiwKICAgICJ2YWwiOiAiMTIzNCIKICB9XQp9

X-MS-API-ROLE: swa-claims-valuetype

Expected Result is the following (not HTTP 400) because @claims.pubID is now casted to an int type to match
the value type of @item.publisher_id.

{
    "value": [
        {
            "id": 1,
            "title": "Awesome book",
            "publisher_id": 1234
        },
        {
            "id": 2,
            "title": "Also Awesome book",
            "publisher_id": 1234
        }
    ]
}

@seantleonard seantleonard requested a review from jarupatj October 20, 2022 22:05
@seantleonard
Copy link
Contributor Author

Added tests.

Copy link
Collaborator

@Aniruddh25 Aniruddh25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after potentially avoiding reparsing

@seantleonard seantleonard enabled auto-merge (squash) October 28, 2022 20:22
@seantleonard seantleonard merged commit 9145395 into main Oct 28, 2022
@seantleonard seantleonard deleted the dev/seleonar/policyClaimTypeCasting branch October 28, 2022 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error "A binary operator with incompatible types was detected." when evaluating policies

4 participants