DEV Community

Cover image for Working with Helix ALM REST API Part 1: Authentication
Mecomis
Mecomis

Posted on • Edited on

Working with Helix ALM REST API Part 1: Authentication

Today we’ll be starting a series of posts focusing on various features from Perforce’s Helix ALM REST API. Today’s feature is about authenticating a client. If you are unfamiliar with Helix ALM, it is a modular suite of ALM tools that you can use to trace requirements, tests, and issues. ALM stands for Application Lifecycle Management, REST for Representational State Transfer, and API for Application Programming Interface.

The Helix ALM REST API has several endpoints that developers can use for interfacing with their organization’s Helix ALM instance. The wide variety of endpoints provide many possibilities for developers to create tools or scripts to aid in their organization’s workflow, with few limitations.

The REST API is available at:

https://{API URL}/helix-alm/api/v0/

and the Swagger UI interactive documentation tool is available at:

https://{API URL}:{port}

where {API URL} is the address of the REST API server. The address can be configured in the JSON configuration file of the REST API, typically located at:

../Perforce/Helix ALM/helix-alm-rest-api/config/config.json

on the machine that is running the Helix ALM instance.

REST API Features

Authentication

There are several ways to authenticate with the REST API. However, to first make any requests the user must belong to a security group that has Allow Login via SOAP enabled in order to use the API. The RBAC (role-based access control) for the security group and user will depend on the your organization, but for this series we will be assuming that there are no restrictions on what the security group can access. It is also recommended to create an API key for the user, but it is not strictly necessary for authentication. If the API key is created, note it down somewhere because the key’s secret is only shown once. For both the security group and API key, an administrator must create these in the Helix ALM client application.

Basic Authentication

Basic authentication is done with the user’s username and password and attached in the request header. The value of the username and password must be Base64 encoded and conform to:

Authorization: Basic username:password

API Key Authentication

Key authentication is similar to basic authentication but instead of including username and password in the header, the API key is sent instead. The value for the authorization header must conform to:

Authorization: ApiKey apiKey:apiSecret

Access Token

Regardless of which authentication method is chosen, all endpoints will require an access token — the only endpoints which do not require an access token are the projects and the token endpoints.

To receive the access token, make a GET request to the endpoint:

https://{API URL}/helix-alm/api/v0/{projectID}/token

The project ID can be gotten from the /projects endpoint. Alternatively, the project name may be used instead but if there are spaces in the project’s name then these must be URL escaped.

The response from the REST API is an access token object, shown below:

{
  "tokenType": "Bearer",
  "expiresOn": "2000–00–00T00:00:00Z",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5… "
}
Enter fullscreen mode Exit fullscreen mode

The access token then needs to be included in the Authorization header with “Bearer” preceding the value.

GET /helix-alm/api/v0/{ProjectID}/{Endpoint} HTTP/1.1
> Host: {Your host}
> accept: application/json
> Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5...
Enter fullscreen mode Exit fullscreen mode

In C#, setting the access token to the header might look like:

private void SetRequestAccessToken(ref HttpRequestMessage request, AccessToken accessToken)
{
  string authorization = $"Bearer {accessToken.AccessToken}");
  request.Headers.Add("Authorization", authorization);  
}
Enter fullscreen mode Exit fullscreen mode

Server Certificate Validation Callback

When any request is made to the Helix ALM REST API it will return a response with an SSL certificate. By default, it is a self-signed certificate that is created by the API the first time the server is launched. If a non-default certificate is used, then the configuration file must be modified to reflect this choice. This setting is found in the config file.

How the program interfacing with the API handles the certificate callback is highly dependent on the programming language chosen. For our examples, we will ignore validation for now.

In C# that might look like:

HttpClientHandler handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
System.Net.ServicePointManager.ServerCertificateValidationCallback =
  ((sender, certificate, chain, sslPolicyErrors) => true);
httpClient = new HttpClient(handler);
Enter fullscreen mode Exit fullscreen mode

In Python, ignoring the certificate can be done with:

ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
Enter fullscreen mode Exit fullscreen mode

and then passing the "ssl_context" to the context parameter in the urllib.request.urlopen() method.

In Go, initializing a transport and then passing it to the client can look like:

transport := &http.Transport {
  TLSClientConfig: &tls.Config {
    InsecureSkipVerify: true,
  },
}
client := &http.Client {
   Transport: transport,
   
}
Enter fullscreen mode Exit fullscreen mode

Using the REST API

Now, let’s look at an example of how to use the REST API. This example will demonstrate authenticating with the “Traditional Template” project provided by Perforce. For other organizations, these item types may be named differently, but here the default terms of “issue”, “requirement”, “test case”, and “test run” will be used. The example code will be in C#, but it should be relatively straightforward to translate it into another programming language.

Initialization

First, we initialize the HTTP client with the base address and set the media type header.

// Using the handler we created earlier for the server certificate callback
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri("https://{API URL}/helix-alm/api/v0/");
// Make sure the headers are clear
client.DefaultRequestHeaders.Accept.Clear();
// Add "application/json" media type to the header
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Enter fullscreen mode Exit fullscreen mode

Access Token

Next, we will get an access token using the API key that was created for the REST API user.

// Be sure to URL escape the space
string url = "Traditional Template/token";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
string authorization = $"ApiKey {ApiKey}";
request.Headers.Add("Authorization", authorization);
AccessToken responseBody = await SendRequest<AccessToken>(request);
Enter fullscreen mode Exit fullscreen mode

Alternatively, the third line may be substituted with the basic authentication approach if desired.

SendRequest<T>() is our method that uses our HttpClient object to send the request to the specified endpoint using the HttpClient.SendAsync() method. T is a generic object type that the method expects returned from the response. Here, we have specified that the object to return is of type AccessToken. So what happens in our method is that it sends the request to the API, waits for a response, deserializes the JSON data into our AccessToken class, and returns the data to the caller.

The AccessToken class is relatively simple, as we saw earlier from the JSON data in the API’s response, containing only a token type, expiration date, and the token itself. This is easy for a JSON deserializer to handle. For more complex data that need serialization, we can pass JSON serializer options, from the System.Text.Json namespace, to our SendRequest<T>() method, depending on which object we are deserializing. For your programming language of choice, you will have to consult the documentation for how to handle de/serializing data in JSON.

Nonetheless, we now have our access token, which we will attach in the header for all subsequent HTTP requests. To attach the access token to the header, we can use a method such as:

private void SetRequestAccessToken(HttpRequestMessage request, AccessToken accessToken)
{ 
  string authorization = string.Format("Bearer {0}", accessToken.AccessToken);
  request.Headers.Add("Authorization", authorization);    
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this example we looked at how to authenticate a client. We first initialized our HTTP client, attached our API key in the authorization header, sent our GET request to the /token endpoint, and received an access token for our future requests.

There are more features and endpoints not covered here because their use will largely depend on the requirements of the individual organization in regards to its workflow and project management. However, this example should be enough to help anyone new to the Helix ALM REST API to get started.


Thank you for reading our article about the Helix ALM REST API, we hope you have become a little bit more knowledgeable about authenticating a client for the API. In part 2 we will look at retrieving items using the REST API and how to limit the number of items returned.

Mecomis has over 20 years of experience with using Helix ALM, so if you have further questions about Helix ALM or a general inquiry, please contact us.

Top comments (0)