Using jwt.io to verify the signature of a JWT token

Introduction

In an asymmetric algorithm, a JWT token is signed with an Identity Provider’s private key. To verify the signature of the token, one will need to have a matching public key. This post will cover how to use the JWT tool at https://jwt.io/ to verify the signature of an signed Azure AD token (either access or id token).

Note:

  • You should only validate the token intended for your own resource.  Using the technique below to validate the signature of a Microsoft First Party Apps token (for example token audience is for Microsoft Graph resource) may fail.
  • http://jwt.io utility is a 3rd party tool.  We (Microsoft) have no knowledge of how this site utilizes the token information.
  • To see the token claim information, we recommend using the Microsoft utility http://jwt.ms since the site does not cache token information.

Verifying the token signature

  1. Browse to https://jwt.io/ and paste the JWT token into Encoded text box. The tool should automatically detect the token’s signature algorithm (RS256) and displays the token into 3 parts: header, payload, and signature. Note the “kid” field in the header. This is the key id of the certificate used to sign the token

    Scrolling down a little you will see the version of the token (v1 token in this case) and it will say “invalid signature”. This is expected since at this point we have not provided any certificate info for the tool to verify the token signature.

  2. Find the jwks URL info from Azure AD’s OIDC well-known endpoint. Depending upon your token version, use the correct well known endpoint (make sure to supply the correct tenant name in the well known URL):

    V1 token: https://login.microsoftonline.com/{tenant name}/.well-known/openid-configuration

    V2 token: https://login.microsoftonline.com/{tenant name}/v2.0/.well-known/openid-configuration

    For my case, I use the V1 OIDC endpoint. You can either paste the URL into a web browser or postman to find the “jwks_uri” field from the response:

  3. From the JWKS URI endpoint, find the key that has a matching kid (key id) as the token. Copy the long text string from the key’s x5c field. This is the public key section

  4. Enclose the x5c string in the BEGIN CERTIFICATE / END CERTIFICATE block as followed (see example at the end post)

    ‑‑‑‑‑BEGIN CERTIFICATE‑‑‑‑‑

    MIIDBTCCAe2gAwIBAgIQKOfEJNDyDplBSXKYcM6UcjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE4MTIyMjAwMDAwMFoXDTIwMTIyMjAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8ZT56lunzbgm3a4QxM8BiVbsd4j77bf/K/rhxyCmuwv2/7seYXsDTEvdUoFD2Tq7Km+eLh4/+yDViqihLRXOGD/NxYbLP7jv5k/e3MxDbOM1mkjfRMMPxc9+sav7meue+dJRysF0CdQP6XvlToDZT4PBAou5nkAydOa/N/HrtY6ShY8ZEK3URUy4GLUUO08V/s80cqEUfIqiXOkb54o4dffmH1rQbAiNa9du0hWpFAa2P2SrCshPSjVlC+x+uRMhUTYCvNF32L4UJRsN/gI39vH4u9cFvgcqStW0wgK88F+84Bdx+j9bvDyqLEjkjf0PfkHPV/kf2Pt2zqTiIizr8CAwEAAaMhMB8wHQYDVR0OBBYEFC//HOy7pEIKtnpMj4bEMA3oJ39uMA0GCSqGSIb3DQEBCwUAA4IBAQAIYxZXIpwUX8HjSKWUMiyQEn0gRizAyqQhC5wdWOFCBIZPJs8efOkGTsBg/hA+X1fvN6htcBbJRfFfDlP/LkLIVNv2zX4clGM20YhY8FQQh9FWs5qchlnP4lSk7UmScxgT3a6FG3OcLToukNoK722Om2yQ1ayWtn9K82hvZl5L3P8zYaG1gbHPGW5VlNXds60jIpcSWLdU2hacYmwz4pPQyvNOW68aK/Y/tWrJ3DKrf1feDbmm7O5kpWVYWRpah+i6ePjELNkc2Jr+2DchBQTIh9Fxe8sz+9iOyLh9tubMJ+7RTs/ksK0sQ1NVScGFxK+o5hFOOMK7y/F5r467jHez

    ‑‑‑‑‑END CERTIFICATE‑‑‑‑‑

  5. Now copy entire text above into the 1st textbox under “Verify Signature” section and the Invalid Signature text should change to “Signature Verified”

 

Conclusion:

The above steps show a manual way to validate the JWT token’s signature given the certificate’s public key.

References:

https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-openid-connect-code

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc

for clarity:

Example public certificate section

