API Security – General

SoNET uses OAuth 2.0 to secure its API. It supports all OAuth grants:

To start making API calls, you need to:

1. Register first

2. Add New Client App in the client area with proper callback URL.

3. Use your assigned Client App ID and when needed - Client App Secret with any of the grants above to generate access token

4. Send that access token with each request to ensure authorization

Each access token is generated for a certain requested scope. Some scopes are special:

There are 3 relevant endpoints to call depending on OAuth grant:

  1. Authorization Endpoint

    URL where a Client redirects the User to make authorization request.

    https://www.LPK7.com/mvc/oauth/user

  2. Token Endpoint

    URL from which a Client can request access token

    https://www.LPK7.com/mvc/oauth/token

  3. Token Enpoint for an Api.Access scope and Implicit Grant

    URL from which a Client can request access token for Api.Access scope using Implicit Grant (good for limited trust Clients running in the browser)

    https://www.LPK7.com/mvc/oauth

Important: All access tokens are short lived (valid for only a couple of minutes).

Sample: Implicit Grant – Calling non-Site specific API

This sample demonstrates how to obtain an access token using Implicit Grant and call non-Site specific API: api/TemplateObjects/GetAllTemplates

HTML
<form action="/s/ImplicitGrant_General" method="post">
	<input type="button" id="btnGo" name="go" value="Get Templates">
</form>
<ul id="results" style="display: none">
    <table id="templates">
    </table>
</ul>
JavaScript
$(document).ready(function () {
    $('#btnGo').click(getAccessToken);
    //After SoNET calls us back – we extract access token and use it to call API
    var hashIndex = document.location.href.indexOf('#');
    if (hashIndex > 0) {
        var fragment = document.location.href.substring(hashIndex + 1);
        var accessToken = null;
        var keyValuePairs = fragment.split('&');
        for (var i = 0; i < keyValuePairs.length; i++) {
            var keyValue = keyValuePairs[i].split('=');
            var key = decodeURIComponent(keyValue[0]);
            if (key == 'access_token') {
                var value = keyValue[1];
                accessToken = decodeURIComponent(value);
                break;
            }
        }
        if (accessToken) {
            $.support.cors = true;
            $.ajax({
                type: 'GET',
                url: 'https://www.LPK7.com/api/TemplateObjects/GetAllTemplates', //API to call
                dataType: 'json',
                contentType: 'application/json; charset=utf-8',
                headers: { 'Authorization': 'Bearer ' + accessToken },  //Pass Access Token with request
                success: function (data) {
                    //Bind to some sample controls for demonstration
                    $('#results').show();
                    $.each(data, function (i, template) {                        
   $('#templates').append($('<tr>').append($('<td>').text('Name')).append($('<td>').text(template.Name)));
                    });
                },
                error: function (error) {
                    alert(error.statusText);
                }
            });
        }
    }
});
function getAccessToken(evt) {
    var url = 'https://www.LPK7.com/mvc/oauth'; //Token Endpoint for Api.Access scope
    url = url + '?client_id=2551ef4d-5ef8-4bf2-ade9-79dea8488f51';  //Your Client App ID
    url = url + '&scope=Api.Access'; //Required scope to access non-Site specific API
    url = url + '&redirect_uri=' + encodeURIComponent('http://mobile.client.com/s/implicitgrant_general'); //Callback URL – same  page
    url = url + '&response_type=token'; //Implicit Grant
    document.location = url;
}

Sample: Implicit Grant – Calling Site Specific API

This sample demonstrates how to obtain an access token using Implicit Grant and call Site specific API: odata/Sites(‘SiteName’)

HTML
<form action="/s/implicitgrant" method="post">
<input type="button" id="btnGo" name="go" value="Get Site Info">
</form>
<ul id="results" style="padding: 1em 0; display: none">
    <li>
        Site Name: <span id="txtSiteName"/>
    </li>
    <li>
        Short Info: <div id="txtShortInfo"/>
    </li>
