Part 2: OAuth Scopes May Not be Enough
This is a multi-part series of articles describing why and how one can approach applying Externalized Dynamic Authorization to an API and/or microservices architecture that uses OAuth 2.0 flows and/or OpenID Connect (OIDC). Externalized Dynamic Authorization and OAuth 2.0 (and/or OIDC) are complementary technologies. Some of the naming can lead to confusion however, on what roles each can and should play. The series is divided into multiple parts: This Primer provides some background of the standards involved in this series, including OAuth 2.0 (referred to as just OAuth from here on out) and OpenID Connect (OIDC). The eXtensible Access Control Markup Language (XACML) tutorial is available as well.
of this series will show some patterns of how Externalized Dynamic Authorization could be integrated within an OAuth or OpenID Connect (OIDC) flow.
will contrast OAuth scope-based authorization with Externalized Dynamic Authorization.
will discuss how Externalized Dynamic Authorization itself can be a microservice and best practices for leveraging the authorization service within the microservice architecture and its principles.
Let’s establish how one might provide authorization policies using OAuth scopes without a Externalized Dynamic Authorization solution. Let’s establish an example of an organization Example.com, that leverages multiple cloud benefits sites that are aggregated as part of its HR offering. CloudBenefits and SaaSRewards are two of the providers used by Example.com. Alice is an employee at Example.com and wishes to leverage these HR services. The benefits providers need her social security number (SSN) in order to evaluate whether the employee is eligible for certain government entitlements. The diagram below depicts and an API client from each provider. Note the PII (Personally Identifiable Information) label on the SSN field.
Example.com exposes their employee data to these benefits providers via a SCIM (System for Cross-Domain Identity Management) interface. For those that glaze over looking at JSON, just read the bold print.
The username (alice) is used as a key for retrieving attributes of the user. Metadata, including the PII tag, is returned in the response.
Example.com wants to give its employees the ability to opt-in or opt-out of letting benefits providers leverage certain HR attributes like Social Security Number. They have defined a set of scopes at the level of granularity of the APIs:
If an employee opts-out of any of these scopes, Example.com shall not return those attribute values to the cloud benefits providers. Employees would be given the option on the Cloud Benefits site on leg one of this three-legged, authorization code OAuth flow:
Once Alice approves of CloudBenefits of using her SSN, Example.com will issue an access token that acts as a key for the Resource Server to retrieve which scopes Alice has approved of and the Resource Server has the responsibility to enforce these scopes.
The provider may want to know what scopes are available, so that it can ask for specific scopes required for its application:
Most OAuth implementations will allow all scopes to be requested by default (the absence of asking for any one or more specific scopes), but there may be a significant number of scopes that the provider may not want employees to have to wade through. For this reason, scope definition tends to be static and changing design on the fly is not realistic, as it would require coordination with all of the consumers of that service. It’s not a matter of how granular scopes can be be, it’s just that the lifecycle of change and the dependencies make it unrealistic.
The diagram below shows the relation of the scope approvals by the employee Alice with the API Client, the Resource Server and the service.
Allowing the employees to determine what access the API client may have is a Discretionary Access Control (DAC) model. The Wikipedia entry provides an excellent definition:
“The controls are discretionary in the sense that a subject with a certain access permission is capable of passing that permission (perhaps indirectly) on to any other subject (unless restrained by mandatory access control)”.
Let’s confirm that OAuth scopes fits the description of DAC. The first subject here, is the employee (Alice) who passing on the permission to view her profile attributes to CloudBenefits (specifically, the API Client). That fits. Let’s understand the disclaimer at the end, though. The term Mandatory Access Control (MAC) is used, so let’s pull out a definition of MAC from Wikipedia:
“Any operation by any subject on any object is tested against the set of authorization rules (aka policy) to determine if the operation is allowed.”
These definitions provide rationale for complimenting an OAuth solution with Externalized Dynamic Authorization. Externalized Dynamic Authorization defines a MAC policy that may complement DAC or override or restrain DAC policies. MAC policies may be more top-down, and typically representing the interests of the stewards of the data. Let’s continue with Example.com having a MAC policy:
External benefits providers must have annual training in handling Example.com employee attributes that are labeled as Personably Identifiable Information (PII).
Where the subject in Part 1 was a user entity, now the policy is written against the organization. The model remains the same however. This is where the flexibility of XACML comes in handy.
Even if Alice approves of her SSN being shared with CloudBenefits, if the organization is not in good standing, it may be in Example.com’s interests not to share Alice’s PII with the provider. The MAC policy overrides the DAC policy.
The Resource Server essentially has two primary criteria for allowing the social security number to be returned to the client. You have the scope-based DAC policy (Did Alice approve of having her social security number shared with CloudBenefits) and the dynamic MAC policy (Does the CloudBenefits provider meet its training requirements to allow Example.com to share its employee’s PII?) The example above doesn’t use the scope as context in the authorization request to the Policy Decision Point (PDP). This is just a matter of design, where the Policy Enforcement Point might make to separate enforcements for these two concerns with different error handling. Here is an example from one API Gateway vendor how that might look:
The Resource Server is orchestrated to check that the incoming request has its access token and validates the token against OAuth Authorization Server for validity and determines whether the scopes included with the token include that which entitles the client to the resource. Once that check passes (following the green line), the Policy Decision Point is called with subject (CloudBenefits), action (view), resource (social_security_number) and context (type=PII). The Resource Server could be enhanced to mask or filter responses, rather than just blocking the entire request.
One might argue that an API Developer for Example.com could have implemented security logic to not return the SSN if certain conditions hold true, assuming that metadata about the API client could be passed down. However, with the practice of externalizing authorization, scope-based or dynamic, the API developer can focus on surfacing everything and let the security layer determine what is returned to the client. Implementation timelines are shorter as a result.
One might also argue that an API Gateway could be made to call the Learning Management System (LMS) that has the attribute value to determine whether CloudBenefits has performed its PII training, thereby cutting out the Externalized Dynamic Authorization PDP. The tradeoff with this approach comes with the changes that may be required in policy and where you want these changes to occur. It is a slippery slope once you start incorporating authorization logic into your application code. The same principle applies to your API Gateway orchestration. Use each tool for what it does best.
Part 3 of this series will examine microservices, and where Externalized Dynamic Authorization fits into the picture.