Careers   |   Events   |   Contact   |   402.238.1399   |   contactus@deliveron.com

Deliveron
Connect with us on FacebookConnect with us on LinkedInFollow Us on Twitter

Category List


Tag List

deliveron alm delivery guidance (2)
Azure (14)
jquery (4)
ssas (2)
razor (4)
AzureAD (1)
rest assured (1)
cascading-dropdown (2)
sql saturday (2)
tfs 2012 (4)
Collaboration (2)
Java (1)
Nuget (1)
xaml (2)
tfs (11)
business insight (2)
IntelliSense (1)
load tests (2)
kanban (1)
MSBuild (1)
Keith Holt (1)
json (2)
licensing (2)
deliveron agile delivery process (2)
installation (2)
Office 365 (1)
msi (2)
microsoft case study (2)
MFA (1)
subsites (2)
Automated Testing (10)
mvvm (2)
webparts (2)
team build (2)
swagger (1)
Decisions (2)
sharepoint 2007 (2)
Power BI (3)
github (1)
OAuth2 (1)
outlook (2)
microsoft test manager (2)
lunch and learn (2)
alm rangers (1)
whitesource (1)
sharepoint 2013 (6)
application insights (2)
Cosmos DB (1)
requirements (2)
Visual Studio Online (6)
webpack (1)
asp.net-mvc-4 (2)
insiders (1)
sharepoint 2010 (10)
artifacts (1)
performance (3)
windows 8 store app (2)
service-fabric (1)
adfs (3)
tfs 2013 (2)
test agent (2)
dependency-injection (2)
tips (2)
top 5 (1)
bi (2)
vsdbcmd (2)
fluentvalidation (2)
load testing (2)
web deploy (1)
Business (2)
windows azure (2)
power tools (2)
c# (13)
work item (2)
tags (2)
angular 2 (3)
wiki (1)
Web API (1)
testing (5)
continuous inegration (2)
tfs 2017 (1)
CI (3)
sp1 (2)
HOLs (1)
lab management 2010 (2)
react (1)
security (1)
selenium (4)
owasp (3)
my work (2)
opensource (1)
ninject (2)
web performance tests (2)
DevOps (14)
test cases (2)
Functions (2)
release management (7)
coded ui tests (6)
visual studio team services (1)
sharepoint (5)
ssl (1)
home projects (1)
microsoft alm rangers (2)
ARM Template (1)
agile (12)
table-valued-parameters (4)
nintex (4)
netstandard (2)
event-handling (2)
dns (2)
faq (2)
lync (2)
Mike Douglas (4)
Big Data (2)
entity-framework (6)
AAD (2)
storyboarding (2)
code-first (4)
team foundation server (6)
automatedui (1)
mstestv2 (1)
onenote (4)
gulp (2)
tfs 2010 (2)
Template (1)
reporting (2)
lab environments (1)
webs (2)
Analytics (2)
continuous integration (2)
asp.net-mvc-3 (4)
Azure Functions (1)
silverlight (2)
feedback (2)
powershell 2.0 (8)
single page applicaiton (1)
Visual Studio 2017 (4)
xunit (1)
test automation (1)
angular (1)
team foundation 2012 (2)
visual studio (8)
Node.js (1)
action-filters (2)
deployment (2)
sql server (2)
site collections (2)
asp.net-mvc-routing (2)
video (2)
Document (1)
scrum (8)
certificates (2)
pdf (2)
REST (1)
azure mobile services (2)
Multi-Factor Authentication (1)
asp.net-mvc (6)
selinium (1)
API Tests (1)
spc14 (4)
bdd (2)
wit (2)
web application firewall (1)
workflow (2)
DevSecOps (2)
nebraska code camp (2)
visual studio 2010 (18)
visual studio 2012 (10)
webcast (4)
TFS 2015 (6)
data warehousing (2)
TestArchitect (5)
preview (1)
Meetings (1)
2013 (2)
whitelist (1)
Quality (2)
AzureAD Admins (1)
Powershell (1)
tokenization (1)
performancepoint services (2)
team foundation server 11 beta (2)
database publishing wizard (2)
team web access (2)
team foundation server 2012 (4)
Infrastructure (1)
pipelines (1)
nunit (1)
database projects (4)
azure resource manager (1)
visual studio code (1)
association (1)
ssrs (4)
exchange (2)
burndown (2)
alerts (2)
M Query (1)
pipeline (1)
test controller (2)
alm (9)
connect() (1)
necc (2)
MVP (2)
planning poker (4)
sql server 2008 (2)
gherkin (2)
team deploy (2)
dbpro (2)
example (2)
Data Analytics (1)
fields (2)
Build (6)
visual studio 11 beta (2)
tfs odata (2)
PBI (1)
serverless (3)
web (1)
business intelligence (2)
vsts (22)
user profiles (4)
zap (1)
javascript (3)
bundling (2)
tls 1.2 (1)

Archive

Three Ways to get an OAuth2 Access Token for API Testing for Azure AD Secured APIs

Jun 24, 2018

Automated testing has never been more critical in improving the frequency of releases without sacrificing quality.   API tests are often used to validate functional requirements and run much faster than UI tests.   One challenge with executing API tests is that many modern websites and the APIs are protected by Azure Active Directory (AAD) identity.  Fortunately there are some different approaches for obtaining the credentials to securely call the APIs from the automated API tests.  In this post I will discuss some of the various ways to accomplish this.