</ul>
JavaScript
$(document).ready(function () {
    $('#btnGo').click(getAccessToken);
    //After User approves and SoNET calls us back – we extract access token and use it to call API
    var hashIndex = document.location.href.indexOf('#');
    if (hashIndex > 0) {
        var fragment = document.location.href.substring(hashIndex + 1);
        var accessToken = null;
        var keyValuePairs = fragment.split('&');
        for (var i = 0; i < keyValuePairs.length; i++) {
            var keyValue = keyValuePairs[i].split('=');
            var key = decodeURIComponent(keyValue[0]);
            if (key == 'access_token') {
                var value = keyValue[1];
                accessToken = decodeURIComponent(value);
                break;
            }
        }
        if (accessToken) {
            $.support.cors = true;
            $.ajax({
                type: 'GET',
                url: "https://www.LPK7.com/odata/Sites('SampleSite')", //API to call
                dataType: 'json',
                contentType: 'application/json; charset=utf-8',
                headers: { 'Authorization': 'Bearer ' + accessToken }, //Pass Access Token with request
                success: function (data) {
                    //Bind to some sample controls for demonstration
                    $('#results').show();
                    $('#txtSiteName').text(data.SiteName);
                    $('#txtShortInfo').html(data.HeaderShortInfo);
                },
                error: function (error) {
                    alert(error.statusText);
                }
            });
        }
    }
});
function getAccessToken(evt) {
    var url = 'https://www.LPK7.com/mvc/oauth/user'; //Authorization Endpoint
    url = url + '?client_id=2551ef4d-5ef8-4bf2-ade9-79dea8488f51'; //Your Client App ID
    url = url + '&scope=Api.Access SiteName:SampleSite'; //Api.Access and Site.Name:{SiteName} scopes
    url = url + '&redirect_uri=' + encodeURIComponent('http://mobile.client.com/s/implicitgrant'); //Callback URL-same page
    url = url + '&response_type=token'; //Implicit Grant
    document.location = url;
}

Sample: Using Various OAuth Grants from .NET

This sample demonstrates how to obtain an access token using Client Credentials Grant, Resource Owner Password Credentials Grant and Authorization Grant with DotNetOpenAuth library and call Site specific API: odata/Sites(‘SiteName’)

C#
public class SController : Controller
{
        private static readonly string clientID = "{Your Client App ID here}"
        private static readonly string clientSecret = "{Your Client App secret here}"
        private static readonly string TOKEN_ENDPOINT = "https://www.LPK7.com/mvc/oauth/token";
        private static readonly string AUTHZ_ENDPOINT = "https://www.LPK7.com/mvc/oauth/user";
        private AuthorizationServerDescription _authorizationServer;
        public AuthorizationServerDescription AuthorizationServer
        {
            get
            {
                if (_authorizationServer == null)
                {
                    _authorizationServer = new AuthorizationServerDescription()
                    {
                        TokenEndpoint = new Uri(TOKEN_ENDPOINT),
                        AuthorizationEndpoint = new Uri(AUTHZ_ENDPOINT)
                    };
                }
                return _authorizationServer;
            }
        }
        private WebServerClient _webServerClient;
        public WebServerClient WebServerClient
        {
            get
            {
                if (_webServerClient == null)
                    _webServerClient = new WebServerClient(AuthorizationServer, clientID, clientSecret);
                return _webServerClient;
        }
        string siteName = "SampleSite";
        /* Client Credentials Grant */
        public ActionResult ClientCredentials()
        {
            var authorization = WebServerClient.GetClientAccessToken(new[] { "Api.Access" });
            if (authorization == null)
                return new EmptyResult();
            string accessToken = authorization.AccessToken;
            Site site = getSite(accessToken, siteName);
            if (site == null)
                return new EmptyResult();
            return View(site);
        }
        /* Resource Owner Password Credentials Grant */
        public ActionResult ResourceOwnerPassword()
        {
            var authorization = WebServerClient.ExchangeUserCredentialForToken(
                    "Admin",
                    "test123",
                    new[] { "SiteName:" + siteName, "Api.Access" });
            if (authorization == null)
                return new EmptyResult();
            string accessToken = authorization.AccessToken;
            Site site = getSite(accessToken, siteName);
            return View(site);
        }
        /* Authorization Code Grant */
        public ActionResult UserAuthorization()
        {
            WebServerClient.RequestUserAuthorization(
                new[] { "SiteName:" + siteName, 
                        "Api.Access" },
                        new Uri(Url.Action("Callback", 
                        "S",
                        null,
                        Request.Url.Scheme)));
            return View();
        }
        public ActionResult Callback()
        {
            //exchange authorization code for access token
            var authorization = WebServerClient.ProcessUserAuthorization();
            if (authorization == null)
                return View();
            if (authorization.RefreshToken != null && authorization.AccessTokenExpirationUtc.HasValue)
                WebServerClient.RefreshAuthorization(authorization, TimeSpan.FromSeconds(30));
            //You could store refresh token or better yet entire IAuthorizationState to do not ask User again
            string accessToken = authorization.AccessToken;
            Site site = getSite(accessToken, siteName);
            return View(site); 
        }
        private Site getSite(string accessToken, string siteName)
        {
            if (string.IsNullOrWhiteSpace(accessToken))
                throw new ArgumentNullException("accessToken");
            using (var httpClient = new SoNETHttpClient(accessToken))
            {
                //with access token present - make Web Api call to get Site object
                string url = string.Format("https://www.LPK7.com/odata/Sites('{1}')", siteName);
                var apiResponse = httpClient.GetAsync(url).Result;
                if (!apiResponse.IsSuccessStatusCode)
                    return null;
                string result = apiResponse.Content.ReadAsStringAsync().Result;
                return JsonConvert.DeserializeObject<Site>(result);
            }
        }
}
;