Authentication with the Workflow REST API
This topic provides some samples that demonstrate how to use different authentication approaches with the Workflow REST API.
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
- Windows Integrated Authentication
- OAuth: Static Credentials (C#)
- OAuth: Static Credentials (JavaScript)
- OAuth: Prompt for Credentials
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 the product using the context of the username and password you pass in.
Basic Authentication
// 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);
}
Windows Integrated Authentication
To configure the Workflow REST API to use Windows Integrated authentication, enable Windows Authentication in IIS for the Workflow API.
- Open IIS and browse to the API (K2 > API > Workflow > v1)
- Open Authentication
- Enable Windows Authentication
Any code you use must have the UseDefaultCredentials property set to true.
UseDefaultCredentials = true
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://[k2environmentid]/api/workflow/v1/Employees");
//Use the currently logged on user for authentication
request.UseDefaultCredentials = true;
//execute the request
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//Process response
...
OAuth: Static credentials using ClientID and Secret Key (C#)
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.
OAuth: Static credentials
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.
//Hard-coding the Client ID, Client Secret, Username and Password is a security risk, rather use a secure store.
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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> 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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> for OAuth, provide the Client Secret (also known as the Key value) from your <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> 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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> 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: Static credentials using ClientID and Secret Key (JavaScript)
This code snippet demonstrates how to construct an OAuth token in JavaScript, without prompting for a username and password. Note that a statically-defined username and password is used.
OAuth: Static Credentials in JavaScript
// OAuth: Static Credentials
// This sample uses the OAuth Resource Owner Password grant
// Will only work with <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span>
// Will not work with users with MFA enabled
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
// TODO: Directory (tenant) ID from <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span>
const tenantId = "[uniqueID]";
// Hard-coding the Client ID, Client Secret, Username and Password is a security risk, rather use a secure store
const vals = {
grant_type: "password",
scope: "openid",
resource: "https://api.k2.com/",
// TODO: Application (client) ID from <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span>, must have K2 API permission scope
client_id: "[xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]",
// TODO: Secret for the client ID
client_secret: "[###################################]",
// TODO: <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> user account
username: "[username]@[yourdomain].onmicrosoft.com",
// TODO: User's password
password: "[password]",
};
// TODO: Set K2 Environment URL
const environmentUrl = "https://[k2environmentid]/api/workflow/v1/workflows";
function GetUserToken(callback) {
var formBody = [];
for (var property in vals) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(vals[property]);
formBody.push(`${encodedKey}=${encodedValue}`);
}
formBody = formBody.join("&");
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
json = JSON.parse(this.responseText);
callback(json["access_token"]);
} else {
console.log(this.responseText);
}
};
request.open(
"POST",
`https://login.microsoftonline.com/${tenantId}/oauth2/token`
);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.send(formBody);
}
function GetWorkflows(token) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
console.log(this.responseText);
};
request.open("GET", environmentUrl);
request.setRequestHeader("Content-Type", "application/json");
request.setRequestHeader("Authorization", `Bearer ${token}`);
request.send();
}
GetUserToken((token) => GetWorkflows(token));
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 Azure Active Directory Sign-on page if a token isn't found.
OAuth: Prompt for credentials
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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> 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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span>
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 <span class="mc-variable BrandingThirdParty.Azure_Active_Directory variable">Azure Active Directory</span> 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;