How to protect WebApi with Azure Active Directory?

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

This article describes how to protect you WebApi project with Microsoft Azure Active Directory. IN other words, you wan to implement some desktop application, which authenticates
against Azure Directory with OAuth and not as usual against Active Directory using NTLM or Kerberos.
First of all you need to provision Active Directory in Azure (not described in this article) and create some users. I have created “mydomain” with two users. tfsadmin is user is a global admin and user1 has common rights.

image 

Following picture shows settings of ‘tfsadmin’ user. Don’t be confused with the name. This article does not relate to TFS.
This was just an existing user which I used in this example.
image

As first we will create the new WebApi application called “WebApi”.

image

No chose WebApi project type and change Authentication to “Organizational Account”.

image

In the next screen enter the domain of your AD. For example mydomain.onmicrosoft.com.

image

As next you will have to login as user with global admin permissions. This permission is required is because VS will provision you WebApi application in AD.

 

image 

Click OK and VS will start provisioning process. This will take a minute.

image

Now switch to Active Directory in Azure Portal and notice your new application.

image

 

How to implement Client Application (App)?

Now we have to implement one of more applications which need to authenticate against AD. IN this example we will implement a console application.

 

image

Add Active Directory Authentication Library (ADAL) via NuGet, which provide client authentication functionality.

image

Paste following code in Main- methods. Note that [STAThread] is mandatory.

class Program
    {
        [
STAThread]
       
static void Main(string[] args)
        {
           
string authority = "";
           
string resource = "";
           
string clientId = "";
           
string redirectUri = "";

           
AuthenticationContext authContext =
               
new AuthenticationContext(string.Format("https://login.windows.net/{0}", authority));
           
AuthenticationResult result =
                authContext.AcquireToken(resource,
                clientId,
               
new Uri(redirectUri),
               
PromptBehavior.Auto);
        }
    }


Now we need to add manually this application to AD.

image

image

Enter the name of you console application.I used in this example “authconsole”. Please note, that if you app would be a native app like
Windows Store App, you would have to go to Service - Live ID portal and copy the package ID to paste it here. For more information about this
take a look here.

image

Enter some syntactically valid URL. This URL will not be used for redirection, because Console Application is not online.

 

image 

Now, your client app is created.

image

Now under section “Get Started/Update Your Code” you can obtain two important arguments and add them in you Main-method as variables:

string clientId = "82f6fb04-3b4e-4e40-b6dc-4c4cac564311";
string redirectUri = http://anything.com;

 

As next go to section “Get Started/Enable users to sign In” in your WebApi (web application) and copy two marked values in the code too.

image

This is how to code looks like now:

[STAThread]
       
static void Main(string[] args)
        {
           
string authority = ff77**”
           
string resource = "https://***.onmicrosoft.com/MyWebApi";
           
string clientId = "***";
           
string redirectUri = "http://anything.com";

           
AuthenticationContext authContext =
               
new AuthenticationContext(string.Format("https://login.windows.net/{0}", authority));
           
AuthenticationResult result =
                authContext.AcquireToken(resource,
                clientId,
               
new Uri(redirectUri),
               
PromptBehavior.Auto);
        }


Be careful by copying of parameters from the portal. If some of parameters is not right one you might get errors which are possible difficult to understand.
Here is one error example when some of parameters are not correctly copied and client application is started.

Additional information: access_denied: AADSTS65005: The client application has requested access to resource 'https://****.onmicrosoft.com/MyWebApi'. This request has failed because the client has not specified this resource in its requiredResourceAccess list.“

This error indicates that we didn’t define permission for client application to access WebApi. To do this navigate to WebApi application in Active Directory
and download the manifest which describes permissions:

image

You can find more about this here: Expose API to other applications

Save downloaded file and open it it Visual Studio. You will on the left JSON manifes. Locate appPermission in the manifest and add
your permission as shown at the right side.

{
 
"appId": "96bcc942-56d0-4c65-a664-beb82a982d6c",
 
"appMetadata": null,
 

 "appPermissions": [],

 
"availableToOtherTenants": false,
 
"displayName": "MyWebApi",
 
"errorUrl": null,
 
"homepage": "https://localhost:44304/",
 
"identifierUris": [
   
"https://***.onmicrosoft.com/MyWebApi"
  ],
 
"keyCredentials": [],
 
"knownClientApplications": [],
 
"logoutUrl": null,
 
"passwordCredentials": [],
 
"publicClient": null,
 
"replyUrls": [
   
"https://localhost:44304/"
  ],
 
"requiredResourceAccess": [
    {
     
"resourceAppId": "00000002-0000-0000-c000-000000000000",
     
"requiredAppPermissions": [
        {
         
"permissionId": "****",
         
"directAccessGrant": false,
         
"impersonationAccessGrants": [
           
"User"
          ]
        }
      ]
    }
  ],
 
"resourceApplicationSet": null,
 
"samlMetadataUrl": null,
 
"webApi": null,
 
"webApp": null,
 
"notifications": [],
 
"serviceEndpoints": [],
 
"objectType": "Application",
 
"objectId": "****",
 
"softDeletionTimestamp": null,
 
"createdOnBehalfOf": null,
 
"createdObjects": [],
 
"manager": null,
 
"directReports": [],
 
"members": [],
 
"memberOf": [],
 
"owners": [],
 
"ownedObjects": []
}



