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
}
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 quoteresources 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=123this will return a result as API key 123 maps to a pro subscriptionhttps://localhost:5001/quote/GOOG/live?apiKey=456this will return a 403 status code as API key 456 maps to a standard subscription