5 dashes followed (no space) by BEGIN CERTIFICATE followed by 5 dashes. The end section is in the same format

-----BEGIN CERTIFICATE-----
MIIC8DCCAdigAwIBAgIQUdK9w17K+rNOSRJZP83bIjANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDEylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZpY2F0ZTAeFw0xOTA0MTgwMDU5MzNaFw0yMjA0MTgwMDU5MzNaMDQxMjAwBgNVBAMTKU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQgU1NPIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArkGIwWMl5Z6bQDsRZocoylG2Nf91JlBWbGKULJCu8yzoFT5C4JgJ6qoYXjKNIq/+DI8aWsxMclYHmsTRl8JMWaCH1K4BaApYGPYLBjL8DKXm+ELSp9VyAPzD+FYElGCpU+B3FvWcEQvGFBzajhn17J5zutN6I8rGngIK0ewqpekGV85CEFQ5EFwgx7lkF5PLvgiTBq08b8xNB3f0laSGMH7MYjDmGh//Zb2QT/6S7ZzB85YnGtlOxaLjKeYcM8hBdVK5lYqvQb7a0GWmUxmlwClwN3XpBBdg274hBG4ynkWLnx/0Vb5/RfWa0HCRa4JK28sfI/VufdR0SJ+WBZWXZwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA6IpznhiMSBayXGZaw0o8mPtI9qkXaFF5kDLqZFYN1tVTAukG3Q//PPnwsGLdRHFGOn3OwPNwo7XtmM6iyIunKAjTqtf7zA53umWirJzq85l6NVpqtQf7CABOzY3I6NKEa7wmYPBD6Egh6PqJO9O1ppAqJT4z/0lYTIEac7KYMdv/FwpYd0w4Y4gbYtRODO9iQwAXzzM243oM8XSrrqQj3smfNyrZfZS8XWvjQGJy9MTn2Ybvy9IUhVwEWJTyeTKBhnBk9ujNCcEG4kAYL1uWGun+dT2h4vbyNKxMlomryz3actMp90QEefZTZ/kOxqAthenbou+WF0OfhCH9Zhd04
-----END CERTIFICATE-----

Troubleshooting network related issue when using ADAL authentication library

Problem:

The problem described in this post is often seen in enterprise environment where the customer uses ADAL.Net library to run code like the following from their corpnet machine to authenticate to Azure Active Directory with a Federated account. The network topology in a corporate environment is often complex with multiple security measure put in place (proxy, firewall, router, etc…) to protect the LAN environment from the internet. Unfortunately, these security restrictions can cause problem when a request needs to reach Azure AD internet endpoint (login.microsoftonline.com) and/or ADFS server (or other Federated Server) to complete the authentication handshake.

[code lang=”csharp”]var authenticationContext = new AuthenticationContext(AuthorityUrl);

AuthenticationResult authenticationResult = null;

// Authentication using master user credentials

var credential = new UserPasswordCredential(Username, Password);

authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, ApplicationId, credential);

return authenticationResult;

[/code]The AcquireTokenAsync call on line 9 above can result in Exception such as the following:

Case 1: Error:

Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: unknown_error: Unknown error —> System.Threading.Tasks.TaskCanceledException: A task was canceled.

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()

at Microsoft.IdentityModel.Clients.ActiveDirectory.HttpClientWrapper.<GetResponseAsync>d__30.MoveNext()


at PowerBIEmbedded_AppOwnsData.Controllers.HomeController.<EmbedReport>d__9.MoveNext() in C:\Users\xxx \App Owns Data\PowerBIEmbedded_AppOwnsData\Controllers\HomeController.cs:line 49


ErrorCode: unknown_error

StatusCode: 408

Or

Case 2: Error

System.Net.Http.HttpRequestException: An error occurred while sending the request. —> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)

at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)

..

Analysis:

In these scenario, traditional troubleshooting technique using either ADAL logging or Fiddler does not yield much info since the problem lies deep in the socket connection layer. For the first Exception a quick search for error code 408 discussed here and here tells us that the request is timed out somewhere, but which request? The latter Exception in Case 2 provides a little context in revealing that some remote host is shutting down our request connection. There is quite a bit of work going on for a Federated account happening in the AcquireToken call:

  1. A home realm discovery request is made to Azure AD to find out where to send the authentication request to
  2. A request is then made to the Federated Identity Provider endpoint (usually ADFS server) to get the meta data info
  3. The account is sent to the Federated authorization endpoint for authentication to get a SAML token
  4. A request is then sent to Azure AD token endpoint with the SAML token to exchange for an OAuth2 token

