security_DxO

Using PowerShell to Authenticate Against OAuth

From development to deployment, PowerShell is becoming the ‘go to’ automation technology on Microsoft Azure. So, I decided to use PowerShell to perform automated tests against a Web API (a.k.a REST service). These tests are built to run during the execution of a Continuous Release cycle and confirm that the API is responding as expected.

The Web API I’m testing is exposed to the outside world through Microsoft Azure API Management. Therefore, consumers of my API must subscribe and must use a Subscription Key for every request. This key is used to authenticate against Microsoft Azure API Management, which acts as a proxy between the outside world and the Web API. The Subscription Key does not authenticate the client against the Web API. Therefore, clients must authenticate by posting requests to the OAuth endpoint.

Getting an Access Token from OAuth on Azure API Management

#OAuth Basic Token
$basicToken = 'Basic lots-of-alphanumerics=='

#API Management URL & Key
$url = 'https://test.azure-api.net/api/token'
$subscriptionKey = 'lots-of-alphanumerics'

#Service User Info
$username ='brisebois'
$password = 'zxcvbnm'

#Getting an Access Token
$context = Get-ApiToken -methodUrl $url -username $username -password $password -authorization $basicToken -subscriptionkey $subscriptionKey

#Testing the AccessToken by making a GET request against the API
$peoplelistUrl = 'https://test.azure-api.net/api/people'

$peopleList = Get-ApiResource -methodurl $peoplelistUrl -oauthContext $context -subscriptionkey $subscriptionKey

Wait! How Does That Work?

First I need a Data Transfer Object (DTO). This DTO will be used to make subsequent secured calls to the Web API.

Add-Type @'
    using System;
    public class OAuthContext{
        public string AccessToken{get;set;}
        public string TokenType{get;set;}
        public string ExpiresIn{get;set;}
        public string RefreshToken{get;set;}
    }
'@

Using Invoke-RestMethod to authenticate against an OAtuh endpoint, I encapsulate the response in an OAuthContext instance. I decided to use Invoke-RestMethod instead of Invoke-WebRequest because it automatically applies ConvertFrom-Json to the response. This is quite useful, because I can work directly with the object.

Headers for the request need an IDictionary collection. In PowerShell, we use a Hash collection to store key/value pairs. I really want to highlight this, because it took me a couple of minutes to find out how to satisfy the IDictionary dependency. The following will create a collection to which you can add your headers.

$dict = @{}
$dict.Add('Authorization',$authorization)

I’m sure I could have done this differently, but considering that I’m still new to PowerShell, I’m pretty happy with the outcome. The following builds a request that is used to authenticate against an OAuth endpoint that is exposed through Microsoft Azure API Management. Notice that I systematically add the Subscription Key as a query string, this is done so that Microsoft Azure API Management allows us to reach the API.

function Get-ApiToken([string]$methodUrl, [string]$username,[string] $password,[string] $authorization, [string] $subscriptionkey)
{
  $methodtype = 'POST'
  $contentType = 'application/x-www-form-urlencoded'

  $dict = @{}
  $dict.Add('Authorization',$authorization)

  $methodURL = $methodURL+'?subscription-key='+$subscriptionkey

  $body = [System.Text.Encoding]::UTF8.GetBytes('grant_type=password&username='+$username+'&password='+$password) 

  $response = Invoke-RestMethod -Method $methodtype -Uri $methodUrl -Headers $dict -ContentType $contentType -Body $body

  $context = New-Object OAuthContext

  $context.AccessToken = $response.access_token
  $context.ExpiresIn = $response.expires_in
  $context.RefreshToken = $response.refresh_token
  $context.TokenType = $response.token_type

  return $context
}

To test the acquired Access Token I perform a GET request against a resource exposed by my Web API. The following creates a GET request and returns the Json payload as an object to the caller.

function Get-ApiResource([string]$methodurl,[OAuthContext]$oauthContext,[string]$subscriptionkey)
{
	$headers = @{}
	$headers.Add('Authorization',$oauthContext.TokenType + ' ' + $oauthContext.AccessToken)

	$methodtype = 'GET'
	$methodurl = $methodurl+'?subscription-key='+$subscriptionkey

	return Invoke-RestMethod -Method $methodtype -Uri $methodurl -Headers $headers
}

That was Cool, What’s Next?

The goal of this post was provide a happy path REST call against a Web API exposed through Microsoft Azure API Management. These examples lack error handling, retry policies and everything else needed to create robust solutions. Use this is a starting point, but remember that it still needs a lot of love.

Do you use PowerShell to make requests to Web APIs (a.k.a REST services)? Have you done this using different a technique? I very curious to find out what I missed.

5 responses to Using PowerShell to Authenticate Against OAuth – #Azure API Management

  1. 

    Nice job!! This is sweet!

    Like

  2. 

    Where did you get the OAuth Basic token from in this example?

    Like

  3. 

    I’m also interested where you go the OAuth Basic Token from.

    Like

    • 

      Hey calrain, I ended up writing a PowerShell function to do somewhat based on this article and others. I can always post it on my blog if you are still looking for a solution.

      Liked by 1 person

Trackbacks and Pingbacks:

  1. Dew Drop – August 14, 2014 (#1836) | Morning Dew - August 14, 2014

    […] Using PowerShell to Authenticate Against OAuth – #Azure API Management (Alexandre Brisebois) […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s