First, before we talk about how we get the credentials to call the service let's discuss how to call a secured API.  Most modern applications use OAuth2 to allow authorized users access to the APIs.  One of the benefits of OAuth2 is flexible and allows different types of applications to be authorized in different ways. The different ways are called Grants.  I'll mention the names but I'll focus more on the how to use it.  Once you are have been authorized by one of these approaches, you will have an access token to call the API. To make an authorized call to the service, a valid access token is passed as an authorization header in each call.  So regardless of which of the following approaches below is used, each will call the service the same way.

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = httpClient.GetAsync(todoListBaseAddress "/api/todolist").Result;

The following examples are using ADAL.NET library Microsoft.IdentityModel.Clients.ActiveDirectory that can be downloaded from NuGet.

Use a Native App to sign on via Resource Owner Password Credential Grant

I mentioned that an app registered as a web app/API app doesn't have a flow to handle accepting the username and password to retrieve the access token.  However, the other option when registering an app allows you to register an app as a Native app.  This approach is called Resource Owner Password Credential Flow and requires a username and password for authentication.  A native application is typically a mobile app and the app includes the sign on page.  If you or an AAD admin can register a native app, this can be used for automated testing.  I like this approach the best because the sign on can be done by code and it uses an account to retrieve specific authorization roles/claims.  This allows you tests to validate specific authorization rules in you API for different test users and roles.  There are some downsides to this approach and doesn't work in all scenarios.  This approach does not work with Microsoft Accounts (MSA), Multi-Factor Authentication (MFA), and if you application requires consent.

To register a native application in Azure, navigate from the portal to AAD > App Registrations > New App Registration.

create-native-app.jpg

Grant permission for the new app registration to have access to API.  Open the app registration and choose Settings > Required Permissions > API Access > Select Service

app-registration-add-api-access.jpg

 

Add the permission for API Access

add-permission-for-api-access.jpg

 

Click on Grant Permission to delegate permission to all users. If you fail to do this you will see an error message similiar to this below.
AADSTS65001: The user or administrator has not consented to use the application.

grant-permission.jpg

 

 

The clientId is the application id from the new Native App registration.

string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

 

UserPasswordCredential uc = new UserPasswordCredential(user, password);
var authContext = new AuthenticationContext(authority);

 

var result = authContext.AcquireTokenAsync(todoListResourceId, clientId, uc).Result;

 

accessToken = result.AccessToken;

 

 

More info
http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/

Send the Client Secret via Client Credentials Grant

If creating a native app isn't an option, a similar alternative is to use the client application secret key from the AAD app registration settings.  This option is is known as Client Credentials Grant.  This requires a the ability to securely keep the secret key of the application.  Ensure that this is the key for the QA / test environment and it is a separate key than what is used in the application in case it is compromised.  One downside to this approach is that the client secret is global for the application so you would have to use something else to test roles / claims authorization in the API.

To create the key, navigate to you app registration > Settings > Keys to create a new key and Save.

add-client-secret.jpg

 

Set this clientSecret equal to the key.

string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

var authContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential(clientId, clientSecret);

var result = authContext.AcquireTokenAsync(todoListResourceId, clientCredential).Result;

accessToken = result.AccessToken;

More info
https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Client-credential-flows

Use a automated UI Test to get the access token via Authorization Code Grant

The third option is not as straight forward as calling an API but this option doesn't require the application administrators giving any kind of secret or building something separately.  This option requires the assistance of a UI test to use the application's sign on page.  This allows the application's normal authentication process to occur.  Once your UI test signs in to the application, the access token is stored in local storage.  I am using Selenium in this case and within Selenium, the JavaScript executor allows access to the DOM and application settings such as local storage.  Use the browser dev tools to look to see the token name.  Once, we have the access token, we can use it in all of our tests as long as stay valid.  Probably the biggest downside of this approach is that a different tool has to be used to get the token.  It can still be done headless so it doesn't require an agent to be configured to run UI tests.

// UI Sign on Test
var driver = Browser.Open(url, browser);
SignOnPage signonPage = new SsoSignOn(driver);
var homePage = signOnPage.Logon(username, password);

// Retrieve Access Token after user is signed in
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
string accessToken = (string)js.ExecuteScript("return window.localStorage.getItem('adal.access.token.keycd123')");

Only Retrieving the Access Token once and Keeping the Access Token Valid

The typical access token stays valid for 1 hour. If you are using the 3rd approach and retrieving the access token using a UI test, you probably don't want this to have to occur for every API test.  Additionally, if you API tests run longer than an hour, you will need to handle with your code.   You could use the singleton pattern to only retrieve the token once and keep it in memory if it has already been retrieved.  The access token also states how long it is going to be valid.  In addition to retrieving the stored token, check to see if the token is close to expiring.  If the token is 15 minutes from expiring, retrieve a new access token with a new 1 hour expiration to continue running tests.  This sounds like a good next post.

As always, if you have any questions or comments, reach out to me on Twitter at @mikedouglasdev.



Category: Test Automation

Mike Douglas

user_avatar

He is a solution consultant focused on helping organization build high quality application effectively utilizing DevOps practices. He is a Microsoft DevOps / ALM Ranger and you can reach him on Twitter at @mikedouglasdev


We believe in helping our customers create software solutions in a better way.
We do this by having a project delivery process and technology expertise that ensures we are solving the right problem in the right way and driving the most business value.