{
 
"appId": "***",
 
"appMetadata": null,
 

"appPermissions":[
{
"claimValue":"user_impersonation",
"description":"Allow the application full access to the service on behalf of the signed-in user",
"directAccessGrantTypes":[
],
"displayName":"Have full access to the service",
"impersonationAccessGrantTypes":[
{
"impersonated":"User",
"impersonator":"Application"
}
],
"isDisabled":false,
"origin":"Application",
"permissionId":"b69ee3c9-c40d-4f2a-ac80-961cd1534e40",
"resourceScopeType":"Personal",
"userConsentDescription":"YOUR TEXT HERE Allow the application full access to the service on your behalf",
"userConsentDisplayName":"YOUR TEXT HERE Have full access to the service"
}
],



 
"availableToOtherTenants": false,
 
"displayName": "MyWebApi",
 
"errorUrl": null,
 
"homepage": "https://localhost:44304/",
 
"identifierUris": [
   
"https://****.onmicrosoft.com/MyWebApi"
  ],
 
"keyCredentials": [],
 
"knownClientApplications": [],
 
"logoutUrl": null,
 
"passwordCredentials": [],
 
"publicClient": null,
 
"replyUrls": [
   
"https://localhost:44304/"
  ],
 
"requiredResourceAccess": [
    {
     
"resourceAppId": "00000002-0000-0000-c000-000000000000",
     
"requiredAppPermissions": [
        {
         
"permissionId": "311a71cc-e848-46a1-bdf8-97ff7156d8e6",
         
"directAccessGrant": false,
         
"impersonationAccessGrants": [
           
"User"
          ]
        }
      ]
    }
  ],
 
"resourceApplicationSet": null,
 
"samlMetadataUrl": null,
 
"webApi": null,
 
"webApp": null,
 
"notifications": [],
 
"serviceEndpoints": [],
 
"objectType": "Application",
 
"objectId": "fbb65b40-799e-45bd-a2dd-19c305136ee6",
 
"softDeletionTimestamp": null,
 
"createdOnBehalfOf": null,
 
"createdObjects": [],
 
"manager": null,
 
"directReports": [],
 
"members": [],
 
"memberOf": [],
 
"owners": [],
 
"ownedObjects": []
}



After you have saved the JSON manifest upload it in AD:

image

Now we can navigate in AD portal to our client application and under configuration we can select appropriate permission.

 

image 
Now you can start the client application. As first you will need to authenticate.

image 

If all works fine you will get the token.

 

image

In the last step we simply call the WebApi:

class Program
    {
        [
STAThread]
       
static void Main(string[] args)
        {
           
string authority = "ff77****9a5";
           
string resource = "https://*****.onmicrosoft.com/MyWebApi";
           
string clientId = "82f6*****4311";
           
string redirectUri = "http://anything.com";

           
AuthenticationContext authContext =
               
new AuthenticationContext(string.Format("https://login.windows.net/{0}", authority));
           
AuthenticationResult result =
                authContext.AcquireToken(resource,
                clientId,
               
new Uri(redirectUri),
               
PromptBehavior.Auto);

            go(result.CreateAuthorizationHeader());

           
Console.ReadLine();
        }

       
private static async void go(string authHeader)
        {
           
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) =>
                {
                   
return true;
                };
        
           
HttpClient client = new HttpClient();
           
HttpRequestMessage request = new HttpRequestMessage(
             
HttpMethod.Get, "https://localhost:44304/api/Values");
            request.Headers.TryAddWithoutValidation(
"Authorization", authHeader);
           
HttpResponseMessage response = await client.SendAsync(request);
           
string responseString = await response.Content.ReadAsStringAsync();

        }
    }


 

 

More information: http://msdn.microsoft.com/en-us/library/azure/dn151790.aspx


Posted Jul 03 2014, 09:26 AM by Damir Dobric

Comments

Damir Dobric Posts wrote AAD authentication with REST API Client
on 06-07-2016 17:50

If you have ever worked with SOAP, it is most likely that you have get in touch with WSDL, which is used

Damir Dobric Posts wrote AAD authentication with REST API Client
on 06-07-2016 17:53

If you have ever worked with SOAP, it is most likely that you have get in touch with WSDL, which is used

developers.de is a .Net Community Blog powered by daenet GmbH.