Last updated: Oct 30 2018

Authorization Service
By default, Content Delivery API supports OAuth authentication (by installing the ContentDeliveryApi.OAuth package, see Installing Content Delivery API) and cookie-based authentication. However, ContentDeliveryApi exposes APIs allowing you to customize the authorization flow and use your preferred authorization mechanism like AzureAD or GitHub.
The Authorization flow of Content Delivery API is described by the diagram below:
- When you make a request to an endpoint (for example, api/episerver/v2.0/content/5), the request is handled by
ContentApiAuthorizationAttribute
before being passed to the corresponding controller. - At
ContentApiAuthorizationAttribute
, the flow is like the following:- The user principal is initialized from
HttpActionContext
usingISecurityPrincipal.InitializePrincipal()
, and this principal is assigned to current http context. - The user principal is validated by
ContentApiAuthorizationService
. There are two main steps atContentApiAuthorizationService
: (1) the user principal is retrieved fromISecurityPrincipal
, and then (2) the principal is validated. The final result should be a Tuple<HttpStatusCode,string> that contains HttpStatusCode and the error message if any errors occur.
- The user principal is initialized from
- Based on the authorization result,
ContentApiAuthorizationAttribute
returns an error or forwards the request to the controller endpoint.
ISecurityPrincipal
and ContentApiAuthorizationService
are important components for customizing the authorization flow:
ISecurityPrincipal
: defines signatures for user principal manipulation. If you want to use another OAuth system, you should create your own implementation for this interface and define how to initialize and retrieve user principal:- Create a new class inheriting
ISecurityPrincipal
and decorate the class with attributeServiceConfiguration(typeof(ISecurityPrincipal))
. - Override the method
InitializePrincipal
to initialize user claims. For example, a real-life scenario might be a customized OAuth system where the user’s access token is retrieved by calling one service, and another service is called for authentication and authorization. In this case, those operations should be put inInitializePrincipal
and the final result should be that the principal for the current request is set (for example,HttpContext.Current.User
= principal andThread.CurrentPrincipal
= principal). - Implement
GetCurrentPrincipal()
andGetAnonymousPrincipal()
in line with your systems. - If your use case is complicated and this interface is not enough, you can customize the
Authorize()
method ofContentApiAuthorizationService
,
- Create a new class inheriting
This is the default implementation of ISecurityPrincipal
:
using EPiServer.ServiceLocation; using System.Security.Principal; using System.Threading; using System.Web; using System.Web.Http.Controllers; namespace EPiServer.ContentApi.Core.Security.Internal { /// <summary> /// Default implementation of <see cref="ISecurityPrincipal"/> for initialzing and accessing <see cref="IPrincipal"/> within ContentApi's scope. /// </summary> [ServiceConfiguration(typeof(ISecurityPrincipal))] public class DefaultSecurityPrincipal : ISecurityPrincipal { /// <summary> /// Get <see cref="IPrincipal"/> from provided <see cref="HttpActionContext"/>. Set Principal on current thread and current <see cref="HttpContext"/> /// </summary> /// <param name="actionContext"></param> public virtual void InitializePrincipal(HttpActionContext actionContext) { // custom authentication logic, we must set the principal on two places: Current thread & current httpContext // for reference, go here https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api Thread.CurrentPrincipal = actionContext.RequestContext.Principal; // in case the application is not self-hosted if (HttpContext.Current != null) { HttpContext.Current.User = actionContext.RequestContext.Principal; } } /// <inheritdoc /> public virtual IPrincipal GetCurrentPrincipal() { return HttpContext.Current?.User ?? Thread.CurrentPrincipal; } /// <summary> /// Retrieve an anonymous Principal with Anonymous and Everyone roles /// </summary> /// <returns></returns> public virtual IPrincipal GetAnonymousPrincipal() { return new GenericPrincipal( new GenericIdentity("Anonymous"), new[] { "Everyone" } ); } } }
ContentApiAuthorizationService
: is responsible for authorizing requests. It will check two main things; the user validity, and the user’s privileges to access the API. User principal is extracted byISecurityPrincipal.GetCurrentPrincipal()
. If the process becomes complicated, this service should be customized. Otherwise,ISecurityPrincipal
should be enough.
Do you have feedback on this documentation? Send an email to documentation@episerver.com. For development-related questions and discussions, refer to our Forums on https://world.episerver.com/forum/