C# Password-Based Application Example |
When your client application is a console app or service that does not present a BarTender Cloud sign-in interface to users, you must use password-based authentication. With this type of authentication, you manually grant authorized users the ability to access the BarTender Cloud API by entering their user name and password in your console app or service.
This example demonstrates how to use the sample "ResourceOwnerPasswordFlow" C# application to connect to BarTender Cloud and to generate the access token that is needed to send API requests to the server.
Note: To use this example, you must have Microsoft Visual Studio 2022 and .NET Core 8.0 installed. |
Step 1: Register a password-based application or service
Register a console application or service with BarTender Cloud, and then copy the application ID and secret for later use. To do this, follow these steps:
-
In BarTender Cloud, click BarTender Cloud API the left navigation pane of the Manage Cloud Account view to display the BarTender Cloud API page.
-
Click Register Application for Password-Based Access.
-
In the Register Password-Based Access dialog, complete the following fields:
-
Name: Specifies a name for the application or service. This is the "friendly" display name.
-
Description: Specifies an optional description for the application or service.
-
Click Register. The dialog closes, and your newly registered application or service is listed on the BarTender Cloud API page.
-
Make a note of the application ID and secret for the application or service. To do this, click , and then click View ID & Secret. Click for each value to copy it to the clipboard, and then paste it into a safe location.
For more information about how to register your application or service, refer to Authentication.
Step 2: Enable password-based access for your user account
-
In BarTender Cloud, click Users in the left navigation pane of the Manage Cloud Account view to display the Users page.
-
Next to the user to whom you want to grant password-based access to the API, click , and then click Edit.
-
In the user information dialog, select Allow password-based API access, and then click Save.
Step 3: Download the sample C# application
Download the "ResourceOwnerPasswordFlow" C# project from the following web page:
This is a simple C# application that you will use to connect to the BarTender Cloud API and generate an access token that you can then use to make API requests.
Step 4: Run the sample application
-
In Visual Studio, compile and run the ResourceOwnerPasswordFlow.csproj project file from the folder that you downloaded.
-
In the command prompt window, enter the following information to connect to BarTender Cloud:
-
Your BarTender Cloud URL
-
Application ID that you saved previously
-
Application secret that you saved previously
-
User name of the user account that you configured previously
-
Password of the user account that you configured previously
-
The sample application returns an access token in the command prompt window. Copy this token, and then use it in your script to make an API request.
Using Refresh Tokens
BarTender Cloud applications use access tokens when they invoke REST APIs. Access tokens are used to provide the identity of the user who is invoking the API, which allows the API to verify that the user is allowed to perform the requested operation. For security reasons, access tokens have a limited lifespan. After this lifespan expires, the token will stop working.
There are two options to address this:
-
Re-authentication: This method involves prompting for the user’s credentials and requesting a new access token. The disadvantage of this method is that forcing the user to re-enter their credentials is usually disruptive to the end-user experience.
-
Token renewal: For applications that are registered to support token renewal, a refresh token can be returned along with the access token during the authentication process. This refresh token is used to request an updated access token without requiring the user to re-enter credentials.
To support console and service applications, code must be run to request the updated (refreshed) access token, as demonstrated in the following code samples.
Note: In the code, the strings that are associated with "organizationIdentifier," "username," "password," "client_id," and "client_secret" are only examples. Replace these values with values that are applicable to your organization, user, and application. |
Retrieve an access token and a refresh token
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(
"application/x-www-form-urlencoded"
));
// This sample assumes that the organization, user, and application are located in the am1.bartendercloud.com cluster.
client.BaseAddress = new Uri("https://auth.am1.bartendercloud.com/connect/token");
var contentBodyList = new List<KeyValuePair<string, string>>();
// Provide values that are required to request an access token by using the OIDC Resource Owner Password Flow.
contentBodyList.Add(new KeyValuePair<string, string>("username", "email@company.com"));
contentBodyList.Add(new KeyValuePair<string, string>("password", "XXXXXXXX"));
contentBodyList.Add(new KeyValuePair<string, string>("client_id", "b-7928-49c5-8121-b3023525a914"));
contentBodyList.Add(new KeyValuePair<string, string>("client_secret", "tHjCUZtEv2zow1QevqrD0yAnyEdZfU523ZJ+LxiH3bQJ9HfrchFlugNUmSn8lpFDtLB/macxpS9K7+TUIL2n5Q=="));
contentBodyList.Add(new KeyValuePair<string, string>("audience", "https://BarTenderCloudServiceApi"));
contentBodyList.Add(new KeyValuePair<string, string>("grant_type", "password"));
// The string "offline_access" that is included in the following scope requests that a refresh
// token should be included in a successful response.
contentBodyList.Add(new KeyValuePair<string, string>("scope", "openid profile BarTenderServiceApi offline_access"));
// Token requests must identify the organization against which the token is being requested.
// This ensures that the application, identified by "client_id" above, has been permitted to
// operate against the organization and that "username" and "password" can be used
// to identify a member of this organization.
string organizationIdentifier = "my-organization";
string queryParam = $"?OrganizationDnsName={organizationIdentifier}";
// Form a POST request using the data from above.
var request = new HttpRequestMessage(HttpMethod.Post, queryParam) {
Content = new FormUrlEncodedContent(contentBodyList)
};
HttpResponseMessage msg = client.SendAsync(request).Result;
if (msg.IsSuccessStatusCode)
{
// Upon success, the tokenInformation variable will include a JSON response with the following fields:
// access_token – A string that contains the access token
// expires_in – The number of seconds until the access token expires
// token_type – The access token type; this value will always be "bearer"
// refresh_token – A string that contains the refresh token
// scope – "BarTenderServiceApi offline_access openid profile"
string tokenInformation = msg.Content.ReadAsStringAsync().Result;
}
The following JSON-formatted content represents the value that is assigned to "tokenInformation" in the previous sample:
{
“access_token”: “eyJhbGciOiJSUzI1NiIsImtpZCI6IkM5QzNFM0NFRjZFREFBNTIyM0M2QTUyQ0M1NTFDMzI1IiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE3MjQxOTU1MjUsImV4cCI6MTcyNTA1OTUyNSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNjAiLCJhdWQiOiJodHRwczovL0JhclRlbmRlckNsb3VkU2VydmljZUFwaSIsImNsaWVudF9pZCI6ImVlNjAzNmRiLTc5MjgtNDljNS04MTIxLWIzMDIzNTI1YTkxNCIsInN1YiI6ImE0ODhjMWM0LWY2YTQtNDNlYS04ZDE4LWM3NWI3YWY5ZjViMCIsImF1dGhfdGltZSI6MTcyNDE5NTUyNSwiaWRwIjoibG9jYWwiLCJodHRwczovL0JhclRlbmRlckNsb3VkLmNvbS9UZW5hbnRJRCI6ImE3NGE1MDRjLTc2NTItNDliMC05NjA1LWM4N2YwY2ZkN2M0NSIsImh0dHBzOi8vQmFyVGVuZGVyQ2xvdWQuY29tL1VzZXJJRCI6ImZiNjQ1YTBlLWQ0MDUtNDliNi1iNTgwLWY2MDNmNzUzZTc3ZSIsImh0dHBzOi8vQmFyVGVuZGVyQ2xvdWQuY29tL0RhdGFDZW50ZXJVUkkiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAvIiwianRpIjoiRkNDQjhGQTE3NTEwMDI0MzNDOEEyRkQ0RjdGRUVEOEQiLCJpYXQiOjE3MjQxOTU1MjUsInNjb3BlIjpbIkJhclRlbmRlclNlcnZpY2VBcGkiLCJvcGVuaWQiLCJwcm9maWxlIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.q6a945NFuGYgD31hcUf_qFmGXjrVn3kFHPTBBYcmbHkuy2P7YBC5eoVWROdQpOioa5ztZjgbVmDhZPvyogloTu4H719SVb4XQGbSgcnCZDGTtqtkPB5bzyaxXap7Uj7B9OcO214O7WnxJoqywUEw2X8z49CN2WGTRpNqCjdrER4nJw1YDNMcKp-kD6yYJ-fICAPox6nFXEGBx371T-HcPO-pPx4jCxyjfq3gNotS224d33tmb1Dz-htYlowcM1zvOTi61gSDuHLtZQ66JCIB0_QfztiuwX760UoyZniPuAhyjB9rEXbsmzy9YteHJIYp74_Yh299vOM8th3Y8Yfgkw”,
“expires_in”: 864000,
“token_type”: “Bearer”,
“refresh_token”: “DD567BC9B4073E28A1B1954557DF2AC3D029EAF7B3126308585958115DD98DDE”,
“scope”: “BarTenderServiceApi offline_access openid profile”
}
Until the token expires in 864000 seconds (10 days), the value in the “access_token” field can be used to make REST calls against the BarTender Cloud API. After this window of time elapses, any usage of the access token will result in an HTTP error code. This means that prior to expiration, the value in the “refresh_token” field should be used to acquire a new access token so that REST calls may continue to be made without interruption.
Use a refresh token to get an access token
// This sample assumes the organization, user, and application are located in the am1.bartendercloud.com cluster
string organizationIdentifier = “my-organization”;
string refreshUrl = $“https://auth.am1.bartendercloud.com/connect/token?OrganizationDnsName={organizationIdentifier}”;
string refreshToken = “DD567BC9B4073E28A1B1954557DF2AC3D029EAF7B3126308585958115DD98DDE”;
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, refreshUrl);
var collection = new List<KeyValuePair<string, string>>();
collection.Add(new("grant_type", "refresh_token"));
collection.Add(new("client_id", “b-7928-49c5-8121-b3023525a914”));
collection.Add(new("client_secret", “tHjCUZtEv2zow1QevqrD0yAnyEdZfU523ZJ+LxiH3bQJ9HfrchFlugNUmSn8lpFDtLB/macxpS9K7+TUIL2n5Q==”));
collection.Add(new("audience", $"https://BarTenderCloudServiceApi"));
collection.Add(new("refresh_token", refreshToken));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
var msg = client.SendAsync(request).Result;
if (msg.StatusCode == HttpStatusCode.OK)
{
// Upon success, the variable tokenInformation will include a JSON response with the following fields:
// access_token – A string that contains the new access token
// expires_in – The number of seconds until the access token expires
// token_type – The access token type; this value will always be "bearer"
// refresh_token – A string that contains the new refresh token
// scope – “BarTenderServiceApi offline_access openid profile”
string tokenInformation = msg.Content.ReadAsStringAsync().Result;
}