You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bind database policy claims as typed OData constants (#3756)
## Why make this change?
Closes#3755
## What is this change?
- Replaces claim references in database policies with inert OData
parameter aliases.
- Keeps claim values separate from policy text in a
`ResolvedDatabasePolicy`.
- Injects claim values into the parsed OData AST as typed `ConstantNode`
values before operand type promotion.
- Converts supported primitive claim types to CLR values using invariant
parsing and fails closed when a claim does not match its declared type.
- Continues using database parameters for SQL predicates and now
parameterizes Cosmos DB policy constants instead of inlining them.
- Preserves legitimate claim values containing apostrophes, percent
characters, or encoded text without decoding or rewriting them.
Database policy resolution now returns a `ResolvedDatabasePolicy` rather
than a string. This keeps trusted OData policy syntax separate from
untrusted claim values: the policy contains inert aliases, while typed
values are carried independently and bound during OData AST processing.
This prevents URI decoding or escaping behavior from turning claim data
into policy syntax.
Relevant specification:
- [OData 4.01 URL Conventions: Parameter
Aliases](https://docs.oasis-open.org/odata/odata/v4.01/cs02/part2-url-conventions/odata-v4.01-cs02-part2-url-conventions.html#sec_ParameterAliases)
```mermaid
flowchart TD
A["Trusted configured policy<br/>@item.ownerId eq @claims.userId"]
B["Untrusted authenticated claim<br/>alice%27 or 1 eq 1 or %27"]
A --> C["AuthorizationResolver"]
B --> C
C --> D["ResolvedDatabasePolicy"]
D --> E["Policy:<br/>ownerId eq @dabClaim0"]
D --> F["ClaimValues:<br/>@dabClaim0 maps to raw CLR string"]
E --> G["ODataParser"]
F --> H["ConstantNode map"]
H --> G
G --> I["ClaimsTypeDataUriResolver<br/>Resolves aliases before type promotion"]
I --> J["ParameterAliasRewriter<br/>Resolves remaining aliases and Boolean contexts"]
J --> K["Typed FilterClause AST"]
K --> L["ODataASTVisitor"]
K --> M["ODataASTCosmosVisitor"]
L --> N["SQL predicate and provider parameters"]
M --> O["Cosmos SQL predicate and provider parameters"]
```
## How was this tested?
- [x] Integration Tests
- [x] Unit Tests
Focused unit-test coverage includes:
- Literal apostrophes in string claims.
- Percent-encoded text.
- Double-encoded and mixed-encoded text.
- Legitimate percent characters.
- Typed boolean, integer, floating-point, and null claims.
- Malformed primitive claims failing closed.
- Cosmos DB policy constants being emitted as query parameters.
Integration tests use an authenticated REST test in FindApiTestBase, so
it will run against MSSQL, PGSQL, MySQL, and DWSQL, along with a cosmos
specific authenticated GQL integration test.
## Sample Request(s)
No client-facing request contract changes are introduced.
Example database policy:
@item.ownerId eq @claims.userId
Example request:
GET /api/Note
Authorization: Bearer <token-with-userId-claim>
X-MS-API-ROLE: authenticated
A legitimate claim such as `O'Brien` or `50% complete` is preserved
exactly and bound as a database parameter. It is never inserted into or
reinterpreted as OData policy syntax.
0 commit comments