We need to know how far in the pipeline this authentication mechanism is made before encountering an Exception and what is the URL and IP Address of the endpoint causing the exception. As I mentioned above unfortunately ADAL logging is not detailed enough to shed much info. In the above Case 2 Exception this is what ADAL logging looks like:

[ADAL]-Information 2019-01-04T18:22:04.1279473Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: ADAL PCL.Desktop with assembly version ‘4.4.2.0’, file version ‘4.4.2.0’ and informational version ‘4.4.2’ is running…

[ADAL]-Information 2019-01-04T18:22:21.1473375Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: === Token Acquisition started:

    CacheType: null

    Authentication Target: User

    , Authority Host: login.microsoftonline.com

[ADAL]-Verbose 2019-01-04T18:22:23.2660794Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: Loading from cache.

….

[ADAL]-Information 2019-01-04T18:22:23.3500878Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: Checking MSAL cache for user token cache

[ADAL]-Information 2019-01-04T18:22:23.3640906Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: Sending request to userrealm endpoint.

[ADAL]-Error 2019-01-04T18:22:25.5532973Z: fca00bbf-d7f2-4ec3-bb76-c5f828aa1854 – AdalLoggerBase.cs: Exception type: System.Net.Http.HttpRequestException

—> Inner Exception Details

Exception type: System.Net.WebException

—> Inner Exception Details

Exception type: System.IO.IOException

—> Inner Exception Details

Exception type: System.Net.Sockets.SocketException

at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)

All we can tell from the above is that that the Exception happens after we send a home realm discovery request. Not too much to go on from here….

A corresponding for Fiddler trace for Case 2 looks like this:

The Fiddler trace tells us that the home realm discovery request (frame 20) is successful. The next expected request should be made to the ADFS server metadata endpoint (I know this from the tunnel request in frame 21 and 22) and that is missing in this trace. At this point we have an inkling that the ADFS server might have aborted our SSL connection (based on the error message) …

System.Net tracing and Network capture to the rescue….

Instruction to capture system.net tracing and Network capture are below at the end of this post. Both System.Net log and Network capture can provide extremely valuable information about the low-level TCP IP socket connection between the 2 end points. They tell us info about how the socket connection is initialized and established between the 2 IP addresses and if there is any problem with the connection.

Below is snippet of the System.Net log for Case 1:

System.Net Verbose: 0 : [17420] Entering HttpWebRequest#48342929::HttpWebRequest(uri: ‘https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=https://login.microsoftonline.com/<tenant id redacted>/oauth2/authorize’, connectionGroupName: ‘1954745’)

ProcessId=17212

DateTime=2018-08-28T21:36:56.4706363Z

System.Net Verbose: 0 : [17420] Exiting HttpWebRequest#48342929::HttpWebRequest()

ProcessId=17212

DateTime=2018-08-28T21:36:56.4716363Z

System.Net Verbose: 0 : [17420] Entering ServicePoint#51812814::ServicePoint(login.microsoftonline.com:443)


System.Net.Sockets Verbose: 0 : [9244] Entering Socket#59411631::InternalEndConnect(ConnectOverlappedAsyncResult#21067700)

ProcessId=17212

DateTime=2018-08-28T21:37:17.5366363Z

System.Net.Sockets Error: 0 : [9244] Socket#59411631::UpdateStatusAfterSocketError() – TimedOut

ProcessId=17212

DateTime=2018-08-28T21:37:17.5376363Z

System.Net.Sockets Error: 0 : [9244] Exception in Socket#59411631::InternalEndConnect – A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond <IP Address redacted>.

ProcessId=17212

DateTime=2018-08-28T21:37:17.5386363Z

..

System.Net Error: 0 : [15916] Exception in HttpWebRequest#48342929:: – The request was aborted: The request was canceled..

ProcessId=17212

DateTime=2018-08-28T21:37:26.5476363Z

System.Net Verbose: 0 : [15916] Entering HttpWebRequest#48342929::EndGetResponse()

ProcessId=17212

DateTime=2018-08-28T21:37:26.5516363Z

System.Net Error: 0 : [15916] Exception in HttpWebRequest#48342929::EndGetResponse – The request was aborted: The request was canceled..

ProcessId=17212

DateTime=2018-08-28T21:37:26.5526363Z

System.Net Information: 0 : [15916] ServicePoint#51812814::CloseConnectionGroupInternal(1954745)

ProcessId=17212

DateTime=2018-08-28T21:37:26.5566363Z

