SuperOffice.WebApi Preview

This library provides an alternative to the existing SuperOffice NetServer WCF proxies, and is a .NET Standard 2.0 library that works with both .NET Framework (4.6.1 and higher) and .NET Core (3.1 and higher) applications.
Ratings

The SuperOffice.WebApi nuget package is ready for preview.

https://www.nuget.org/packages/SuperOffice.WebApi

Install-Package SuperOffice.WebApi -Version 1.0.0-preview2

Get the samples on github:

https://github.com/SuperOffice/SuperOffice.WebApi-Samples

This is a pre-release version which is very young and untested in the wild. Please take the time to give it a good test drive and provide your feedback.

Feedback can either go to sdk@superoffice.com, subject: SuperOffice.WebApi Preview, or even better, create an issue on the SuperOffice.WebApi Samples repo!

About the samples

The samples use a pre-registered application called SuperOffice DevNet WebApi Sample. It is registered with the following details:

Property Description
Environment This application is registed for SOD
ContextIdentifier The tenant identifier will be one of your tenants
SystemUserToken The SystemUser is issued at app approval on your tenant
ClientId 857fd8fa9c83db5fa030b94d1bcc7b60
ClientSecret ca452f9c29870bc278017796cd16bd11
PrivateKey See the code sample Program.cs, line 206.

To get a system user token, sign-in using the DevNet-Tokens application using the provided client ID and secret in the table above. When redirected back the web site, your System User Token is displayed on the page.

Copy and paste both the System User token and Access Token from the page into each of the sample program.cs files to successfully run the code.

SuperOffice WebApi Samples

First things first! This is not an OAuth 2.0 client. When authenticating with OpenID Connect or OAuth, you still have to use another means to obtain OAuth tokens.

For OAuth/OpenID Connect authentication in web applications, we recommend you take a look at the AspNet.Security.OAuth.SuperOffice provider. It’s an open source library created by DevNet, and tailored for SuperOffice online.

Now lets begin looking what the SuperOffice.WebApi library is and how it is used.

What is SuperOffice.WebApi

This library is a .NET Standard 2.0 library that works with both .NET Framework (4.6.1 and higher) and .NET Core (2.0 and higher) applications.

This library is used for both onsite and online installations. Its purpose is to provide an alternative to the existing SuperOffice NetServer WCF proxies. SuperOffice.WebApi provides the exact same Agent-style services as SuperOffice.NetServer.Services, while adopting modern practices, such as asynchronous methods.

This library makes it easier to work in with multiple installations simultaneously. It isolates a customers context in a WebApiConfiguration instance, where each instance is configured to target one specific tenant.

Each WebApiConfiguration instance can be configured with its own language, culture and timezone settings.

This library also has built-in system user token support. More on that below.

OK. So that’s what the SuperOffice.WebApi library is, now lets see how to use it.

How to use SuperOffice.WebApi

  1. Instantiate a WebApiConfiguration instance. The primary constructor accepts a customer web api URL. I.e.,

    https://sod.superoffice.com/cust12345/api
    or
    https://www.super-onsite.com/api

    WebApiConfiguration(string baseUrl);

    WebApiConfiguration inherits from RequestOptions, which contain the internationalization settings. These settings can also be passes into an overloaded contructor.

    WebApiConfiguration(
        string baseUrl, 
        IAuthorization authorization, 
        string languageCode = null, 
        string timeZone = null, 
        bool verifyUrl = true
    );
  1. Define the IAuthorization credential type. The IAuthorization parameter is used to define the credential type, and used to set the Authorization attribute in each HTTP request.

    There are 4 built-in IAuthorization implementations.

    Authorization Type Used in Online Used in Onsite
    AuthorizationAccessToken X  
    AuthorizationSystemUserTicket X  
    AuthorizationTicket   X
    AuthorizationUsernamePassword   X
    AuthorizationUserToken   X

    Assign an instance to the WebApiConfiguration.Authorization property.

    var config = new WebApiConfiguration(tenant.WebApiUrl);
    config.Authorization = 
        new AuthorizationUsernamePassword("jack@black.com", "TenaciousD!");
  2. Create the desired Agent class. Pass the WebApiConfiguration instance into the Agents' constructor. This requirement is different when compared to the Agent construction of the existing WCF proxies.

    var contactAgent = new ContactAgent(config);

    Now your code is able to make the same method calls it does today, with one exception, they are all not asynchronous, and can use the async await pattern!

    await contactAgent.GetContactEntityAsync(contactId);

About IAuthorization

There are cases where a users credentials will expire.

It’s probably easiest to say that the only case where credentials will not expire is when using AuthorizationUsernamePassword. All other IAuthorization implementations contain time-sensitive credentials.

The SuperOffice WebApi library has built-in refresh credential support for online IAuthorization instances.

Both AuthorizationTicket and AuthorizationSystemUserTicket credentials expire after 6 hours but out of these two only the AuthorizationSystemUserTicket implementation has automatic refresh support.

To auto-refresh AuthorizationSystemUserTicket requires the following information:

  1. Environment
  2. ContextIdentifier
  3. ClientSecret
  4. PrivateKey
  5. SystemUserToken

