With Sitecore 10.3 comes the Sitecore Authoring and Management Graph API. The API provides a single endpoint that allows you to manage Sitecore content using GraphQL. The endpoint is disabled by default, but in this blog post I will show how we can enable the endpoint and get the required access token to start calling it.
First the motivation for this post: If you – like me – are curious on the capabilities of this new endpoint, you probably want to get it up and running locally. Hence, you will most likely end up on this guide provided by Sitecore.
The guide describes three steps. First, we need to enable the GraphQL endpoint using these settings:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<sitecore>
<settings>
<setting name="GraphQL.Enabled" value="true"/>
<setting name="GraphQL.ExposePlayground" value="true"/>
</sitecore>
</configuration>
We then need to get an access token from the Sitecore Identity Server. And finally, we will be able to test the API via the build in IDE playground on https://<your-server>/sitecore/api/authoring/graphql/playground/
.
All of this is pretty straight forward, except the guide Sitecore provides for obtaining an access token. It involves creating a client application, registering it in Sitecore Identity Server and then use that client credentials to obtain an access token.
The guide provided by Sitecore is a good approach in a production setup, but for simply testing out the API locally there is easier way (which of course should not be used in production). So if you are in a hurry, and understand that the approach below is only for testing, you can skip the next section :)
The Sitecore Identity Server
The Sitecore Identity Server is built on the IdentityServer4 (which is an implementation of an OIDC and OAuth2 server). It exposes a couple of endpoints, that allow a registered client applications to obtain access tokens.
The details of a IdentityServer4 server can be inspected using this url: https://<your-identity-server>/.well-known/openid-configuration
. This document is used for “discovery” because it describes everything a client needs to know to interact with the identity server.
A normal login flow (on a web site) uses the authorization endpoint (https://<your-identity-server>/connect/authorize)
. This is the endpoint that exposes the HTML login form that we normally associate with a login. The login form will typically redirect the browser back to the client application with a authorization code. The client application can then exchange the authorization code to an access token using the token endpoint (https://<your-identity-server>/connect/
token). This flow is called an authorization code flow, and in a web site setup it has a lot of benefits, because the fact that only the authorization code is sent to the browser prevents a lot of security issues related to man-in-the-middle attacks.
But there is a lot of ways to use the token endpoint on an IdentityServer4, and using an authorization code is just one of them.
Another option is to use a client id and a client secret. This method is used by client applications without an actual user (imagine some server-to-server interaction). Here the client application will simply contact the Identity Server with a id and a secret, and get a access token. This way of obtaining a access token is called a client credentials flow.
There is also an option for a client application that does have a user, but do not want to use the authorize endpoint: It can simply send the username and password to the token endpoint, and get an access token for that user. This is called a password credentials flow. It has some security issues (you can read about some of them here) – but it exists.
Finally, there is a refresh token flow, where a already obtained access token (which expires) can be renewed.
Please be aware that when designing client applications using the Sitecore Identity Server, its really important to understand the benefits and security issues with these each of these flows and choose the correct one for a concrete situation. This is especially important for SPA and mobile applications, where the user will have access to inspect the client applications code. Information like client secrets, passwords and refresh tokens will give long term access to a client application, and the various flows are design to prevent access to these.
TLDR: Use the password credential flow
These warnings aside, for simply obtaining an access token on a local test environment we can simply use the password credential flow to obtain an access token.
In a OOTB Sitecore, there is already registered a client application called SitecorePassword
. It has a client secret configured in the Config\production\Sitecore.IdentityServer.Host.xml
file (in the PasswordClient
node) of the Sitecore Identity Server and will allow us to receive access tokens using the password credential flow.
So for testing puposes, we will simply use this client to obtain an access token. We need to provide a list of scopes (more of less the same as permissions) that we want the access token to contain.
We can simply call the token endpoint using Powershell:
$Uri = 'https://your-identity-server/connect/token'
$ContentType = 'application/x-www-form-urlencoded'
$Body = @{
grant_type='password'
username='sitecore\admin'
password='b'
scope='openid sitecore.profile sitecore.profile.api'
client_id='SitecorePassword'
client_secret='your-client-secret'
}
$Response = Invoke-WebRequest -Uri https://your-identity-server/connect/token -Method POST -ContentType $ContentType -Body $Body
$JsonResponse = $jsonObj = ConvertFrom-Json $([String]::new($response.Content))
Write-Host $JsonResponse.access_token
Another option is to create a controller in our local Sitecore solution (or in a seperate solution): We can use the IdentityModel 3.10.10
NuGet package (used by Sitecore), which contains all the functionality we need to interact with the Sitecore Identity Server. In a classic .NET 4.8 solution such a controller could look like this:
namespace sc10xm.Controllers
{
using IdentityModel.Client;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Mvc;
using static IdentityModel.OidcConstants;
public class IdentityController : Controller
{
public async Task<string> Token()
{
var identityServer = "your-identity-server";
var clientSecret = "your-client-secret";
var httpClient = new HttpClient();
var discoveryResponse = await httpClient.GetDiscoveryDocumentAsync(identityServer);
PasswordTokenRequest tokenRequest = new PasswordTokenRequest()
{
Address = discoveryResponse.TokenEndpoint,
ClientId = "SitecorePassword",
ClientSecret = clientSecret,
GrantType = GrantTypes.Password,
Scope = "openid sitecore.profile sitecore.profile.api",
UserName = @"sitecore\admin",
Password = "b"
};
var token = await httpClient.RequestPasswordTokenAsync(tokenRequest);
return token.AccessToken;
}
}
}
After registering this endpoint, we will now be able to call our Sitecore server using e.g., https://<your-server>/identity/token
and obtain an access token. Of course such a endpoint should only be used locally, as it automatically obtains an access token for sitecore\admin
.
Per default the access token will have a lifetime of 1 hour, but this can be adjusted using the AccessTokenLifetimeInSeconds
settings in the Sitecore Identity Server.
With this access token we are now able to call the Authoring and Management API using the IDE. The access token needs to be provided as an Authorization
header and prefixed with Bearer
.