We can tell from the above log that the request fails very early in the home realm discovery stage. The client sends a request to Azure AD (login.microsoftonline.com) but that request is timed out We tried running the same code in an Azure VM outside of the customer’s environment and that worked fine. This is enough evidence to conclude that the Azure AD endpoint is reachable and something within the customer’s environment is blocking our request.

Below is the snippet of the System.Net for Case 2:

System.Net Verbose: 0 : [32820] Entering HttpWebRequest#59312528::HttpWebRequest(uri: ‘https://<ADFS URL redacted>/adfs/services/trust/mex’, connectionGroupName: ‘35903099’)

ProcessId=40964

DateTime=2019-01-04T18:22:24.7492510Z


System.Net Information: 0 : [41764] Connection#1680021 – Created connection from 10.100.##.##:65057 to 10.100.##.##:443.

ProcessId=40964

DateTime=2019-01-04T18:22:25.1833208Z


System.Net Information: 0 : [41764] HttpWebRequest#59312528 – Request: GET /adfs/services/trust/mex HTTP/1.1

ProcessId=40964

DateTime=2019-01-04T18:22:25.2003015Z

System.Net Information: 0 : [41764] ConnectStream#62301924 – Sending headers


System.Net.Sockets Error: 0 : [36156] Exception in Socket#28560362::BeginReceive – An existing connection was forcibly closed by the remote host.

ProcessId=40964

DateTime=2019-01-04T18:22:25.2898109Z

System.Net.Sockets Verbose: 0 : [36156] Exiting Socket#28560362::BeginReceive()

ProcessId=40964

DateTime=2019-01-04T18:22:25.3063138Z

System.Net.Sockets Verbose: 0 : [36156] Entering Socket#28560362::Dispose()

ProcessId=40964

DateTime=2019-01-04T18:22:25.3198160Z

System.Net Error: 0 : [36156] Exception in HttpWebRequest#59312528:: – The underlying connection was closed: An unexpected error occurred on a send..

ProcessId=40964

DateTime=2019-01-04T18:22:25.3558191Z.

The above log tells us that we are failing to connect to the ADFS Server metadata endpoint. The server shuts down our request. It also tells us the IP address and port number of both the local machine and the remote ADFS server and we can use this info as a filter when looking at the corresponding network trace below in

Message Analyzer:

Filter used: IPv4.Address == xxx and ipv4.Address == yyy and TCP.Port == 443 and tcp.port == 65057

Or in Wireshark:

From the network trace, after the client completes TCP IP 3-way handshake with the ADFS server it sends a Client Hello message to start an SSL connection to the ADFS server. That SSL handshake fails when the server sends a reset command (RST) to close the connection. If the SSL connection is successful, we should see the server sending back a Server Hello message. In this case it’s the customer’s Firewall that blocks the connection.

How to capture a System.Net log:

https://blogs.msdn.microsoft.com/jpsanders/2009/03/24/my-favorite-system-net-trace-configuration-file-dumps-process-id-and-date-time-information/

How to capture a network log:

There are multiple ways to do this. I use netsh command to do this:

(run the following from an Admin command prompt):

  1. netsh trace start capture=yes persistent=yes traceFile=C:\temp\trace\trace001.etl // start tracing
  2. Repro the issue
  3. netsh trace stop  // stop tracing

Also see the following blog for more info:

https://blogs.msdn.microsoft.com/benjaminperkins/2018/03/09/capture-a-netsh-network-trace/

https://blogs.technet.microsoft.com/askpfeplat/2014/08/18/introduction-to-network-trace-analysis-using-microsoft-message-analyzer-part-1/

Summary:

I hope the above information is useful to help you diagnose Exceptions like this when using ADAL or any other Authentication library to Azure AD.

Microsoft Graph Explorer – How come I only see one user in my directory?

Problem:

Customer uses the Microsoft Graph Explorer tool and clicks the “Sign in with Microsoft” button to log in.

After logging in, he tries the following query to get all the users in his directory. There is only one user returned. Expected result is that there should be a lot more than one user in this directory being returned by MS Graph.

Resolution:

This is because the customer logs in with his personal Microsoft Account (MSA account) as highlighted in red in the above screen shot. To correctly get all the users in a directory customer needs to log in with an organizational Azure AD account (eg. upn = name@tenant.onmicrosoft.com).

Walkthrough: how to retrieve an Azure Key Vault secret from an Azure Function App using client credentials flow with certificate

Introduction:

