Request access token to call a web services

This article describes how to use access tokens in HTTP requests to access protected resources such as Sitefinity Web API. You need to perform the following:

  1. Register your app in the Security Token Service, based on IdentityServer3.
  2. Within your app, acquire an access token from the STS.
  3. Add an authorization header Bearer access_token and call the Sitefinity Web API.

Following are two samples demonstrating how to configure your applications with Sitefinity CMS and acquire an access token using the Resource owner flow and the Implicit flow. You can also take a look at the sample MVC application, which can obtain access tokens from Sitefinity CMS with implicit flow and can call the Sitefinity CMS Web API at the GitHub repository.

Resource owner client flow: Request a token by a trusted client

Perform the following:

  1. Navigate to Administration » Settings » Advanced.
  2. In the left pane, expand Authentication » SecurityTokenService » IdentityServer.
  3. Click Clients » Create new.
  4. Fill out the required fields.
    For example, enter the following:
    1. In Client name, enter testApp
    2. In Client Id, enter testApp
    3. Select Enabled checkbox.
    4. In Client flow dropdown box, select ResourceOwner.
    5. Select Allow access to all scopes checkbox.
    6. Save your changes.
  5. Expand the newly created client.
  6. Select Client secret and click Create new.
    1. Enter a secret.
      For example, enter secret
    2. Save your changes.
  7. Select Allow cors origins and click Create new.
    1. Enter the origin that can request tokens from the STS.
      For example, enter http://your-site.com
    2. Save your changes.
  8. Expand Authentication » SecurityTokenService » IdentityServer.
  9. Select Scopes and click Create new.
    1. In Scope name, enter offline_access
    2. In Scope type, enter Resource
  10. Save your changes
  11. To request a token for accessing a protected web services resource, you can use one of the following code samples:
    • JavaScript
      <!DOCTYPE html>
      <html>
      <head>
      <title>Title</title>
      <meta charset="utf-8" />
      </head>
      <body>
      <h1>JS-based resource owner sample</h1>
      <div>
      <label>username</label>
      <input id="username" value="test@test.test" />
      </div>
      <div>
      <label>password</label>
      <input id="password" type="password" value="password" />
      </div>
      <div>
      <button id="getTokenBtn">Get Token with Credentials</button>
      <button id="getTokenWithRefreshBtn">Get Token with Refresh Token</button>
      <button id="apiCallBtn">Api Call</button>
      </div>
      <div> Token: <label id="token"></label></div>
      <br/>
      <div>Refresh Token:<label id="refreshToken"></label></div>
      <br/>
      <div>Api Result:<p id="apiResult"></p></div>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
      <script>
      //The token end point from where we can retrieve the access token
      var tokenEndPoint = "http://yoursitefinitysite/Sitefinity/Authenticate/OpenID/connect/token";
      var apiUrl="http://yoursitefinitysite/api/default/newsitems";
      var client_id = "testApp";
      var client_secret = "secret";
      var accessToken;
      var refreshToken;
      $("#getTokenBtn").on("click", getToken);
      $("#getTokenWithRefreshBtn").on("click", getAccessTokenFromRefreshToken);
      $("#apiCallBtn").on("click", callApi);
      function getToken() {
      var username = $('#username').val();
      var password = $('#password').val();
      //Call that gets the access and refresh token
      $.ajax({
      url:tokenEndPoint,
      data:{
      username:username,
      password:password,
      grant_type:'password',
      scope:'openid offline_access',
      client_id:client_id,
      client_secret:client_secret
      },
      method:'POST',
      success:function(data){
      console.log(data.access_token);
      console.log(data.refresh_token);
      $('#token').text(data.access_token);
      $('#refreshToken').text(data.refresh_token);
      accessToken=data.access_token;
      refreshToken=data.refresh_token;
      },
      error:function(err){
      alert(err.responseText);
      }
      })
      }
      //Call that gets new access and refresh token from the current refresh token
      function getAccessTokenFromRefreshToken() {
      $.ajax({
      url:tokenEndPoint,
      data:{
      refresh_token:refreshToken,
      grant_type: 'refresh_token',
      client_id:client_id,
      client_secret:client_secret
      },
      method:'POST',
      success:function(data){
      console.log(data.access_token);
      console.log(data.refresh_token);
      $('#token').text(data.access_token);
      $('#refreshToken').text(data.refresh_token);
      accessToken=data.access_token;
      refreshToken=data.refresh_token;
      },
      error:function(err){
      alert(err.responseText);
      }
      })
      }
      //Sitefinity Web API call with access token as a bearer token
      function callApi() {
      $.ajax({
      url:apiUrl,
      method:'GET',
      beforeSend:function (xhr) {
      xhr.setRequestHeader ("Authorization", "Bearer " + accessToken);
      },
      success:function(data){
      if(data.value.length!==0){
      $("#apiResult").text("Item content:"+ data.value[0].Content)
      }
      else{
      $("#apiResult").text("No news items");
      }
      },
      error:function(err){
      alert(err.responseText);
      }
      })
      }
      </script>
      </body>
      </html>
      You also need to add the Access-Control-Allow-Origin header to the web.config file and register the domains that can request access tokens. You can register a single domain or allow all domains to request an access token.
      <configuration>
      <system.webServer>
      <httpProtocol>
      <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" /> <!--Single domain or * (all)-->
      </customHeaders>
      </httpProtocol>
      </system.webServer>
      </configuration>
    • C#
      using IdentityModel.Client;
      using System;
      using System.Collections.Generic;
      using System.IO;
      using System.Net;
      namespace Sample
      {
      public class Program
      {
      private static TokenClient tokenClient;
      public static void Main(string[] args)
      {
      // The token client is used to make calls to the STS endpoint where you can retrieve the access token.
      // The AuthenticationStyle.PostValues tells that the parameters will be send into the body of the request
      // For the different Authentication Styles please check https://github.com/IdentityModel/IdentityModel
      tokenClient = new TokenClient(TokenEndpoint, ClientId, ClientSecret, AuthenticationStyle.PostValues);
      TokenResponse tokenResponse = RequestToken();
      string accessToken = tokenResponse.AccessToken;
      //The purpose of the refresh token is to retrieve new access token when the ols expires
      string refreshToken = tokenResponse.RefreshToken;
      Console.WriteLine("Access token: {0}", accessToken);
      Console.WriteLine("Refresh token: {0}", refreshToken);
      string reponseHtml = CallApi(accessToken);
      Console.WriteLine("Api Response: {0}", reponseHtml);
      var newTokenResponse = RefreshToken(refreshToken);
      Console.WriteLine("New access token: {0}", accessToken);
      Console.WriteLine("New refresh token: {0}", refreshToken);
      }
      public static TokenResponse RequestToken()
      {
      //This is call to the token endpoint with the parameters that are set
      TokenResponse tokenResponse = tokenClient.RequestResourceOwnerPasswordAsync(Username, Password, Scopes, AdditionalParameters).Result;
      if (tokenResponse.IsError)
      {
      throw new ApplicationException("Couldn't get access token. Error: " + tokenResponse.Error);
      }
      return tokenResponse;
      }
      public static string CallApi(string accessToken)
      {
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(WebApiNewsEndPoint);
      request.ContentType = "application/json";
      request.Method = "GET";
      request.Headers.Add("Authorization", "Bearer " + accessToken);
      string html = string.Empty;
      WebResponse response = request.GetResponse();
      using (Stream stream = response.GetResponseStream())
      using (StreamReader reader = new StreamReader(stream))
      {
      html = reader.ReadToEnd();
      }
      return html;
      }
      public static TokenResponse RefreshToken(string refreshToken)
      {
      //This is call to the token endpoint that can retrieve new access and refresh token from the current refresh token
      return tokenClient.RequestRefreshTokenAsync(refreshToken).Result;
      }
      public const string ClientId = "testApp";
      public const string ClientSecret = "secret";
      public const string TokenEndpoint = "http://yousitefinitysite/Sitefinity/Authenticate/OpenID/connect/token";
      public const string Username = "test@test.test";
      public const string Password = "password";
      public const string Scopes = "openid offline_access";
      public static readonly Dictionary<string, string> AdditionalParameters = new Dictionary<string, string>()
      {
      { "membershipProvider", "Default" }
      };
      public const string WebApiNewsEndPoint = "http://yoursitefinitysite/api/default/newsitems";
      }
      }
       

      NOTE: If you have an external project, you must install the official IdentityModel NuGet package. You do not need to do this, if you have already installed Progress.Sitefinity.Authentication NuGet package

