How To: Use Custom View-Based Authorization
Create the Custom Authorization View in the ODS
First, identify the basis entity for your authorization. This is the entity whose primary key columns will be used to join to the subject entity (the entity being authorized). For this example, we’ll use the Student entity and the new authorization view will only include its primary key column – StudentUSI.
Next, review the Ed-Fi ODS database model and identify how best to write a query to apply the necessary criteria to meet the business requirements. For this example, we’ll filter the available Students based on their enrollment in a CTE (Career and Technical Education) course.
Finally, identify the name for the view, following the strict naming convention
for custom authorization views: {EntityName}With{HintPhrase}
. The first part of
the view name consists of the basis entity’s name (i.e. “Student” in this case).
The second part is the literal text “With”. This is case-sensitive and is used
to separate the entity name from the hint phrase to follow. The final part is a
title-cased “hint phrase”. When view-based authorization fails, the API returns
a “problem details” message in the response that includes a “hint” for the
consumer indicating ways to remedy the situation. The “Hint Phrase” part of the
name should be able to complete a sentence that starts with “You may need a
Student with…”.
CREATE OR ALTER VIEW auth.StudentWithCTECourseEnrollments
AS
SELECT DISTINCT StudentUSI
FROM edfi.StudentSectionAssociation ssa
INNER JOIN edfi.CourseOffering co
ON co.LocalCourseCode = ssa.LocalCourseCode
AND co.SchoolId = ssa.SchoolId
AND co.SchoolYear = ssa.SchoolYear
AND co.SessionName = ssa.SessionName
INNER JOIN edfi.CourseAcademicSubject csubj
ON csubj.CourseCode = co.CourseCode
AND csubj.EducationOrganizationId = co.EducationOrganizationId
INNER JOIN edfi.descriptor d
ON csubj.AcademicSubjectDescriptorId = d.descriptorid
WHERE d.Uri = 'uri://ed-fi.org/AcademicSubjectDescriptor#Career and Technical Education'
GO
Add Security Metadata to the Security Database
In custom view-based authorization (which introduces no new metadata due to design constraints), the authorization strategy name must match the view name. Create a script to add the new authorization strategy to the EdFi_Security database (or use another preferred approach):
INSERT INTO dbo.AuthorizationStrategies(DisplayName, AuthorizationStrategyName)
VALUES ('Students Enrolled in CTE courses', 'StudentWithCTECourseEnrollments')
Due to differences in how database engines handle casing of identifiers, the view name and authorization strategy only need to match in a case-insensitive manner.
Next, use the new authorization strategy for authorization of a resource claim on a claim set’s actions using your preferred approach.
The declarative XML snippet below follows the approach described in How To: Create and Manage API Security Metadata using Declarative Security Policies
and applies the new authorization strategy to the Student resource for API
clients assigned to the Ed-Fi Sandbox claim set. This XML can be transformed
into a database script using the transform.ps1
script located in the
SecurityMetadata folder of the Ed-Fi-Ods-Implementation repository:
.\transform.ps1 "C:\Temp\Scripts\MsSql\Students-with-CTE-enrollments-security-metadata.xml"
The transform.ps1
script also supports arguments for the output (SQL) file,
and the database engine (SqlServer or PostgreSQL), but it will default the
output filename to be co-located with the .xml
file and apply a .sql
extension, and it will auto select the appropriate target database if a MsSql
or PgSql
folder is found in the path.
<SecurityMetadata>
<Claims>
<Claim name="http://ed-fi.org/ods/identity/claims/domains/people">
<Claims>
<Claim name="http://ed-fi.org/ods/identity/claims/ed-fi/student">
<ClaimSets>
<ClaimSet name="Ed-Fi Sandbox">
<Actions>
<Action name="Create" />
<Action name="Read">
<AuthorizationStrategyOverrides>
<AuthorizationStrategy name="StudentWithCTECourseEnrollments" />
</AuthorizationStrategyOverrides>
</Action>
<Action name="Update">
<AuthorizationStrategyOverrides>
<AuthorizationStrategy name="StudentWithCTECourseEnrollments" />
</AuthorizationStrategyOverrides>
</Action>
<Action name="Delete" />
<Action name="ReadChanges" />
</Actions>
</ClaimSet>
</ClaimSets>
</Claim>
</Claims>
</Claim>
</Claims>
</SecurityMetadata>
Test the New Authorization Strategy
With the ODS view created and the security metadata defined to apply the
authorization strategy to an API client, review the behavior of the new
strategy. For this example, identify some students who are enrolled in a CTE
course and some who are not (hint: use a query with a LEFT JOIN
from
edfi.Student
to auth.StudentWithCTECourseEnrollments
). Then test the
following operations:
GET
all Student resource items and ensure all returned items are for students identified as having CTE course enrollments.GET
all Student resource item for a non-CTE enrolled student byid
. The operation should fail.GET
all Student resource item for a CTE enrolled student byid
. The operation should succeed.POST
a Student resource item for an existing non-CTE enrolled student. The operation should fail.POST
a Student resource item for an existing CTE enrolled student. The operation should succeed.
Since this approach is entirely based on security metadata and ODS database artifacts, the API does not need to be restarted after making the changes described above – the new authorization strategy will be recognized and applied after the next security metadata cache expiration in the API.