Authentication with the Workflow REST API

This topic provides some samples that demonstrate how to use different authentication approaches with the Workflow REST API.

In the code samples below, you will need to replace values in square brackets with the appropriate values for your K2 environment. For example, the value [K2RESTSERVICEBASEURL] refers to the location of the K2 Site where the service is hosted. You can determine the REST service's URL for you environment through the K2 Management Site by navigating to IntegrationAPIsWorkflow REST, the URL will be displayed in the Base URL property. The URL may look something like this, of course the value would be different for your environment: https://k2serverprod:4444/api/workflow/v1

If using OAuth authentication in your code, you will need to configure our K2 environment for OAuth. Please see the KB article KB002784: Configure AAD and K2 Services for Inbound OAuth for details.

The K2 Workflow REST API only supports basic and OAuth authentication.

There are many ways of working with authentication and OAuth in Azure apps. This topic covers the basics and you can find many more examples on the internet.

Samples:

Basic Authentication

This example shows how to use Basic Authentication with the Workflow REST API. Note that basic authentication is not as secure as OAuth, and the connection will always be authenticated by K2 using the context of the username and password you pass in.

// Create a new HttpClient object as static for the application, make sure it's only created once to avoid opening multiple ports on a server, per application.
// Dispose of httpclient object when application closes.
static System.Net.Http.HttpClient k2WebClient;

public void BasicAuth() {
 // Passing static credentials for authentication, using a client handler to store credentials.
  System.Net.NetworkCredential k2credentials = new NetworkCredential("[USERNAME]", "[PASSWORD]");
System.Net.Http.  HttpClientHandler loginHandler = new HttpClientHandler {
  Credentials = k2credentials
 };

 // Open the HTTPClient connection one time upon form load so that we only open one port/socket on the server.
 k2WebClient = new System.Net.Http.HttpClient(loginHandler, true);
}

OAuth: Static credentials using ClientID and Secret Key

This code snippet demonstrates how to construct an OAuth token in C#, without prompting for a username and password. Note that a statically-defined username and password is used.

public async static void OAuthSampleNoPrompt() {
 string username = "[username]@[yourdomain].onmicrosoft.com"; //TODO: replace with the username and domain with your details
 string password = "[password]"; //TODO: replace with the user's password
 var vals = new List < KeyValuePair < string,
  string >> {
   new KeyValuePair < string,
   string > ("grant_type", "password"),
   new KeyValuePair < string,
   string > ("scope", "openid"),
   new KeyValuePair < string,
   string > ("resource", "https://api.k2.com/"), //Identifier of the target resource that is the recipient of the requested token. This value will most likely be https://api.k2.com/ in your environment.
   new KeyValuePair < string,
   string > ("client_id", "[xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]"), //Client ID of the custom client app requesting the token (the app should have the K2 API permission scope). If using AAD for OAuth, provide the Application ID of your custom app registration; you can find this value in the Application ID field in the App Registration page, in Settings > Properties
   new KeyValuePair < string,
   string > ("client_secret", "[###################################]"), //TODO: the secret key for the custom client app requesting the token. If using AAD for OAuth, provide the Client Secret (also known as the Key value) from your AAD App Registration page, in the Settings > Keys page
   new KeyValuePair < string,
   string > ("username", username),
   new KeyValuePair < string,
   string > ("password", password)
  };

 var url = $ "https://login.microsoftonline.com/[uniqueID]/oauth2/token"; //TODO: use the outh2token endpoint URL from your AAD config

 var hc = new HttpClient();
 HttpContent hcContent = new FormUrlEncodedContent(vals);
 HttpResponseMessage hcResponse = hc.PostAsync(url, hcContent).Result;

 if (!hcResponse.IsSuccessStatusCode) return;
 //read in the token that was returned
 System.IO.Stream data = await hcResponse.Content.ReadAsStreamAsync();
 string responseData;
 using(var reader = new System.IO.StreamReader(data, Encoding.UTF8)) {
  responseData = reader.ReadToEnd();
 }

 //construct an access token object using the NewtonSoft Json helper
 AccessToken authToken = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessToken> (responseData);

 //set up the endpoint to hit
 string fullUrl = "https://[k2environmentid]/api/workflow/v1/workflows"); //TODO: replace with your K2 environment's URL and the endpoint you want to hit
