I would like to demonstrate how to create Sitecore WebAPI based custom service and utilize native Sitecore/.NET security mechanism. The ServicesApiController is part of Sitecore.Services.Infrastructure.dll and it implements .NET ApiController. Usage of ServicesApiController ensures continuation of Sitecore global item security policies and individual filters that can have individual requirements. My goal is to create stateless WebAPI based service in Sitecore with authentication and authorization against Sitecore Security.
Project Configuration
- Create custom controller
using System.Web.Http; using Sitecore; using Sitecore.Services.Core; using Sitecore.Services.Infrastructure.Web.Http; namespace WebApiTest.controllers { [ServicesController] public class TestController : ServicesApiController { [AuthorizedUser(@"sitecore\ServicesAPI")] [HttpGet] [Route("service/package/test")] public string Test(string d) { var context = Context.User; return string.Format(@"User: {0}; IsAuthenticated: {1}", context.Name, context.IsAuthenticated); } } }
- Custom Authentication/Authorization Filter (Known issue: IsAuthenticated set to false for stateless auth, please click here for more details)
using System.Net; using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Sitecore; namespace WebApiTest { public class AuthorizedUser : AuthorizationFilterAttribute { private readonly string _user; public AuthorizedUser(string user) { _user = user; } public override void OnAuthorization(HttpActionContext actionContext) { base.OnAuthorization(actionContext); var context = Context.User; if ((context.IsAuthenticated && context.Name.Equals(_user))) return; actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized Access; User is " + Context.User.LocalName); } } }
- Custom patch config File (App_Config/include/zzzzz_WeAPITest.config)
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <settings> <setting name="Sitecore.Services.AllowAnonymousUser"> <patch:attribute name="value">false</patch:attribute> </setting> <setting name="Sitecore.Services.Token.Authorization.Enabled"> <patch:attribute name="value">true</patch:attribute> </setting> <setting name="Sitecore.Services.SecurityPolicy"> <patch:attribute name="value">Sitecore.Services.Infrastructure.Web.Http.Security.ServicesOnPolicy, Sitecore.Services.Infrastructure</patch:attribute> </setting> </settings> <api> <tokenSecurity> <signingProvider type="Sitecore.Services.Infrastructure.Sitecore.Security.SymetricKeySigningProvider, Sitecore.Services.Infrastructure.Sitecore"> <param desc="connectionStringName">Sitecore.Services.Token.SecurityKey</param> </signingProvider> </tokenSecurity> <services> <configuration type="Sitecore.Services.Infrastructure.Configuration.ServicesConfiguration, Sitecore.Services.Infrastructure"> <allowedControllers hint="list:AddController"> <allowedController desc="TestController">WebApiTest.controllers.TestController, WebApiTest</allowedController> </allowedControllers> </configuration> </services> </api> </sitecore> </configuration>
- Update to App_Config/ConnectionStrings.config file (please do not use default token)
<add name="Sitecore.Services.Token.SecurityKey" connectionString="key=GHUwnYMxb75Td25yqyVdQQ8QQ8RzBG6T"/>
Testing with Postman
- make a call to https://HOST/sitecore/api/ssc/auth/login
- get token form response
request/response:
- compile request to custom endpoint
How to refresh this token, its expired after 20 min.
Just make another post request for the same service “sitecore/api/ssc/auth/login” and use the new key. Alternatively, you can disable token or increase the timeout, depends on scenario and circumstance.
Thank you for this!
Really nice and work well..
I have one question – maybe you can tell me how it can be done:
Currently I have a SPA (on Sitecore 9) that expose WebApi and from frontend side, and I need to somehow implement federated auth here at this point..
So looks like I need somehow bypass users to login.microsoft.com during OWIN auth and after that handle their cookie or token..
Any ideas?
I am not quite clear on reqs, but SPA should not behave any different in SC vs otherwise. Sitecore content can be exposed over Odata Item Serice, available in 9 now. Shoot me an email, if you have any questions.
I couldn’t get it to work in Sitecore 9.0.1 can you please point me to the right direction?
Do you get any specific errors in config? I tried in 9.0.2 – have had no issues.
Once you have the token, what are you doing with it?
you could use the token to make calls to Sitecore APIs to get data or with commerce server, get access to all Sitecore Commerce Connect APIs
Hello,
When i fixed my ssl issue and tried to generate token from my instance
https://HOST NAME/sitecore/api/ssc/auth/login , im getting this issue. Please help me to resolve this issue.
{
“Message”: “The request entity’s media type ‘multipart/form-data’ is not supported for this resource.”,
“ExceptionMessage”: “No MediaTypeFormatter is available to read an object of type ‘UserCredentials’ from content with media type ‘multipart/form-data’.”,
“ExceptionType”: “System.Net.Http.UnsupportedMediaTypeException”,
“StackTrace”: ” at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)”
}
try this answer. https://sitecore.stackexchange.com/questions/21975/authenticating-via-restful-api-service it worked for me.
Using Sitecore 9.3, I’m getting this error. Any idea ?
Could not resolve type name: Sitecore.Services.Infrastructure.Sitecore.Security.SymetricKeySigningProvider, Sitecore.Services.Infrastructure.Sitecore (method: Sitecore.Configuration.DefaultFactory.CreateFromTypeName(XmlNode configNode, String[] parameters, Boolean assert)).
Check that you have added “Sitecore.Services.Token.SecurityKey to connstring file
In Sitecore 9.3 the SymetricKeySigningProvider is under a different namespace. Use the below type instead
Sitecore.Services.Infrastructure.Security.SymmetricKeySigningProvider, sitecore.services.infrastructure
Upgrade the version of Sitecore.Security.SymmetricKeySigningProvider.
Upgrade Sitecore.Services.Infrastructure.Security.SymmetricKeySigningProvider version
I am getting Below response for test API: The controller for path ‘/api/sitecore/test’ was not found or does not implement IController.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Sitecore.Mvc.Diagnostics.ExceptionWrapper: The controller for path ‘/api/sitecore/test’ was not found or does not implement IController.