For more information about Endpoints, supported by IdentityServer 3, see the following:

Implicit client flow: Request a token by untrusted client

Perform the following:

  1. Navigate to Administration » Settings » Advanced.
  2. In the left pane, expand Authentication » SecurityTokenService » IdentityServer.
  3. Click Clients » Create new.
  4. Fill out the required fields.
    For example, enter the following:
    1. In Client name, enter testApp
    2. In Client Id, enter testApp
    3. Select Enabled checkbox.
    4. In Client flow dropdown box, select Implicit
    5. Save your changes.
  5. Expand the newly created client, select RedirectUris and click Create new.
    Enter the URL of your external app and save your changes.
  6. Select PostLogoutRedirectUris and click Create new.
    Enter the URL of your external app and save your changes.
  7. Using Visual Studio, create an MVC app that uses No authentication.
  8. Install following NuGet packages:
    • Microsoft.Owin
    • Microsoft.Owin.Host.SystemWeb
    • Microsoft.Owin.Security.Cookies
    • Microsoft.Owin.Security.Cookies
    • Microsoft.Owin.Security.OpenIdConnect 
  9. Create a Startup.cs class and add the code inside:
    using Microsoft.Owin;
    using Microsoft.Owin.Security.Cookies;
    using Microsoft.Owin.Security.OpenIdConnect;
    using Owin;
    using System.Collections.Generic;
    using System.IdentityModel.Tokens;
    using System.Threading.Tasks;
    [assembly: OwinStartup(typeof(MVCImplicitFlow.Startup))]
    namespace MVCImplicitFlow
    {
    public class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
    AuthenticationType = "Cookies"
    });
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
    ClientId = "testApp",
    Authority = "http://yousitefinitsite/Sitefinity/Authenticate/OpenID",
    RedirectUri = "http://yoursite",
    ResponseType = "id_token token",
    Scope = "openid",
    UseTokenLifetime = false,
    SignInAsAuthenticationType = "Cookies",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
    SecurityTokenValidated = n =>
    {
    var id = n.AuthenticationTicket.Identity;
    id.AddClaim(new System.Security.Claims.Claim("access_token", n.ProtocolMessage.AccessToken));
    n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(id, n.AuthenticationTicket.Properties);
    return Task.FromResult(0);
    }
    }
    });
    }
    }
    }

    NOTE: You can configure the STS endpoint to be different from http://yoursitefinitysite/Sitefinity/Authenticate/OpenID/connect.
    To do this, navigate to Administration » Settings » Advanced » Authentication » SecurityTokenService » ServicePath.

 

Want to learn more?

Increase your Sitefinity skills by signing up for our free trainings. Get Sitefinity-certified at Progress Education Community to boost your credentials.

Get started with Integration Hub | Sitefinity Cloud | Sitefinity SaaS

This free lesson teaches administrators, marketers, and other business professionals how to use the Integration hub service to create automated workflows between Sitefinity and other business systems.

Web Security for Sitefinity Administrators

This free lesson teaches administrators the basics about protecting yor Sitefinity instance and its sites from external threats. Configure HTTPS, SSL, allow lists for trusted sites, and cookie security, among others.

Foundations of Sitefinity ASP.NET Core Development

The free on-demand video course teaches developers how to use Sitefinity .NET Core and leverage its decoupled architecture and new way of coding against the platform.

Was this article helpful?