This post builds on the information from the previous post and I will assume that you already have an Azure Key Vault, an AAD Application registration, and a certificate file. We will cover the following steps in this blog in order to use a certificate from an Azure Function App:

  1. Create an Azure Function App
  2. Upload the certificate to the Function App
  3. Configure the Function App to load certificate file
  4. Create an Azure Function to consume the certificate

Create an Azure Function App

From the Azure Market Place in the Azure portal, create an Azure Function App. The Hosting Plan can either be Consumption Plan or App Service Plan.

Upload the certificate to the Azure Function App

Go to the Function App resource we just created => click on Platform features tab => click on SSL link

From the SSL blade => click on Private Certificates (.pfx) tab => click the Upload Certificate link

Go through the Certificate Upload wizard to provide a pfx file and password. Once the upload is complete, the certificate info should appear under the Private Certificate section

Configure the Function App to load the certificate

From the Function App blade, click on the Application settings link under the Platform features tab

Under Application settings section, add a new setting called WEBSITE_LOAD_CERTIFICATES and set the value to be the certificate thumbprint. Click on Save button to save the new setting

Create an Azure Function

From Visual Studio 2017, create a new Azure Functions project. If you don’t see the “Azure Functions” template, you may need to install “Azure Functions and Web Jobs Tools” extension. See https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs for more info.

For the Function trigger, I just choose Timer trigger for the purpose of this blog. You an choose any trigger you like. Trigger is just a mean to invoke an Azure Function. If you have a storage account then go ahead and configure the storage account for the Function under Storage Account setting. The schedule setting uses CRON expression to define a timer schedule for the Function App. The prepopulated expression 0 */5 * * * * means that the Function is invoked every 5 minutes.

Now we need to write the code for this Function:

  1. Install the following Nuget packages from the Package Manager Console:

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory

Install-Package Microsoft.Azure.KeyVault

  1. Replace the code in Function1.cs with the following code:

[gist id=”069082b4a4a2df7b0e3f9ef4ccf4498b” file=”Function1.cs”]

  1. Build and publish this Azure Function to our Azure Function App by right-click on the Project name and select “Publish…”

    Note: If you have not done this already, make sure you log into Visual Studio with your Azure AD account.


Select the target to be our existing Azure Function App and click “Publish”

Select the right Azure Function App under the right Resource Group and click OK to publish

Once the publishing is finished, we should see our Function 1 appearing in the Azure portal. You can click on the “Run” button to see the output in the Logs section at the bottom.

References

https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs

https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/

Walkthrough: how to retrieve an Azure Key Vault secret from a console app using client credentials flow with certificate

Introduction

This is a code walkthrough to show you how to create a .Net console application to authenticate to Azure Active Directory using OAuth2 Client Credentials flow to get an access token to Azure Key Vault. It then uses the access token to call Azure Key Vault to get a secret. The following steps will be performed in this post:

  1. Create an Azure Key Vault
  2. Create a new self-signed certificate to use in client credentials flow
  3. Create a new Application Registration
  4. Create a new console app to retrieve a secret from Azure Key Vault

Create an Azure Key Vault

You can create an Azure Key Vault from the Azure portal if you don’t have one already. Refer to https://docs.microsoft.com/en-us/azure/key-vault/key-vault-get-started for more info. I use the Powershell script below to create a new Azure Key Vault and then set a new secret.

[gist id=”f712488ddd72ab9eed7c6b0e2115ce61″ file=”CreateKeyVault.ps1″]

The above script creates an Azure Key Vault called BlogKV123 with a secret called SQLPassword:

Create a new self-signed certificate

I use the Powershell script below to create a new exportable self-signed certificate. See https://docs.microsoft.com/en-us/azure/key-vault/key-vault-use-from-web-application for more info.

[gist id=”e5f4671e35a97f3b3e8a579b9a2c05b9″ file=”CreateSelfSignedCert.ps1″]

Create a new Application Registration

We need to create a new Application Registration in the Azure Active Directory’s App Registration blade and then upload the certificate cer file created above to the Keys section of the Application. In addition, we also need to give our Application (really its Service Principal) access permission to the Azure Key Vault to read its secret info. I use the following Powershell script from https://docs.microsoft.com/en-us/azure/key-vault/key-vault-use-from-web-application to do this.. Take note of the certificate thumbprint output below as you will need it later for the application code.

[gist id=”c5a8c49ed9e831e98925e25cf3b2ffd7″ file=”CreateAADAppwithKeyVault.ps1″]

The script above should create a “Web app / API” Application type and upload the certificate file to the Application in the Keys => Public Keys section as in the screen shot below.  The thumbprint info should match the output above in the Powershell console.