System.Net.WebRequest request = WebRequest.Create(fullUrl);
//pass in the outh token you obtained
request.Headers.Add("Authorization", "Bearer " + authToken.Access_Token);

System.IO.Stream dataStream = null;
string result;

try {
 var webresponse = (HttpWebResponse) request.GetResponse();
 int webresponseCode = (int)(webresponse).StatusCode;

 dataStream = webresponse.GetResponseStream();
 System.Text.Encoding encode = System.Text.Encoding.GetEncoding("UTF-8");
 System.IO.StreamReader readStream = new System.IO.StreamReader(dataStream, encode);

 result = readStream.ReadToEnd();

 webresponse.Close();
} finally {
 if (dataStream != null)
  dataStream.Dispose();
}
Debug.WriteLine(result);
}

class AccessToken {
 //represents a public string token_type;
 public string Scope {   get;   set;  }
 public string ExpiresIn {   get;   set;  }
 public string ExpiresOn {   get;   set;  }
 public string NotBefore {   get;   set;  }
 public string Resource {   get;   set;  }
 public string Access_Token {   get;   set;  }
 public string RefreshToken {   get;   set;  }
 public string IdToken {   get;   set;  }

}

OAuth: Prompt for credentials

This code snippet shows how to get an OAuth token in C#, where the user gets prompted to login through the AAD Sign-on page if a token isn't found.

Uri _baseUrl = new Uri("https://[environmentid]/api"); //TODO: replace with your K2 environment's URL
string _clientId = "[xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]"; //Client ID of the custom client app requesting the token (the app should have the K2 API permission scope). If using AAD for OAuth, provide the Application ID of your custom app registration; you can find this value in the Application ID field in the App Registration page, in Settings > Properties
string _authority = "https://login.microsoftonline.com/common/login"; //Login URL for AAD
string _redirectUri = @ "https://api.k2.com/client"; //Address to return to upon receiving a response from the authority
string _webApiResourceId = @ "https://api.k2.com/"; //Identifier of the target resource that is the recipient of the requested token. This value will most likely be https://api.k2.com/ in your environment
string _resource = "workflow/v1/workflows"; //the endpoint you want to query (in this case, a list of workflow definitions)

//set up http client
System.Net.Http.HttpClient _httpClient = new HttpClient(new HttpClientHandler() {
 UseDefaultCredentials = false,
});

//platform-specific arguments and information
Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters parameters = new PlatformParameters(PromptBehavior.Auto);
//retrieves authentication tokens from Azure Active Directory and ADFS services
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext = new AuthenticationContext(_authority);
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult authResult = null;

try {
 //get the OAuth token (will show login screen to user if no token found)
 authResult = authContext.AcquireTokenAsync(_webApiResourceId, _clientId, new Uri(_redirectUri), parameters).Result;
} catch (Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException adalEx) {
 //TODO: do something with the auth error
 return;
}

//use pathos client to construct the HTTP request and read response
Pathoschild.Http.Client.IRequest request = null;
Pathoschild.Http.Client.IResponse result = null;

request = (Pathoschild.Http.Client.IRequest) new Pathoschild.Http.Client.FluentClient(_baseUrl, _httpClient).GetAsync(_resource).WithHttpErrorAsException(false);
//pass in the access token that was obtained
request = request.WithBearerAuthentication(authResult.AccessToken);
result = request.AsResponse().Result;
//get the result from the endpoint call
string returnvalue = result.Message.Content.ReadAsStringAsync().Result;