To auto-refresh AuthorizationAccessToken requires the following information:

  1. Access Token
  2. Refresh Token
  3. Redirect URI

The system user flow is discussed more in the System User section below.

When is IAuthorization refreshed

This library takes a reactive approach and waits to receive an access denied response prior to attempting to refresh the Authorization.

When an access denied response is received, the client looks to make sure the WebApiConfiguration has an IAuthorization.RefreshAuthorization implementation. When present, and the RefreshAuthorization implementation succeeds, RefreshAuthorization returns an updated IAuthorization.

With an updated Authorization, the client then invokes the IAuthorization.GetAuthorization method to get a two-value tuple, the scheme and the parameter, and uses those to set the Authorization header.

("Bearer", "8A:Cust12345:ABCdefg....XyZ")

Finally, the client retries that original request with an updated scheme and parameter.

Certificate Validation

Both AuthorizationAccessToken and AuthorizationSystemUserTicket validate the response from SuperOffice using the SuperOffice public certificate.

The client does this by requesting the OAuth 2.0 metadata document from the online environment. This process takes two requests:

  1. The first request obtains the OAuth 2.0 metadata document to obtain the jwks_uri.
  2. The second request gets the public certificate details contents from the jwks_uri.

The benefit of this process is that the integration does not need to include any physical public certificates.

Custom IAuthorization implementation

If for some unknown reason you want to populate the Authorization header with a different scheme/parameter values, you can implement your own IAuthorization. The interface is simple.

public interface IAuthorization
{
    Func<ReAuthorizationArgs, IAuthorization> RefreshAuthorization { get; set; }
    (string scheme, string parameter) GetAuthorization();
}

RefreshAuthorization is a function that accepts a ReAuthorizationArgs and returns an IAuthorization instance with updated credential values.

The client updates the WebApiConfiguration and then calls the GetAuthorization method. GetAuthorization returns the scheme and parameter.

System User

This library supports the System User flow. The client makes it very easy to call the online PartnerSystemUserService endpoint, validate the JWT and return the claims it contains.

While the JWT contains a lot of information, it’s usually just the Ticket credential people want. Therefore, SuperOffice.WebApi simplifies calling the service, validating the response, and then returning the ticket in a single method call.

The classes described in this section can be used ahead of time to populate an AuthorizationSystemUserTicket. 

Do not ask for a System User Ticket every single time you invoke an Agent method! This creates a new credentials record in the database each and every time. Take advantage of the 6 hour window and only ask for a new Ticket when absolutely necessary!

How to use System User flow

Use the SystemUserClient class, located in the SuperOffice.WebApi.IdentityModel namespace.

The constructor accepts a SystemUserInfo instance, and contains all of the information required to submit a request to the partnersystemuserservice.svc endpoint.

SystemUserInfo Properties

Property Description
Environment The online environment (SOD, Stage, Production.
ContextIdentifier The tenant, or customer, identity.
ClientSecret The application secret, a.k.a. client_secret.
PrivateKey The applications RSAXML private certificate value.
SystemUserToken The SystemUser token, issued during app approval.

Given the required information, the SystemUserClient is able to generate and send a request to the service, then receive and validate the response.

var sysUserClient = new SystemUserClient(systemUserInfo);
var sysUserJwt = sysUserClient.GetSystemUserJwt();
var sysUserTkt = sysUserClient.GetSystemUserTicket();

If all you want is the System User Ticket, just use the GetSystemUserTicket method and the rest of is done for you. However, if you want to access any of the claims, you will need to use the GetSystemUserJwt method and validate the JWT as show next.

GetSystemUserJWT returns the JWT wrapped inside a SystemUserResult instance. It does not validate or extract any claims.

To perform validation and extract claims, the SystemUserClient uses the JwtTokenHandler, located in the SuperOffice.WebApi.IdentityModel namespace.

var handler = new JwtTokenHandler(
    "YOUR_CLIENT_ID",                 // Application ID, A.K.A. client_id
    new System.Net.Http.HttpClient(), // HttpClient instance.
    OnlineEnvironment.SOD             // target online environment (SOD, Stage or Production)
    );

var tokenValidationResult = handler.ValidateAsync(sysUserJwt.Token);

The method JwtTokenHandler.ValidateAsync returns a TokenValidationResult, a Microsoft datatype located in the Microsoft.IdentityModel.JsonWebTokens namespace, in the Microsoft.IdentityModel.JsonWebTokens assembly.

Package Dependencies

These will automatically be included when you add the SuperOffice.WebApi package to a project.

.NETStandard 2.0

  • Microsoft.IdentityModel.JsonWebTokens (>= 5.6.0)
  • Microsoft.IdentityModel.Logging (>= 5.6.0)
  • Microsoft.IdentityModel.Tokens (>= 5.6.0)
  • Newtonsoft.Json (>= 12.0.2)
  • System.Security.Permissions (>= 4.7.0)

Known Issues

The current SuperOffice.WebApi package dependencies are not the latest Microsoft packages available. Therefore, if your project uses newer versions of the Microsoft packages, there will be conflicts with TokenValidationResult.

The current library does not have any logging, and very little exception handling.

Post Comment To the top