Take note of the Application ID and the thumbprint as you will use it in your console app later.

Over in the Azure Key Vault blade, you should see the Service Principal for our Application listed in the Access policies section with all the given secret operation permission

Create a Console Application

  1. From Visual Studio 2017 Create a new .Net console app:

  1. Install the following Nuget packages from the Package Manager Console:

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory

Install-Package Microsoft.Azure.KeyVault

  1. Replace the code in Program.cs with the following code (Use both the Application ID and the certificate thumbprint from above on line 14 and 15 respectively):

[gist id=”8e986c31c71da41d696ac4d4b175df2a” file=”Program.cs”  ]

  1. Run the application and you should get the output ‘Pa$$w0rd’ printed out.

References:

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-get-started

https://www.rahulpnath.com/blog/authenticating-a-client-application-with-azure-key-vault/

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-use-from-web-application

Capturing Python web traffic with Fiddler

Update 4/15/2019 – added GraphRbacManagementClient section

Introduction:

Capturing encrypted HTTPS web traffic in Python with Fiddler can be tricky mainly because Python uses its own trusted certificate store instead of the OS’s certificate store and in certain scenario, python does not use proxy by default.  This post will cover how to capture SSL traffic using Fiddler for a few different scenario:

ADAL for Python:

The problem with this case is one will get an SSL error related to certificate since Python does not trust Fiddler certificate.  There are a couple of ways to resolve this:

  1. Set the following environment variable at the beginning of the application before initializing the AuthenticationContext object

import os

os.environ[‘ADAL_PYTHON_SSL_NO_VERIFY‘] = “1”

  1. Pass the verify_ssl flag to AuthenticationContext method:

# use verify_ssl=False to capture Fiddler traffic

context = adal.AuthenticationContext(authority,verify_ssl=False)

MSAL for Python:

app = msal.PublicClientApplication(client_id = appId,
                                   authority = “https://login.microsoftonline.com/”+ tenantId,verify = False)

Python Requests Module:

The Requests module does not use Proxy by default so we have to force the request to go through Fiddler proxy.  Below is an example showing how to do this.

Note:  Usually Fiddler is configured to listen to port 8888. I have changed this on my system to use port 9999

import requests

access_token = token.get(‘accessToken’)

endpoint = ‘headers = {“Authorization”: ‘Bearer ‘ + access_token}

json_output = requests.get(endpoint,headers=headers,proxies={“http”: “http://127.0.0.1:9999“,”https”:”http:127.0.0.1:9999″},verify=False).json()

AAD Libraries for Python / GraphRbacManagementClient:

from azure.graphrbac import GraphRbacManagementClient
from azure.common.credentials import UserPassCredentials

credentials = UserPassCredentials(
      <username>,    # Your user name
      <password>,    # Your password
      resource=”https://graph.windows.net”,
      verify=False
)
tenant_id = <tenant name or tenant id>
graphrbac_client = GraphRbacManagementClient(credentials, tenant_id)
graphrbac_client.config.connection.verify=False
res = graphrbac_client.users.get(<UPN or ObjectID>)
print(res.display_name)

References:

https://stackoverflow.com/questions/7694789/fiddler-doesnt-capture-python-http-request

How to add an owner to an Azure AD Application

Introduction:

This post will go over a three different ways to add owner to Azure AD Application using Azure Powershell, Azure AD Graph, and Microsoft Graph endpoint.  The Microsoft Graph documentation on this may not be clear to point out that an Application owner can be either a User object or a Service Principal object.

Various technique to add Application Owner:

Azure AD Powershell:

Use the Azure AD Powershell command Add-AzureADApplicationOwner.  Below is an example:

# prerequisite:  You may need to run Install-Module -Name AzureADPreview to install AzureADPreview module first

$AppObj = (Get-AzureADApplication -Filter “DisplayName eq ‘DeleteMe'”).ObjectId

$UserObj = (Get-AzureADUser -ObjectId xyz@tenant.onmicrosoft.com).ObjectId

Echo ‘Get Application Owner list Before Adding Owner….’

Get-AzureADApplicationOwner -ObjectId $AppObj

Add-AzureADApplicationOwner -ObjectId $AppObj -RefObjectId $UserObj

Echo ‘Get Application Owner After Adding Owner….’

Get-AzureADApplicationOwner -ObjectId $AppObj

image

Azure AD Graph API:

Request:

# Directory ID can be obtained from the Azure portal –> Azure Active Directory –> Properties –> Directory ID

POST https://graph.windows.net/<Directory ID>/applications/<Application Object ID>/$links/owners?api-version=1.6

Request Header:

Content-Type:  application/json

Request payload:

{
“url”:https://graph.windows.net/<Directory ID>/directoryObjects/<Object ID>
}

Notethe above Object ID can be either a User Object ID or a Service Principal Object ID

Microsoft Graph API:

Request:

POST https://graph.microsoft.com/beta/applications/<Application Object ID>/owners/$ref

Request Header:

Content-Type:  application/json

Request payload:

# for User Object:

{
“@odata.id”: “https://graph.microsoft.com/beta/users/<User Object ID>
}

# for Service Principal Object:

{
“@odata.id”:”https://graph.microsoft.com/beta/servicePrincipals/<Service Principal Object ID>
}

References:

https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/application_post_owners

https://github.com/microsoftgraph/microsoft-graph-docs/issues/1645

How to Use the .Net Microsoft Graph SDK to Get Users and Get Next Page of Results

Introduction

This post will explain how to use the .Net Microsoft Graph SDK in order to get users. This article is assuming that you have already gotten an Access Token using ADAL .NET. In order to learn more on how to get the Adal .NET token, please reference :

How to Use the ADAL .NET library to Acquire a Token Interactively in a Console Application (Authorization Code Flow) Link

Warning Regarding Microsoft Graph SDK

The Microsoft Graph SDK isn’t updated as frequently as the Microsoft Graph API, which makes the Microsoft Graph SDK lag behind a bit. The most effective way to keep up with the Microsoft Graph API is to utilize the HTTPClient, and then parse the response body accordingly. If you would like to utilize the data structures and requests predefined in the Microsoft Graph SDK that is fine, however know that the SDK will not always be up to date with the Microsoft Graph API.

 

Installing the MSFT Graph SDK NuGet

In order to install this SDK, please go to your project management and then go to browse. Then look up Microsoft.Graph. This NuGet Package is shown in the picture below.

It is the Microsoft.Graph library.

 

Making Calls Using the Microsoft Graph SDK

In order to make calls to the Microsoft Graph SDK, you will need to get the Access token as shown in the other post on utilizing ADAL .net library to acquire a token. Once the access token has been acquired, you will create the graphserviceclient, setting the header of the request message as the access token. This is shown in the github gist below.

In the example, we get use the object in the graphserviceclient Users, which has a request call, which has the HTTP request call within, which can be called by using the .getAsync().getAwaiter().getResult() method chain.

In order to set the OData parameters, you can add them after the request() call.

Expand, Skip, Top, OrderBy, and Filter are also supported via the client library when supported by the Microsoft Graph service for the request type.

For more information, please refer to the documentation for the MSFT Graph SDK here: https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/overview.md

In order to page through the results, you will have to utilize the call : users.NextPageRequest.GetAsync().GetAwaiter().GetResult();

Where users is the GraphServiceClient.

Conclusion

This post has gone over how to install and utilize the Microsoft Graph SDK in order to get users from the Microsoft Graph API. We also review how to page through the Microsoft Graph SDK users in order to get the next set of users accordingly. If you have any issues with the Microsoft Graph SDK, please file an issue with them and the maintainers of the SDK will work to resolve the issue. https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues
If you have any issues with Azure Active Directory and making the Microsoft Graph API call, please file a support ticket with Azure and we will get back to you as soon as possible to resolve the issue.

How to Use the ADAL .NET library to Call the Microsoft Graph API in a Console Application (Using Authorization Code Flow)

Introduction

This post is to show how to use the ADAL .NET library to acquire a token interactively in a console application. It will go through setting up an Azure Active Directory Application, setting up the .net console application, acquiring an access token, and then make a HTTP request using the token acquired from the ADAL .net library to get 5 users using the Microsoft Graph API.

 

Setting up your Azure Active Directory Application Registration

First we will need to setup an Azure Active Directory Application Registration in your Azure Portal. You can do this by going to the Azure Portal > Azure Active Directory > App Registrations > Add Application.

 

 

 

Then set the Application Registration to a native app, and put in your own respective values for redirect url and name. The redirect URL will not matter, it will only be important to remember for when you are asking for an access token, and the name is up to you.

Note: It is important to make it a Native Application, otherwise you will get errors saying that there is no Client Secret

 

After you have created the Application, keep track of the Application ID for later. You will need it to authenticate with this AAD Application Registration, then go to required permissions >Add > select an API > Microsoft Graph API > select view users’ basic profile > and press grant permissions.

For more information on which permissions you need and how to grant permissions in different ways, please refer to these posts :

https://blogs.msdn.microsoft.com/aaddevsup/2018/05/21/finding-the-correct-permissions-for-a-microsoft-or-azure-active-directory-graph-call/

https://blogs.msdn.microsoft.com/aaddevsup/2018/05/08/receiving-aadsts90094-the-grant-requires-admin-permission/

 

Setting up the console application

To start, let’s create a new project, install the correct NuGet packages, and fix reference assembly issues.

In this tutorial I will be using a new project with the template Console App (.net framework).

 

 

 

Now that we have a fresh new console .net application, we will need to install some libraries in order to get an access token from Azure Active Directory. The ADAL libraries are Microsoft maintained libraries that we will need to get for our .net console application.

We can do this by going to our NuGet Manager and picking up the correct libraries.

In order to do this you will want to right click on the solution, and go to Manage NuGet Packages for Solution.

In this example we will be using the NuGet pacakages below. You can search and then download them via the Browse section of the NuGet Manager.

Id Versions
— ——–
Microsoft.IdentityModel.Clients.ActiveDirectory {4.3.0}
Microsoft.IdentityModel.JsonWebTokens {5.3.0}
Microsoft.IdentityModel.Logging {5.3.0}
Microsoft.IdentityModel.Tokens {5.3.0}
Newtonsoft.Json {11.0.2}
System.IdentityModel.Tokens.Jwt {5.3.0}

 

 

 

 

The ADAL libraries are the Microsoft.IdentityModel libraries, however the other two libraries are being used for formatting JWT tokens and JSON tokens to be a readable print. This is to make our lives easier later on once we get the access token and JSON response.

After you have installed all the NuGet libraries, you may still need to fix a reference assembly for System.Web.Script.Serialization.

In order to do this, right click on the references in the solution explorer and then click add reference. We will then want to add the System.Web.Extensions, as shown in the picture below.

 

Variable Initialization

Now that we have all the correct libraries and references installed into our solution, you will want to declare some variables for your AAD token acquisition.

You’ll need to declare the variables listed below. In this example we will be accessing the Microsoft Graph API, so the resource URI has already been declared.

You will need to replace the client id(Application ID), redirect URI, and tenant id with your own respective information. You can get the tenant ID from your Azure Active Directory portal in the overview section. You will need to get the client id and redirect URI from the first steps that we followed when creating the AAD Application.

After you have initialized the variables we can setup our main method with some empty methods. I have setup my main method as below. First we will get our access token, and then make the call to the Microsoft Graph with the access token to retrieve 5 users.

Once we have the variables declared and our main skeleton method setup, we can start on our Access Token Call method, shown below. First we initialize the authcontext which is the variable that maintains the environment for the ADAL library. In this setup we try to acquire the access token three times if it fails. Once you have initialized the authcontext, you can simply make the call :

authContext.AcquireTokenAsync(resourceUri, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));

Which will get the access token. In this method we also pretty print the JWT token, so that you can read the claims in the console.

The pretty print method can be found here :

That defines the getAccessToken() method.

 

Now, we will need to flesh out the getMembers() method.
This method can be seen below, first we add the access token we just got to the headers of the HTTP client, then we make the Microsoft graph call using a getAsync method call from the HTTP client class. The documentation on the Microsoft Graph list users call can be read here :

https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_list

In addition to getting the users, we have set the OData V4 $top requirement, in order to get only the first 5 users. In order to continue getting the next 5 users, you can utilize the skip token that is sent back in the response body.
More documentation on this can be found here :
https://developer.microsoft.com/en-us/graph/docs/overview/query_parameters
https://developer.microsoft.com/en-us/graph/docs/concepts/paging

 

After getting the JSON response, we utilize the prettify JSON method in order to clean up and easily print out the JSON response.

 


Now we can run our console application, and we will get 5 users from the Microsoft Graph API.

Note: The account you login with will need the permissions to read all basic user profiles in order to properly call the Microsoft Graph API call as this is an on behalf of the user flow.

Conclusion

After going through all of this we have setup an AAD App registration that we can connect to using ADAL .NET. We have filled out the code to acquire an access token using ADAL and then make a HTTP request using the HTTP Client to get 5 users from the Microsoft Graph API.

If you have any issues with the code, feel free to open up a GitHub issue on the repository to address any coding issues. If you are having an issues with AAD Access, please open up a support ticket and one of our support engineers will reach out as soon as possible.

The full GitHub Repository of this code can be found here : https://github.com/frankhu1234/ADAL-.NET-Console-Application