Part 2 - Protecting the Live Quotes Action
In this part of the tutorial we will define a policy to only allow pro subscriptions to access the live quotes. We will then make Enforcer apply this policy to the controller action using the [EnforcerAuthorization]
attribute.
Creating the policy
Edit the file in the Policy
project folder called quotes.alfa
. Notice that in the file's properties the file is marked with the build action EmbeddedResource
. This will allow the embedded policy store to pick up the policy you define. In this file, add the following ALFA definition
namespace AcmeQuotes
{
import Oasis.Attributes
attribute SubscriptionLevel
{
id = 'subscriptionLevel'
type = string
category = subjectCat
}
import Oasis.Attributes
policy ReadQuotes
{
target clause ResourceType == 'quote'
apply permitUnlessDeny
rule LiveMustBePro
{
target clause Action == 'live'
condition not SubscriptionLevel == 'pro'
deny
}
}
}
Let's look at what this policy defines. The import
statement allows us to use Oasis defined attributes without having to fully qualify the names. The ReadQuotes
policy only applies to quote
resources and is set to permit an action unless a rule specifically denies it. It contains one rule, LiveMustBePro
, that is only considered if live
quotes are being retrieved and will deny
if the SubscriptionLevel
is not pro
. The SubscriptionLevel
refers to a subscriptionLevel
attribute in the subject category
. This will come from the subscriptionLevel
claim that was resolved from the API key.
If the subscriptionLevel
is pro
then the rule condition will return false
and it will not issue a deny
. As there is no deny
, the policy will return a permit
due to the permitUnlessDeny
combining algorithm used.
In many authorization policies the resource is also part of the rule set. In our case, the resource is the stock symbol and we have no authorization requirement for a restriction based on this.
Enforcing the authorization policy
To bring this policy into force we simply add the [EnforcerAuthorization]
attribute to the GetLive
method in the QuoteController
. Identify the ReourceType
as "quote"
and the Action
as "live"
[HttpGet]
[Route("{symbol}/live")]
[EnforcerAuthorization(ResourceType = "quote", Action = "live")]
public async Task<ObjectResult> GetLive(string symbol)
{
return Ok(await quoteService.GetLivePrice(symbol));
}
Now run and test the API by hitting the following URLs in the browser:
https://localhost:5001/quote/GOOG/live?apiKey=123
this will return a result as API key 123 maps to a pro subscriptionhttps://localhost:5001/quote/GOOG/live?apiKey=456
this will return a 403 status code as API key 456 maps to a standard subscription