Ownership-Based Authorization
The Ed-Fi API primarily uses relationship-based authorization strategies based on education organizations. Ownership-based authorization adds an optional, additional level of authorization for scenarios that need more granular access control. Refer to API Claim Sets & Resources for details on the available authorization strategies. This page covers the essentials for platform hosts to set up and manage ownership-based authorization.
How Ownership-Based Authorization Works
Each record the Ed-Fi API stores can carry the ownership token of the API client that created it. Each API client can have:
- A creator token, which is stamped on every record the client creates. The creator token is optional: records created by a client without one have no ownership token. See Records Without an Owner.
- A list of ownership tokens, which identifies the records the client
"owns" and can read and change under the
OwnershipBasedauthorization strategy.
When a claim set uses the OwnershipBased strategy for a resource and action,
the Ed-Fi API allows a request only if the record's ownership token is in the
API client's list of ownership tokens. For collection requests, records owned by
others are left out of the results.
Ownership-based authorization is typically used in conjunction with
relationship-based authorization, for example where students from several LEAs
attend the same private school for special education services. When both are
configured for a resource and action, both must pass: relationship-based
strategies are combined with each other using OR, and the OwnershipBased
strategy is combined with them using AND. The relationship check confirms that
the caller's education organization has a path to the record, and the ownership
check then limits access to the records the caller owns.
Unlike the Ed-Fi ODS/API, Ed-Fi API v8 has no feature flag and needs no extra
database scripts for ownership-based authorization. Every record created by an
API client with a creator token is stamped with that token, whether or not any
claim set uses the OwnershipBased strategy.
The steps to set up ownership-based authorization are:
- Set up security metadata so that a claim
set uses the
OwnershipBasedstrategy. - Configure the API clients with ownership tokens.
- Verify the setup.
Setting up Security Metadata
Add the OwnershipBased strategy to the resource claims and actions it should
apply to, usually as a claim set authorization strategy override alongside the
relationship-based strategy. For example, to let several vendors read each
other's data but allow only the creator to update or delete it, override the
Update and Delete actions for the vendors' claim set with both
RelationshipsWithEdOrgsAndPeople and OwnershipBased. See Claim Set
Authorization Strategy
Overrides
for the full example.
Assign the claim set to the applications whose API clients should be authorized this way.
Configuring the API Clients
Ownership tokens are managed through the Configuration Service API. Requests
need a Configuration Service bearer token: write operations require the
edfi_admin_api/full_access scope, and GET operations also accept
edfi_admin_api/readonly_access. See Runtime Upload via Configuration
Service
for an example of obtaining a token.
In a multi-tenant deployment, tokens belong to a tenant and can only be
assigned to API clients in the same tenant. Every request must include the
Tenant header
with the tenant name, for example Tenant: tenant1. Requests without it fail
with 400 Bad Request.
-
Create an ownership token for each API client, or for each group of API clients that should share ownership, with
POST /v3/ownershipTokens/. The201 Createdresponse body includes the new token'sidanddescription.{"description": "Vendor A ownership token"}The description is required and can be up to 50 characters long.
-
Assign the tokens to the API client with
PUT /v3/apiClients/{id}/ownership, which replaces the client's ownership configuration:{"apiClientId": 5,"creatorOwnershipTokenId": 1,"ownershipTokenIds": [1]}apiClientIdmust equal the{id}in the URL.creatorOwnershipTokenIdis the token stamped on records the client creates.ownershipTokenIdslists the tokens of the records the client can access, up to 1,999 tokens.
Every token must exist in the API client's tenant. If any token doesn't exist or belongs to another tenant, the request fails with
409 Conflictand the client's previous configuration is kept.
The creator token isn't added to ownershipTokenIds automatically. Include it
in ownershipTokenIds if the API client needs to access its records through
actions that use the OwnershipBased strategy.
When the Create action itself uses the OwnershipBased strategy, the API client
also needs a correctly configured creator token to create records:
- If the client has no creator token, creates are denied with the
ownership-uninitializedtype. - If its creator token isn't in its
ownershipTokenIds, creates are denied with theownership-mismatchtype.
To see an API client's current configuration, use
GET /v3/apiClients/{id}/ownership. Ownership tokens can be listed with
GET /v3/ownershipTokens/ and renamed with PUT /v3/ownershipTokens/{id},
whose body must include the token's id, matching the URL, as well as its
description. There is no endpoint to delete an ownership token.
The 1,999-token limit is enforced by the Configuration Service. The Ed-Fi API
also checks it: if an API client somehow has 2,000 or more tokens, for example
because the Configuration Service database was changed directly, the Ed-Fi API
rejects the client's configuration and all of its requests fail with
503 Service Unavailable, whether or not they use the OwnershipBased
strategy.
When Changes Take Effect
The Ed-Fi API caches each API client's ownership configuration for the period
set by CacheSettings:ApplicationContextCacheExpirationSeconds, which defaults
to 600 seconds (10 minutes). A change to an API client's tokens can take that
long to take effect. Restarting the Ed-Fi API applies it immediately.
Transferring Ownership to Another API Client
Records don't need to change when another API client takes over from the one that created them, for example when a district replaces a vendor. To hand over the records:
-
Give the new client the previous client's tokens. Because
PUT /v3/apiClients/{id}/ownershipreplaces the whole configuration, the new client'sownershipTokenIdsmust list both its existing tokens and the previous client's tokens. Sending only the previous client's tokens removes the new client's own. To have the new client keep stamping the same token on new records, also set it as the new client'screatorOwnershipTokenId. -
Retire the previous client. Delete it with
DELETE /v3/apiClients/{id}. To keep the client but remove its access through actions that use theOwnershipBasedstrategy, update its ownership with an emptyownershipTokenIdslist and nocreatorOwnershipTokenId:{"apiClientId": 4,"ownershipTokenIds": []}The client can still access the records through actions that use other strategies. Records it creates afterward have no owner, and if the Create action uses the
OwnershipBasedstrategy, its creates are denied with theownership-uninitializedtype. -
Wait for the change to take effect. The previous client can keep accessing the records for as long as the Ed-Fi API caches its configuration. See When Changes Take Effect. Don't treat the handover as complete until the cache period has passed or the Ed-Fi API has been restarted.
Records Without an Owner
A record is stamped only if its creator had a creator token at the time it was
created. Records created by an API client without a creator token have no owner,
and can never be accessed through the OwnershipBased strategy. A request for
such a record gets a 403 Forbidden response, and collection requests leave it
out.
Assign creator tokens to API clients before they load data that ownership-based authorization should apply to. The Ed-Fi API doesn't assign owners to existing records.
Ownership-based authorization applies to descriptors in the same way as to other resources.
Verifying a Successful Setup
To verify the setup, use Swagger UI or another API client to request records
under a resource and action that use the OwnershipBased strategy. Use a
caller that passes the other authorization strategies for the resource and
action, such as the relationship-based and namespace-based checks. Otherwise,
the request can be denied by one of those strategies, and the response won't
show the ownership error types below.
- A
GETrequest for a single record that the caller owns returns200 OK. - A
GETrequest for a single record that the caller doesn't own returns403 Forbiddenwith the typeurn:ed-fi:api:security:authorization:ownership:access-denied:ownership-mismatch. - A record with no owner returns
403 Forbiddenwith the typeurn:ed-fi:api:security:authorization:ownership:invalid-data:ownership-uninitialized. The same type is returned when a client without a creator token tries to create a record and the Create action uses theOwnershipBasedstrategy. - A collection
GETrequest returns only the records the caller owns.
Technical Details
The Configuration Service database stores the ownership tokens and their assignment to API clients:
In the Ed-Fi API database, each record's ownership token is stored in the
CreatedByOwnershipTokenId column of dms.Document. The Ed-Fi API reads an API
client's tokens from the Configuration Service; they aren't included in the
client's access token.