Vous êtes sur la page 1sur 65

Azure Active Directory

By
Mohamed Waly

Table of Contents
About the Author......................................................................................................... 4
Chapter 1: Introduction ............................................................................................ 5
1.1

What Azure Active Directory is and (is not) .............................................. 5

1.2

Users and Groups.......................................................................................... 7

1.3

Work or Student Accounts .......................................................................... 7

1.4

Microsoft Accounts ....................................................................................... 9

1.5

Adding Users and Groups to Azure AD ..................................................... 9

1.6

Custom Domains......................................................................................... 10

1.7

Protocols supported by Azure AD ............................................................ 11

1.8

From Protocols to Application Endpoints ............................................... 12

1.9

Adding Applications to Azure AD ................................................................ 14

1.10

Summary.................................................................................................... 15

Chapter 2: Building Web Applications for Azure AD ......................................... 16


2.1

Introduction ................................................................................................... 16

2.2

Add a Web Application to Azure AD using Visual Studio........................... 17

2.3

Add a Web API Application to Azure AD using Visual Studio ................... 24

2.4

Identity in the .NET Framework ................................................................. 32

2.5

Summary ....................................................................................................... 34

Chapter 3: Developing Native Client Applications ............................................. 36


3.1

Introduction ................................................................................................... 36

3.2

Using claims in the Web API to drive application behavior ......................... 37

3.3

Exposing the Web API to other applications ................................................ 40

3.4

Add a native client application to Azure Active Directory ........................... 43

3.5

Configure permissions to access the Web API ............................................. 45

3.6

Develop the native client application ............................................................ 45

3.6.1

DEFINE SETTINGS USED BY THE NATIVE CLIENT

APPLICATION ................................................................................................ 46
3.6.2

CALL THE WEB API TO GET VALUES .................................. 49

3.6.3

CALL THE WEB API TO POST A NEW VALUE .................. 51

3.6.4

RUNNING THE NATIVE CLIENT APPLICATION ....................... 52

3.7

ADALs Token Cache and Refresh Tokens .................................................. 54

3.8

Summary ....................................................................................................... 54

Chapter 4: Group Claims ........................................................................................ 56


4.1

Introduction ................................................................................................... 56

4.2

Using Group Claims to Drive Authorization Decisions ............................... 57

4.2.1

ENABLE

GROUP

CLAIMS

FOR

THE

CLOUDALLOC.WEBAPI APPLICATION ............................................... 58


4.2.2

LOCATE

THE

OBJECT

ID

FOR

THE

DEV/TEST

SECURITY GROUP ...................................................................................... 59


4.2.3

UPDATE THE POST METHOD TO LOOK FOR DEV/TEST

GROUP CLAIM ............................................................................................... 60


4.2.4

EXAMINING THE GROUP CLAIMS .......................................... 62

4.3

Working with the Azure AD Group Claims Limit ........................................ 64

4.4

Summary ....................................................................................................... 65

About the Author

Mohamed Waly: I'm a former Hyper-V MVP, Microsoft Student Partner, I use to
deliver sessions about Virtualization Technology and Cloud Computing.

Chapter 1:

Introduction

1.1 What Azure Active Directory is and (is not)


Azure Active Directory (aka Azure AD) is a fully managed multi-tenant
service from Microsoft that offers identity and access capabilities for
applications running in Microsoft Azure and for applications running in
an on-premises environment. Its name leads some to make incorrect
conclusions about what Azure AD really is. Therefore, to avoid any
confusion with Windows Server Active Directory that you may already
be familiar with in an on-premises environment, understand that Azure
AD is not Windows Server Active Directory running on Virtual Machines
in Microsoft Azure.
Azure AD is not a replacement for Windows Server Active Directory. If
you already have an on-premises directory, it can be extended to the
cloud using the directory integration capabilities of Azure AD. In these
scenarios, users and groups in the on-premises directory are synced to
Azure AD using a tool such as Azure Active Directory Sync (AAD Sync).
This has the benefit of users being able to authenticate against
Windows Server Active Directory when accessing on-premises
applications and resources, and authenticating against Azure AD when
accessing cloud applications. The user can authenticate using the same
credentials in both scenarios.
Azure AD can also be an organizations only directory service. For
example, many startups today dont have an on-premises Windows
Server Active Directory. In these scenarios, an organization may simply
rely on Office 365 and other SaaS applications to conduct its business
and manage its users identity and access to SaaS applications, all
online.
As a developer of cloud applications, you can use Azure AD to
accomplish things such as single sign-on (SSO) for your cloud
applications, query the directory for user and group information, and
5

even write to the directory provided your application has the


permissions to do so. Of course, you can accomplish similar ideas onpremises and build applications using Microsoft proprietary
technologies such as Windows NTLM, Kerberos, LDAP and so on.
However, as more applications are developed with the intent of running
in the cloud, and access to those applications cross organizational
boundaries, and are accessed from a growing number of devices across
a variety of platforms, organizations need an enterprise ready directory
service that can handle the authentication needs of the organization
and the applications it depends on. The graphic below illustrates how
Azure Active Directory could be used in a company to address some
common enterprise needs.

Figure 1.1

Throughout this book, the focus will be on the developer, with careful
attention given to the tools, libraries and features of Azure AD that can
be used to build cloud applications that are protected by Azure AD. This
chapter lays the groundwork for some key concepts in Azure AD. Future
chapters in this book will go deep into the developer experience for
different types of cloud applications.

1.2 Users and Groups


In Azure AD there are two entities that we are most concerned with
during application development; the user and perhaps the group (or
groups) the user is a part of. We use the users claims (statements about
the user from Azure AD) to drive application behavior such as
personalizing screens or making authorization decisions about what the
user can do. By externalizing the authentication of users to Azure AD
were able to rely on the claims provided in the authentication token for
the user to drive these application experiences.
A user in a directory can be sourced from either a directory in Azure AD,
which is referred to as aWork or Student Account (previously called
an Organizational Account). Or, the user can be sourced from a
Microsoft Account. An example of how this may look in the Azure AD
Users page of the Azure Management Portal is shown here.

Figure 1.2

1.3 Work or Student Accounts


Users are generally added to a directory in Azure AD as a Work or
Student Account user (formerly know as Organizational Accounts). A
users user name and email address will take the form
of <someuser>@<someorg>.onmicrosoft.com and the account
typically exists for as long as the user is part of the organization and
until an Administrator removes the account. If you have ever had an
account in an on-premises Windows Server Active Directory (for
example, at work) then this is essentially the same concept.
A user from a different directory in Azure AD can also be added to a
directory (aka external user). This is particularly useful in situations
where users in different directories need access to the same cloud
7

applications protected by Azure AD. This is a very powerful scenario and


one that is increasing popular as more and more organizations partner
with one another. Consider, for example, a user John Doe from
CompanyA (john.doe@companya.onmicrosoft.com) is added as a user
to the directory for CompanyB. This would enable John Doe to access
CompanyBs cloud applications protected by CompanyBs Azure AD.
Now, when John Doe authenticates, he will do so in the realm of
CompanyAs directory, not CompanyBs directory. So, his profile data,
password, policies, etc. are all managed by the administrators at
CompanyA. As it should be CompanyA knows him best and is the
authority that can properly authenticate him. Given that CompanyA and
CompanyB have established trust between the two organizations,
CompanyB can add John Doe to their directory so he can collaborate
with users and applications in CompanyB. If CompanyB decides later to
remove John Doe from the directory, then he will no longer be able to
access CompanyBs resources. However, suppose John Doe quits
CompanyA or is removed from the organization for other reasons. What
is the first thing IT generally does in this case? They delete John Doe
from the directory (or at least disable the account). They probably dont
call all their partners such as CompanyB to tell them that John Doe
should be removed. But thats ok, because as I pointed out earlier, John
Doe will never authenticate in the realm of CompanyBs directory. He
will authenticate against CompanyAs directory. And since his account
will have been either removed or disabled, he wont be able to
successfully authenticate, and therefore wont be able to access any
CompanyB resources even though his account technically still exists in
CompanyBs directory. If you have been in this industry for at least a few
short years you can probably appreciate the immense flexibility and
level of security this brings to an organization.
During authentication, Work or Student Account users may notice the
blue badge icon shown above. This icon is a visual hint to the user
signing in using a Work or Student Account.

1.4 Microsoft Accounts


Users can also be added to a directory in Azure AD as a Microsoft
Account user. In this scenario, the user name and email address will
likely take the form of <someuser>@hotmail.com,
<someuser>@outlook.com, or <someuser>@live.com. A Microsoft
Account is an individual account that a user has created to access
consumer services such as Xbox LIVE, Messenger, Outlook/Hotmail, etc.
Unlike the Organizational Account, these accounts dont get deleted
when they are removed from a directory in Azure AD. The account
belongs to the person in this case, not an organization. However, Azure
AD enables organizations to add users to their directory using a
persons Microsoft Account and these users are also considered external
users of the directory.
One scenario where you might add a user to a directory in Azure AD
using a persons Microsoft Account is in a freelance situation where
you need an external user (someone that is not part of the organization)
to have access to cloud applications for a particular project or service
agreement. This prevents the user from having to keep up with a
separate set of user credentials just to access the necessary application
resources for the project. When the project term ends the user can
simply be removed from the directory.
During authentication Microsoft Account users may notice the Windows
icon shown above. This icon is a visual hint to the user signing in using a
Microsoft Account.

1.5 Adding Users and Groups to Azure AD


Users and Groups can be added to a directory in a variety of ways. In no
particular order here are some common methods:

By syncing from an on-premises Windows Server Active Directory using


AAD Sync. This is how most enterprise customers will get their users

added to the directory and requires some additional server


configuration on-premises to setup.

Manually using the Azure Management Portal. The portal experience is


very easy and intuitive. Organizations that dont have an on-premises
directory may use this approach for its simplicity, provided the number
of users is relatively small. This is also very useful during development
and test phases of application development.

Scripted using PowerShell and the Azure Active Directory cmdlets.


PowerShell makes automating this task very useful, particularly for large
user bases. This too can be very useful during development and testing.

Programmatically using the Azure AD Graph API. This is an extremely


powerful option that essentially gives you full control of how users are
added to the directory. We will see examples of this later in the book.

1.6 Custom Domains


Every directory in Azure AD gets a unique DNS name on the shared
domain *.onmicrosoft.com. So, as an example, for a directory named
cloudalloc, the DNS name would becloudalloc.onmicrosoft.com. A
user in the directory would therefore have a user name such
asjohn.doe@cloudalloc.onmicrosoft.com.
By using a custom domain you are able to associate a domain you own
with a directory in Azure AD. This is not required, but often preferred by
customers who own their own domain name. Continuing with the same
example, if you owned the cloudalloc.com domain a user name would
take the form john.doe@cloudalloc.com instead of
john.doe@cloudalloc.onmicrosoft.com.
Configuring a custom domain and associating it with a directory in
Azure AD is a relatively simple process. First, you need to own the
10

domain name you want to use with your directory. Next, you need to go
through a domain verification step in Azure AD, which basically involves
updating the DNS records with your domain registrar to include a TXT
record and value (provided by Azure AD) to prove you own the domain.
The details for configuring a custom domain are covered in full detail in
this Verify a domain article on TechNet.

1.7 Protocols supported by Azure AD


As a developer building applications protected by Azure AD you will
find that Azure AD provides support for all the common protocols that
can be used to secure your applications. Some of these protocols have
been around for a really long time and as a result are widely used in the
industry today. Others are still emerging as a new (and preferred) way to
protect access to cloud applications. The protocols supported are shown
here:

WS-Federation This is arguably one of the most well-known and used


protocol today for authenticating users of web applications. Microsoft
uses this when authenticating users for some of their own cloud
applications, such as the Microsoft Azure Management portal, Office
365, Dynamics CRM Online, and more. There is fantastic tooling support
in Visual Studio 2010, 2012, and 2013 for this protocol making it very
easy for developers to protect their applications using Azure AD. The
token format used in this protocol is SAML.

SAML-P This is also a widely adopted protocol and follows a very


similar authentication pattern to WS-Federation. However, it does not
get the same level of tooling support that WS-Federation gets. The
token format used in this protocol is also SAML.

OAuth 2.0 This is an authorization protocol that has been quickly and
widely adopted in the industry as a way to sign-in users using their
credentials at popular web applications such as Facebook, Twitter, and
other social applications. Some of the benefits of this protocol is its
smaller token format, JSON Web Token (JWT), and application scenarios
11

it simplifies such as accessing Web APIs from a native client with an


access token. To do the latter with WS-Federation or SAML-P involves a
lot of intricate code and configuration.

OpenID Connect This is a protocol that adds an authentication layer


on top of the existing OAuth 2.0 protocol. Because it is layered on
OAuth 2.0, it benefits from the highly efficient JWT token format that
OAuth 2.0 uses.

The OAuth 2.0 and OpenID Connect just recently became Generally
Available (GA, or fully supported and out of preview in September of
2014) on Azure AD and there is a great amount of work going into
libraries like Active Directory Authentication Library (ADAL) and OWIN
middleware components to light up scenarios these protocols enable for
developers. This book will cover these libraries in great detail in later
chapters. The type of application you build and the requirements for your
application will largely determine which of these protocols is used to
protect the application when registering it with Azure AD. For now, it is
enough to know they are supported by Azure AD.

1.8 From Protocols to Application Endpoints


The support for these protocols is surfaced in Azure AD through a set of
Application Endpoints. These endpoints are unique for each directory (or
tenant) in Azure AD. The table below shows application endpoints and
URL for each of the supported protocols. It is these endpoints that your
application uses to leverage the various protocols when authenticating
users.

Notice

that

every

12

endpoint

starts

with https://login.windows.net/<tenant>/, where <tenant> is a


unique identifier for the directory.
Application

URL

Endpoint
Federation

https://login.windows.net/<tenant>/federationmetadata/2007-

Metadata Document

06/federationmetadata.xml

WS-Federation

https://login.windows.net/<tenant>/wsfed

SAML-P

https://login.windows.net/<tenant>/saml2

OAuth 2.0 Token

https://login.windows.net/<tenant>/oauth2/token

OAuth

2.0

https://login.windows.net/<tenant>/oauth2/authorize

Authorization

In each of these endpoints, <tenant> can be either the Guid that is


assigned to the directory, or the hostname of the directory. In other
words, for an Azure Active Directory named cloudalloc with a tenant id
of 530c3a3b-e508-4826-997a-38fb543bc87f, the following two URLs
for the WS-Federation endpoint would be equivalent.

https://login.windows.net/cloudalloc.onmicrosoft.com/wsfed

https://login.windows.net/530c3a3b-e508-4826-997a38fb543bc87f/wsfed
If a custom domain was configured for the directory, then the domain
name could also be substituted for <tenant>.
As this book progresses we will see how these endpoints are leveraged
for various types of applications.

13

1.9 Adding Applications to Azure AD


Adding applications to an Azure AD tenant (or directory) is necessary
when you want users in your organization to be authenticated against
your directory before accessing the application. By adding the
application to the directory (or registering it), you are adding
configuration that Azure AD will need to identify your application as an
application so that it can issue authentication tokens when
authenticating users.
Applications you develop can be registered with a directory in Azure AD
by using tools such as Visual Studio, the Azure Management Portal and
other command line tools. The Azure Management Portal provides an
easy wizard experience to get the process started as shown here when
you click on the add application button in the portal.

Figure 1.3
When you choose the option to add an application my organization
is developing, you must next indicate the type of application you are
going to add. The reason the type is important is because it is here
where necessary protocol artifacts will be collected leading you
eventually to the use of either WS-Federation or OAuth / OpenID
Connect. The two choices are:

14

Web Application and/or Web API Think of browser-based web


applications or services that are accessed using a browser and/or
protocols of the web.

Native Client Application Think of client applications that will run on


a desktop computer, laptop, or other smart device.

1.10 Summary
In this chapter I introduced Azure AD and some important concepts
regarding users. I talked briefly about custom domains and then wrapped
up by covering the protocols supported by Azure AD and how they are
surfaced through application endpoints unique to the directory. In the
next chapter, Ill dive into the developer experience and talk about
building on the first of the two choices mentioned in the last section
which is Web Applications and/or Web APIs.

15

Chapter 2:

Building Web Applications for Azure AD

2.1 Introduction
In the last chapter I introduced some basic concepts about Azure Active
Directory and ended with a review of the protocols and application
endpoints that are used to build applications protected by Azure AD. In
this chapter I will continue by talking about developing Web
Applications and Web APIs protected by Azure AD using Visual Studio
2013.
Before I get into the developer experience of building a Web
Application or Web API protected by Azure AD using Visual Studio, I
want to quickly pick up where I left off on the previous chapter and talk
about the portal experience of adding an application to your directory.
The experience is extremely simple and prompts you to make only four
choices as shown below, two of which require very little thought.

Figure 2.1
Here is a quick description of the four prompts.

16

1. The name of your application. This can be any name you want and is
simply how you will identify the application in your Azure Active
Directory.
2. The type of application. Notice that Web Applications and Web APIs
are considered the same type of application as far as Azure AD is
concerned. Since this article is about both, that makes this an easy
decision.
3. A Sign-On URL. This is the URL where users will access your application.
There is no verification of this URL so even if the application hasnt been
developed yet the portal will still let you add it.
4. An App Id URI. Notice this is a URI and not a URL. This is what Azure AD
will use to identify your application when authentication users
requesting access to it. It can be practically anything you want as long
as it is unique in your directory and a valid URI.
Now, click the checkmark and you have registered an application in
Azure AD. Is it really that simple? Well, not really. What you have is just
enough information at your fingertips to go build the application you
just added to your directory. And if you continue down this path I
promise you will learn to appreciate the degree of automation that
Visual Studio and the Azure SDK provides for you when building Web
Applications and/or Web APIs that are protected by Azure AD.
So, lets develop that appreciation now.

2.2

Add a Web Application to Azure AD using Visual Studio

To get started building a web application protected by Azure AD, you


must navigate your way through a few new project wizard dialogs. If you
do this correctly, you will have a new web application that is also added
to your Azure AD and configured properly, resulting in the F5 (Run)
experience weve become so accustomed to from Visual Studio.

17

Assuming that you are starting from the ASP.NET Project template for
an MVC application and will be hosting it in an Azure Website, the first
thing you must do is change the authentication type to use
Organizational Accounts (the same as Student or Work accounts
mentioned in the last article) and enter the domain (Azure AD tenant)
you are externalizing authentication to. In my sample shown here, the
Azure AD Tenant is configured with a custom domain otherwise it would
be <tenant-name>.onmicrosoft.com.

Figure 2.2
The next change you must do is specify an existing Azure SQL Database
Server to use with your application or create a new one. The reason why
this is required is because the code that is added to your project by the
ASP.NET project template when using Organizational Accounts requires
it.

18

Figure 2.3
These are the only two changes you would have to make to successfully
create a web application and add it to your Azure Active Directory using
Visual Studio. If you prefer a step-by-step experience that walks you
through every dialog and more, then please see Authenticating with
Organizational Accounts and Azure Active Directory. And if you are
interested in further understanding the SQL Database dependency I
mentioned above, then see Deep Dive: Azure Websites and
Organizational Authentication using Azure AD.
The application produced by the ASP.NET template uses Windows
Identity Foundation (WIF) in the .NET Framework to take care of
authenticating users accessing the application. WIF provides the
implementation of protocols such as WS-Federation that an application
like this uses to authenticate users. It handles redirecting
19

unauthenticated users to the correct sign-in (and sign-out) URL for their
realm, verifying the signature of the SAML token issued to the client
after successfully authenticating, managing session tokens and cookies
for the client, extracting claims about the user from the token, and
putting these claims in the principal object of the current thread. Most
of this functionality is implemented in two HTTP modules that WIF
provides, which are
the WSFederationAuthenticationModule and SessionAuthentication
Module. Visual Studio takes care of adding these in the web.config as
shown here.

<system.webServer>
<modules>
<add
name="WSFederationAuthenticationModule"
type="System.IdentityModel.Services.WSFederationAuthenticationModule,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
preCondition="managedHandler" />
<add
name="SessionAuthenticationModule"
type="System.IdentityModel.Services.SessionAuthenticationModule,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
preCondition="managedHandler" />
</modules>
</system.webServer>

20

Visual Studio also adds the configuration necessary to insure that


session security tokens can be used in a web farm type of environment
across multiple machines. This is absolutely critical in situations where
you have an Azure Website, Cloud Service or Virtual Machine configured
with multiple instances hosting your web application. Otherwise, users
would have to re-authenticate every time they landed on a different
instance or be bound to a single instance throughout the entire session
neither of which is good for scale. This powerful feature is achieved by
removing the default token handler that uses the Data Protection API
(DPAPI) and replacing it with a token handler that uses a common
machine key available to all instances as shown here. And again, this is
taken of for you by the template. If you want to know where that key is
and how it comes into the equation see the deep dive link I mentioned
earlier.

<system.identityModel>
<identityConfiguration>
<issuerNameRegistry type="CloudAlloc.Website.Utils.DatabaseIssuerNameRegistry,
CloudAlloc.Website" />
<audienceUris>
<add value="https://cloudalloc.com/CloudAlloc.Website" />
</audienceUris>
<securityTokenHandlers>
<add
type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />

21

<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler,
System.IdentityModel, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
</securityTokenHandlers>
<certificateValidation certificateValidationMode="None" />
</identityConfiguration>
</system.identityModel>

Another important element in this section of the configuration is


the <issuerNameRegistry>element. This is the class that has been
added to your project that WIF will use to validate the SAML tokens
presented to the web application. You can find it in the Utils folder of
your project.
Stepping out of the WIF configuration for a moment, if you look in
the <appSettings> section you will find some settings that should look
familiar.

<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ida:FederationMetadataLocation"
value="https://login.windows.net/cloudalloc.com/FederationMetadata/200706/FederationMetadata.xml" />
<add key="ida:Realm" value="https://cloudalloc.com/CloudAlloc.Website" />
<add key="ida:AudienceUri" value="https://cloudalloc.com/CloudAlloc.Website" />

22

</appSettings>

The first is the ida:FederationMetadataLocation. Recall from the first


chapter in this book that this was the first endpoint listed that is unique
to my Azure Active Directory. In this metadata document is a massive
amount of information about my directory tenant in Azure AD, including
the public key that is used to validate tokens. The ida:Realm is used
when unauthenticated users are redirected to Azure AD to sign-in and
the ida:AudienceUri is that unique identifier in Azure AD that I
mentioned at the very beginning of this chapter. So, where do these
appSetttings get used? Go look in App_Start\IdentityConfig.cs another
class added to your project by the ASP.NET template.

Are you starting to appreciate all the intricate WIF configuration


necessary to make a web application secure with just a few clicks? There
is so much more that I dont have space here to get into. So let me end
this with just one more element in the configuration you should at least
be aware of, which is the <system.identityModel.Services> element as
shown here.
<system.identityModel.services>
<federationConfiguration>
<cookieHandler requireSsl="true" />
<wsFederation
passiveRedirectEnabled="true"
issuer="https://login.windows.net/cloudalloc.com/wsfed"
realm="https://cloudalloc.com/CloudAlloc.Website"
requireHttps="true" />

23

</federationConfiguration>
</system.identityModel.services>

This

configuration

applies

specifically

to

the

WSFederationAuthenticationModule that I mentioned earlier. Notice the


issuer property which should also look familiar. Recall from the first
chapter in this book that this was the second endpoint listed that is
unique to my Azure Active Directory and is where users sign-in and signout of the web application.

2.3

Add a Web API Application to Azure AD using Visual Studio

To get started building a Web API application protected by Azure AD


using Visual Studio, start with the same ASP.NET project template but this
time choose Web API as shown here.

24

Figure 2.4

The rest of the experience is the same as for web applications with one
very important difference the Web API project has no requirement
for a SQL Database. Now, you may want to have a SQL Database linked
to your Web API, but just understand that the project template in this
case does not emit any code in your project that absolutely requires it.
So, youre free to choose the No database option if you like as shown
here.

25

Figure 2.5

The application produced by the ASP.NET template in this scenario


uses Microsoft Open Web Interface for .NET (OWIN) Components to
take care of authenticating users accessing the application. OWIN is still
relatively new and is essentially a specification that defines a standard
interface between .NET web servers and web applications. Microsofts
OWIN Components (aka project Katana) provide an open source
implementation of the OWIN specification with goals of being portable,
modular, and lightweight.
The application in this scenario uses OAuth 2.0 to secure the Web APIs
(REST APIs) and therefore uses the OAuth 2.0 application endpoints in
Azure AD that I mentioned in the first chapter of the book. The
implementation also takes advantage of the JSON Web Token (JWT)

26

format that is much lighter than the SAML token format we saw
previously.
Unlike WIF, OWIN is not a core component of the .NET Framework 4.5
stack. Instead, it is delivered to your project through a set of Nuget
packages as shown below, consisting of the community owned and run
Owin package (Owin.dll) and several Microsoft Owin Components that
provide the implementation of the OWIN specification.
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0"
targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security.ActiveDirectory" version="2.1.0"
targetFramework="net45" />
<package id="Microsoft.Owin.Security.Jwt" version="2.1.0" targetFramework="net45"
/>
<package id="Microsoft.Owin.Security.OAuth" version="2.1.0"
targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />

The Owin package contains the IAppBuilder interface which


standardizes the startup process for the application. Ill come back to
this interface shortly.
The web.config for this project is far less verbose and essentially comes
down to just a couple of appSettings that link back to the application
registration in Azure AD.
<appSettings>

27

<add key="webpages:Version" value="3.0.0.0" />


<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ida:Tenant" value="cloudalloc.com" />
<add key="ida:Audience" value="https://cloudalloc.com/CloudAlloc.WebAPI" />
<add key="ida:ClientID" value="024e16d8-639b-4de3-b57c-e4066473e7c9" />
</appSettings>

The ida:Tenant and ida:Audience have the same meaning as previously


discussed. Theida:ClientID is a unique identifier for the application in
Azure AD and is used if/when the Web API accesses other applications
in Azure AD. We will see this used a lot in the next couple of chapters in
this book. Thats basically it for the configuration!
Lets turn attention now to the code, which essentially comes down to
two files being added in your
project: Startup.cs and Startup.Auth.cs as shown here.

28

Figure 2.6

Startup.cs provides the class name and method signature that Katana
applications look for to configure the Microsoft OWIN components. The
Configuration method takes an IAppBuilderinterface which if you recall,
is the interface defined in the Owin.dll.
using Owin;

namespace CloudAlloc.WebAPI
{

29

public partial class Startup


{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}

The Configuration method simply calls the ConfigureAuth method in


the Startup.Auth.cs file that was added to the project that in turn adds
the Azure Active Directory JWT Bearer Token middleware to the
applications HTTP request pipeline as shown here. Notice that it is here
where the two appSettings in web.config are pulled in the configuration.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.ActiveDirectory;
using Owin;

30

namespace CloudAlloc.WebAPI
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
});
}
}
}

The bearer token middleware simply means that any party in possession
of a token (a bearer) can use it get access to the resource (the Web
API endpoints in this case) as defined in the OAuth 2.0 Authorization
Framework specification.
Just like in the Web Application scenario, this Web API project has all of
these details implemented for you and the application is automatically
registered in Azure Active Directory. Unlike the Web Application
scenario, you cannot just press F5 to run it in your browser. This is a
Web API project that expects you to be the bearer of a JWT token to
31

access the endpoints of the application. Ill show you how to get that
token and use it to access the Web API endpoints in the next chapter.

2.4 Identity in the .NET Framework


Whether authentication of users is accomplished using the WSFederation or OAuth 2.0 endpoints in your Azure Active Directory, and
whether a SAML or JWT token was presented to your application, once
your application is invoked you can access all the claims that Azure AD
(or the users identity provider) issued when the user was authenticated.
This is possible because your application is claims-aware and is the case
for any .NET application targeting .NET Framework 4.5 or newer.
In a claims-aware application the clients identity is presented as a
collection of claims to the application. And as you know, these claims
are delivered via the authentication token that the client received from
their identity provider (ie: Azure AD) after successfully authenticating.
Aclaim is a statement about the user that the identity provider can
corroborate. For example, my Azure AD can undeniably state that my
email is rick@cloudalloc.com. A claims-aware application is one
that relies on the claims presented to drive application behavior for the
user because ittrusts the identity provider it has externalized
authentication to. If you have ever heard the term relying party or RP
to describe a claims-aware or claims-based application, that is why
because it relies on the claims presented by the client provided the
claims are issued by an identity provider it trusts.
Every thread in a .NET application has a ClaimsPrincipal object that can
be used to discover the identity of the client, the identity provider that
authenticated the client, and the claims the identity provider included in
the authentication token. If you are already familiar with the traditional
IPrincipal interface in .NET, then you already know about the principal
object on the thread. And as you can see in the diagram below, the
ClaimsPrincipal class implements the IPrincipal interface making it

32

compatible with existing code. The ClaimsPrincipal also has a Claims


property that you can use to access an individual Claim for a client.

Figure 2.7

These classes are core components of the .NET Framework starting with
version 4.5. You dont need to download a Nuget package or install an
SDK. These classes are as common as System.String and are defined in
the mscorlib assembly. So, if youre targeting .NET Framework 4.5 or
newer, then your application is a claims-aware application.
The ClaimsPrincipal class has a static property called Current that will
return the ClaimsPrinicipal object for the thread. It is also equipped with
some handy methods you can used to find and retrieve the values of
claims for a client
The Claim class is used to describe statements about the Subject (or
client) that the Issuer can prove. Each claim as a Type that describes the
33

statement, such as the Subjects Name, Email, PostalCode or any other


custom claim that the issuer (or you) has added to the Claims collection.
There are 50+ predefined ClaimTypes that are used for the more
common claims. However, these ClaimTypes are simply URIs so you are
free to create custom claims for any situation. For example, you may
store a profile for a user that includes the make of the car he or she
drives and add a claim for that to the Claims collection in
a ClaimsAuthenticationManager implementation.
An example of how you can retrieve the Surname claim for a Subject is
shown here.
var principal = ClaimsPrincipal.Current;
var surnameClaim = principal.FindFirst(ClaimTypes.Surname);
var surname = (surnameClaim != null) ? surnameClaim.Value : "";

Or, if you prefer to use LINQ you could do something like this.
var principal = ClaimsPrincipal.Current;
var surnameClaim = principal.Claims.Where(c => c.Type ==
ClaimTypes.Surname).FirstOrDefault();
var surname = (surnameClaim != null) ? surnameClaim.Value : "";

As you can see the object model is extremely simple to navigate to


discover and retrieve values of claims.

2.5 Summary
In this chapter talked about the developer experience of building Web
Applications and Web API applications that are protected by Azure AD.
To recap each of these, a Web Application generated using Visual
Studio 2013 is protected by WIFs implementation of the WS-Federation
protocol which is configured via settings in web.config, code that is
added to your project, and a SQL Database that stores cryptographic
keys. The web application receives a SAML token from authenticated
34

users and WIF validates the token and extracts the claims about the
client from the token.
Web API applications generated using Visual Studio 2013 are protected
by Microsofts OWIN middleware components using OAuth 2.0 and JWT
token format. The OWIN components perform similar token validation
and also extract the claims from the token.
Finally, I wrapped up with a brief overview of the ClaimsPrincipal and
Claim classes and demonstrated how you can retrieve the claims to
drive behaviors in your application code.
In the next chapter, I will cover the Active Directory Authentication
Library (ADAL) and show you how you can use it to call Web APIs
protected by Azure AD and build native client (non-browser based)
applications for Azure AD.

35

Chapter 3:

Developing Native Client Applications

3.1 Introduction
In the last chapter I discussed developing two types of applications
protected by Azure Active Directory: web applications and web APIs. In
that chapter I approached these applications from the perspective of a
developer using Visual Studio 2013 and the project templates provided
for creating these types of applications. The automation delivered by
Visual Studio and the Azure SDK when creating these applications
resulted in the two applications being registered in my Azure Active
Directory as shown in the following Figure:

Figure 3.1

Testing the CloudAlloc.Website was a matter of simply pressing F5 in


Visual Studio to launch a browser and access the application. Recall this
application is protected using WS-Federation which redirects
unauthenticated users to a sign-in page. After successfully
authenticating, the user is redirected back to the CloudAlloc.Website
URL.
The CloudAlloc.WebAPI is protected using OAuth 2.0 and expects a valid
token in the authorization header when its endpoint is accessed. In this
chapter I am going to continue where I left off with the Web API
36

application and discuss how you can develop a native client to acquire
an access token that can be used to access the Web API.
A native client application is one that is installed on a users computer or
device. Examples of such an application include, but is not limited to,
WinForms, WPF, Windows Store, Windows Phone, and iOS applications.
And while these applications may not necessarily run in Azure as
compared to the web application and web API applications discussed in
the previous chapter, native client applications can be protected by
Azure Active Directory and access other applications registered with
Azure Active Directory.

3.2

Using claims in the Web API to drive application behavior

Before getting into the development of a native client, I want to first


point out two changes I made to the Web API to facilitate the topics
discussed in this chapter.
1. For the Get method, I changed the default implementation provided by
the Visual Studio project template to extract the claims from the
authenticated user and look for a scope claim with a value
of Read_CloudAlloc_WebAPI or Read_Write_CloudAlloc_WebAPI. If
the scope claim is found and contains one of these values, then I return
HTTP 200 (OK). Otherwise, I return an HTTP 401 (Unauthorized).
You may be wondering where I got the scope claim and value. Azure
Active Directory will add this claim and value to the claim set for
authenticated users provided that my Web API has been configured to
support this claim and my client (native client) has been granted the
permissions to include the claim. Ill come back to this shortly. For now,
just understand that with this code, the Web API now requires that this
claim and value be present for the user to be able to read these
values.The updated Get method implementation is shown here.
// GET api/values
public HttpResponseMessage Get()

37

{
// Look for the scope claim containing the
// value 'Read_CloudAlloc_WebAPI' or 'Read_Write_CloudAlloc_WebAPI'
var principal = ClaimsPrincipal.Current;
Claim readValuesClaim = principal.Claims.FirstOrDefault(
c => c.Type == "http://schemas.microsoft.com/identity/claims/scope" &&
(c.Value.Contains("Read_CloudAlloc_WebAPI") ||
(c.Value.Contains("Read_Write_CloudAlloc_WebAPI"))));
if (null != readValuesClaim)
{
//
// Code to retrieve values to include in the response goes here.
//
return Request.CreateResponse(HttpStatusCode.OK);

else
{
return Request.CreateErrorResponse(
HttpStatusCode.Unauthorized, "You don't have permissions to read values.");
}
}

2. For the chapter method, I made similar changes but instead look
for

the

scope

claim

containing

the

value Read_Write_CloudAlloc_WebAPI. If the scope claim is


found and contains this value, then I return HTTP 201 (Created) to
simulate the value being added to the server. Otherwise, I return
an HTTP 401 (Unauthorized).
implementation is shown here.

// POST api/values

38

The updated chapter method

public HttpResponseMessage Post([FromBody]string value)


{
// Look for the scope claim containing the value 'Read_Write_CloudAlloc_WebAPI'
var principal = ClaimsPrincipal.Current;
Claim writeValuesClaim = principal.Claims.FirstOrDefault(
c => c.Type == "http://schemas.microsoft.com/identity/claims/scope" &&
c.Value.Contains("Read_Write_CloudAlloc_WebAPI"));

if (null != writeValuesClaim)
{
//
// Code to add the resource goes here.
//
return Request.CreateResponse(HttpStatusCode.Created);
}
else
{
return Request.CreateErrorResponse(
HttpStatusCode.Unauthorized, "You don't have permissions to write values.");
}
}

39

Note: Generally it is recommended to organize code that tests for the


presence

of

claims

with

this

level

of

granularity

into

custom AuthorizeAttribute class. By doing so you isolate the


authorization code into one place, reducing the potential for error and
improving maintainability of the code. However, in the interest of keeping
the focus in this section on how claims can be used to make authorization
decisions, Im including it directly in the method for readability.

3.3

Exposing the Web API to other applications

To make the Web API accessible to other applications in Azure Active


Directory, permissions must be defined for the Web API that can be
assigned to other applications. The Azure Management portal does not
provide a user interface to do this. However, it does offer you access to
the applications manifest where you can configure settings for an
application, including settings that the portal doesnt provide a user
interface for. Here are the steps to get to an applications manifest using
the Azure Management portal.
1. Go to the APPLICATIONS page for the Azure Active Directory the
application is registered in.
2. Click on the name of the application whose manifest youre interested
in. For this chapter, it is the CloudAlloc.WebAPI application.
3. At the bottom of the screen click on the MANAGE MANIFEST button
and select the option to Download Manifest and save it to your local
computer, as shown in the following Figure.

Figure 3.2
40

The manifest is a JSON formatted file that contains the Azure Active
Directory configuration for an application registered in Azure Active
Directory. If you scroll through the file you will see the settings you see
on the CONFIGURE page for an application and much more. The
configuration setting were interested in for this chapter is the
oauth2Permissions setting. By default, this is an empty array, as shown in
the following Figure.

Figure 3.3

For this application (the CloudAlloc.WebAPI), I am adding two


permissions to this array; one that allows read access to the API and one
that allows read/write access to the API. Notice the valuethat I indicated
for each permission. This is where the values Im looking for in the scope
claim originate from in the Get and chapter methods above.
"oauth2Permissions": [
{
"adminConsentDescription": "Allow read access to the CloudAlloc WebAPI on behalf of
the signed-in user",
"adminConsentDisplayName": "Read access to CloudAlloc WebAPI",
"id": "1835E3A9-C857-4F33-A357-751E620E558D",
"isEnabled": true,

41

"origin": "Application",
"type": "User",
"userConsentDescription": "Allow read access to the CloudAlloc WebAPI on your
behalf",
"userConsentDisplayName": "Read access to CloudAlloc WebAPI",
"value": "Read_CloudAlloc_WebAPI"
},
{
"adminConsentDescription": "Allow read-write access to the CloudAlloc WebAPI on
behalf of the signed-in user",
"adminConsentDisplayName": "Read-Write access to CloudAlloc WebAPI",
"id": "87A81936-E765-4678-B6DB-8E12197AAA7D",
"isEnabled": true,
"origin": "Application",
"type": "User",
"userConsentDescription": "Allow read-write access to the CloudAlloc WebAPI on your
behalf",
"userConsentDisplayName": "Read-Write access to CloudAlloc WebAPI",
"value": "Read_Write_CloudAlloc_WebAPI"
}],

The schema for the oauth2Permissions can be found in the MSDN


documentation for adding, updating, and removing an application in
Azure Active Directory.

42

After making this update to the manifest file all that is left is to upload it
to Azure by clicking theMANAGE MANIFEST button and selecting
the Upload Manifest option.
Now the Web API application can be accessed from other applications
using these permissions.

3.4 Add a native client application to Azure Active Directory


Regardless of the type of native client application you plan to build, the
first step is to register it in Azure Active Directory. This is easily done using
the Azure Management portal by clicking theADD button in
the APPLICATIONS page of the directory and selecting the option to add
an application my organization is developing. This will open a wizard
where you can specify the name and type of application as Ive done in
the following Figure:

Figure 3.4

43

The next page of the wizard will prompt you for the redirect URI
associated with the native client application. This is a URI (not a URL), so
any value will work as long as it is a valid URI and is unique to your
directory. The following Figure shows the URI for the native client
application Im building.

Figure 3.5

That is all that is required to register the application with Azure Active
Directory. The application will appear in the APPLICATIONS page of the
directory as a Native client application as shown in the following Figure:

Figure 3.6
44

3.5

Configure permissions to access the Web API

Since this native client application is going to be accessing the


CloudAlloc.WebAPI I need to configure the permissions for it. In
the CONFIGURE page of the native client application is where
permissions to other applications can be set. And since my Web API
application is now accessible as a result of the manifest changes I made
earlier, I can easily configure the native client with the permissions I want
to give it. For now, Im going to start by assigning the Read access to
CloudAlloc WebAPI permission as shown:

Figure 3.7

As users of the native client application authenticate to Azure Active


Directory,

they

will

now

get

the

scope

claim

with

value

of Read_CloudAlloc_WebAPI in addition to other claims issued by Azure


Active Directory.

3.6 Develop the native client application


For this chapter Im going to build a simple console application for the
native client. However, the code in this application would work the same
for other types.
45

Recall that my Web API is protected by Azure AD and expects a security


token when accessed from client applications. So, I need a way to
authenticate users and acquire a security token (JWT) that can be used
when calling the API. Thankfully, Microsoft provides a super-handy
library called the Active Directory Authentication Library (ADAL) that
simplifies this. Since my client application is a C# console application, Ill
be using ADAL for .NET (version 2.x). But, there are other flavors
available such as ADAL for JavaScript, ADAL for Node.js, ADAL for
Java, ADAL for Android, andADAL for iOS and OSX making native client
application development for Azure AD a breeze for the most popular
languages and platforms used in the enterprise.
To facilitate constructing the HTTP requests to my Web API, I will use
the Microsoft HTTP Client Libraries (version 2.x).

3.6.1 DEFINE SETTINGS USED BY THE NATIVE CLIENT


APPLICATION
The native client application needs the Client ID and Redirect URI of the
application registered with Azure AD. The Client ID is generated
automatically when the application is registered and the Redirect URI is
the URI entered in the new application wizard earlier.
// Native client application settings
private string clientID = "386985f0-b940-4713-a8e5-f7a49d39f368";
private Uri redirectUri = new Uri("http://cloudalloc.webapi.client");

Both of these settings can be found in the properties section of


the CONFIGURE page for the native client application in the Azure
Management portal as shown:

46

Figure 3.8

When a native client needs to get a token from Azure Active Directory, it
needs to specify the resource it wants a token for. In this scenario the
client application wants access to the Web API so the APP ID URI for the
Web API is used as the resource name. After it has the token it also needs
to know the URL where the resource can be accessed, in this case the
address of the Web API.
// Resource settings this application wants to access
private string resource = "https://cloudalloc.com/CloudAlloc.WebAPI";
private Uri WebAPIUri = new Uri("https://localhost:44313

47

Both of these settings can be found in the single sign-on section of


the CONFIGURE page for theWeb API application in the Azure
Management portal as shown:

Figure 3.9

Note: The reason the reply URL is a localhost address is simply because
in the previous chapter when these applications were created and
registered in Azure Active Directory, I didnt publish them to Azure
Websites. If I had, then this reply URL would have a *.azurewebsites.net
address instead. To see how publishing a web application and/or web API
to Azure applies to applications registered in Azure Active Directory.
For ADAL to authenticate the user and acquire a token for the resource,
an AuthenticationContextmust first be instantiated by passing in the
URL of your tenant in Azure Active Directory. The URL is of the form
https://login.windows.net/<tenantID> where <tenantID> can be either
the GUID assigned to your tenant in Azure AD or the domain if you have
a custom domain configured.
// Session to Azure AD
private const string authority = "https://login.windows.net/cloudalloc.com";

48

private AuthenticationContext authContext = new AuthenticationContext(authority);

The AuthenticationContext is like a connection to your Azure Active


Directory and is ultimately used to acquire tokens from your directory.

3.6.2 CALL THE WEB API TO GET VALUES


The code to issue an HTTP GET request to the Web API essentially
breaks down to three tasks:
1. Authenticate the user and get a token from Azure Active Directory. Here
is where theAuthenticationContext instance is used to call
the AcquireToken method. If the user is not already authenticated, then
the ADAL library will launch a sign-in page for the user to sign-in with.
After successfully authenticating, a security token to access
the resourceusing the native client application is issued.
2. An HttpClient instance is instantiated and configured to include
the security token in the Authorization header for HTTP calls to the
resource (Web API).
3. An HTTP GET is issued to the resources URL to retrieve the values.
The full source code for the native client to call the Get method on the
Web API is shown here.
public async Task<bool> ReadValues()

// Authenticate the user and get a token from Azure AD

49

AuthenticationResult authResult = authContext.AcquireToken(resource, clientID,


redirectUri);

// Create an HTTP client and add the token to the Authorization header

HttpClient httpClient = new HttpClient();

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(

authResult.AccessTokenType, authResult.AccessToken);

// Call the Web API to get the values

Uri requestURI = new Uri(WebAPIUri, "api/values");

Console.WriteLine("Reading values from '{0}'.", requestURI);

HttpResponseMessage httpResponse = await httpClient.GetAsync(requestURI);

Console.WriteLine("HTTP Status Code: '{0}'", httpResponse.StatusCode.ToString());

if (httpResponse.IsSuccessStatusCode)

//

// Code to do something with the data returned goes here.

50

//

return (httpResponse.IsSuccessStatusCode);

3.6.3 CALL THE WEB API TO POST A NEW VALUE


The code to issue an HTTP POST request to the Web API is almost
identical. Since this method expects a new value in the body of the
POST, the content-type header needs to be set and the content needs
to be passed along in the body. Otherwise, its the same code.
The full source code for the native client to call the Post method on the
Web API is shown here.
public async Task<bool> WriteValue(string value)
{
// Authenticate the user and get a token from Azure AD
AuthenticationResult authResult = authContext.AcquireToken(resource, clientID,
redirectUri);

// Create an HTTP client and add the token to the Authorization header
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(

51

authResult.AccessTokenType, authResult.AccessToken);

// Construct the payload for the HTTP post operation


var newValue = new StringContent(value);
newValue.Headers.ContentType = new MediaTypeHeaderValue("application/x-wwwform-urlencoded");

// Call the Web API to post the new values


Uri requestURI = new Uri(WebAPIUri, "api/values");
Console.WriteLine("Writing value '{0}' to '{1}'.", value, requestURI);
HttpResponseMessage httpResponse = await httpClient.PostAsync(requestURI,
newValue);
Console.WriteLine("HTTP Status Code: '{0}'", httpResponse.StatusCode.ToString());

return (httpResponse.IsSuccessStatusCode);
}

3.6.4 RUNNING THE NATIVE CLIENT APPLICATION


My primitive console application calls the ReadValues method and then
the WriteValue method shown above. When AcquireToken is called in

52

the ReadValues method, I am immediately prompted to sign-in since a


token doesnt already exist for me.
After successfully authenticating, a token is issued to me and the values
are returned from the Getmethod of the Web API because the security
token included the scope claim with
theRead_CloudAlloc_WebAPI value.
Next, the WriteValue method is called. This time I am not prompted to
sign-in because ADAL has cached my token and can use it since it hasnt
expired (more on this shortly). However, because
the Read_Write_CloudAlloc_WebAPI value is not present in the scope
claim, the Post method in the Web API returned an HTTP 401
(Unauthorized).
The full output of the console application is shown:

Figure 3.10

Using the Azure Management portal, I can change the permissions for
my native client application to grant the read/write permission instead,
as shown:

Figure 3.11
53

Running the native client application now results in a successful call to


both the Get and Post methods as shown:

Figure 3.12

3.7 ADALs Token Cache and Refresh Tokens


Previously I mentioned that ADAL cached my token. ADAL does this
automatically without you having to write any code, resulting in a
positive experience for the end-user. If the token hasnt expired, ADAL
will re-use it in subsequent calls to AcquireToken. However, even if the
token has expired, the end-user may still avoid being prompted to signin if a refresh token was issued when the access token was issued.
A refresh token, which may not always be present, can be used to
acquire a new access token on behalf of the user if Azure AD allows it.
As long as the users account in Azure AD hasnt been deleted, disabled,
or some other change in the directory that would invalidate the token,
the refresh token can be exchanged for a new access token. Best of all,
ADAL will use the refresh token to acquire a new access token if it can
and do so without you having to write any code.

3.8 Summary

In this chapter I demonstrated how to use claims in a Web API


application protected by Azure Active Directory to make authorization
decisions based on the presence of a scope claim in the authenticated
users claim set.
54

Next, I discussed how to expose the Web API to other applications in


Azure AD by defining permissions in the oauth2Permissions array that
can be updated in the manifest file for the Web API. By defining
permissions for the Web API, other applications can be configured to
access the application with selected permissions using the Azure
Management portal.
After the Web API was updated and configured, I discussed the steps
necessary to register a native client application in Azure Active
Directory. Using values in Azure Active Directory for the registered
native client application, I then showed how to develop a console
application that uses the Active Directory Authentication Library (ADAL)
and the Microsoft HTTP Client Library to securely call the Web API.
Running the native client, we were able to observe the benefit of the
token cache provided by ADAL and the use of a refresh token to avoid
unnecessarily prompting the user for credentials.
In the next chapter, I will show how you can extend this scenario and
make authorizations decisions based on a users group membership.

55

Chapter 4:

Group Claims

4.1 Introduction
In the last chapter I showed how you can use the Active Directory
Authentication Library (ADAL) to build a native client application that calls
the CloudAlloc.WebAPI introduced in earlier chapters of this book. As part
of that chapter, I demonstrated how the Web API could be exposed to
other applications using ouath2Permissions that I defined in the
manifest which enabled me to assign these permissions to my native
client application as shown:

Figure 4.1

Being able to assign read and write permissions in this way provided an
easy and useful way to control an applications ability to invoke various
operations using the claims that were issued by Azure Active Directory
for an authenticated user. However, the level of granularity for which
authorization decisions can be made in the application code is pretty
coarse with this approach. In my example, it was the simple read and write
permissions I defined and if the native client application was configured
to allow write permissions, then any authenticated user would be able to
invoke such operations. While that may be sufficient for some
applications,

others

may

require

additional

information

about

the user before making such authorization decisions. For example, you
may want to restrict write operations to users in a specific security group.
As you can see in Figure 2, the claims provided by Azure Active Directory
for our authenticated user John Doe just dont provide that level of detail
56

about the user (yet). Other than some various identifier claims about John
Doe, were currently limited to the values in the scope claim to make
authorization decisions.

Figure 4.2
A common need for many applications is the ability to make authorization
decisions based on a users membership in a specific security group (or
groups). In this chapter Im going to show how you can take advantage
of some recently released features of Azure Active Directory to do just
that.

4.2

Using Group Claims to Drive Authorization Decisions

Now, you can just look for it in the Claims collection for the authenticated
user provided you enable the group claims feature for your application in
Azure AD. Lets see how this would work for the application weve been
talking about and only allow users to invoke the POST method if they are
in the Dev/Test security group.

57

4.2.1 ENABLE

GROUP

CLAIMS

FOR

THE

CLOUDALLOC.WEBAPI APPLICATION
Enabling the group claims feature currently requires that you update the
manifest for the application in Azure AD. This is exactly the same
process I showed you in the last chapter where I set
the oauth2Permissions for the application.
In the Azure Management portal Ill begin by going to
the CONFIGURE page for the CloudAlloc.WebAPI application in Azure
AD. At the bottom of the page is a MANAGE MANIFESTbutton where I
can select to download the manifest for the CloudAlloc.WebAPI
application as shown in Figure 3.

Figure 4.3

The application manifest is just a JSON file that you can edit with the
simplest of editors (ie: notepad.exe). By the way, if youre curious what
the GUID in the filename is about when you download the manifest, it is
the Client ID that was assigned to the application when it was registered
in

Azure

AD.

Scrolling

down

the

manifest

file

will

find

the groupMembershipClaimsproperty which will be set to null as shown


here in Figure 4.

Figure 4.4
Im going to change this value to SecurityGroup and then save the
changes as shown in Figure 5.

58

Figure 4.5

Your choices for setting the groupMembershipClaims property


are null (the default), All orSecurityGroup. If you
choose SecurityGroup you will get group claims in the JWT token for
just security groups the user is a member of. If you choose All you will
get group claims in the JWT token for security groups and distribution
lists the user is a member of.
All that remains now is to upload the modified manifest file which I did
using the MANAGE MANIFEST button.
With that change in place, I will now start getting group claims in the
token for users of my application. As mentioned above, Im interested in
checking for the users existence in the Dev/Test security group. So,
before I show you the code changes needed to do this, lets review my
security groups and where our John Doe user lands in these groups.

4.2.2 LOCATE

THE

OBJECT

ID

FOR

THE

DEV/TEST

SECURITY GROUP
When Azure AD adds applicable group claims to the token it issues for
my users, the value for the group claim will be the Object ID of the security
group and not the name of the security group. Remember, every entity in
Azure AD has a unique Object ID associated with it. You may think it
would be more intuitive to refer to the group by name instead of the
Object ID. This is true. However, a groups name can be changed in the
directory so it is not a reliable identifier for the group. The Object ID will
never change as long as the group exists. So, in this case, I need to find
the Object ID for the Dev/Test security group. This can be found in
59

the CONFIGURE page of for my Dev/Test security group as shown here


in Figure 6.

Figure 4.6
Now that I have the Object ID for the Dev/Test security group I am ready
to make the necessary code changes.

4.2.3 UPDATE THE POST METHOD TO LOOK FOR DEV/TEST


GROUP CLAIM
The only code change needed is to look for a groups claim with the value
of 244728b5-8b9e-4e2f-8703-9853366cd431 in the authenticated
users claims collection as shown here.
60

// POST api/values
public HttpResponseMessage Post([FromBody]string value)
{
// Look for the scope claim containing the value 'Read_Write_CloudAlloc_WebAPI'
var principal = ClaimsPrincipal.Current;
Claim writeValuesClaim = principal.Claims.FirstOrDefault(
c => c.Type == "http://schemas.microsoft.com/identity/claims/scope" &&
c.Value.Contains("Read_Write_CloudAlloc_WebAPI"));

// Look for the groups claim for the 'Dev/Test' group.


const string devTestGroup = "244728b5-8b9e-4e2f-8703-9853366cd431";
Claim groupDevTestClaim = principal.Claims.FirstOrDefault(
c => c.Type == "groups" &&
c.Value.Equals(devTestGroup, StringComparison.CurrentCultureIgnoreCase));

// If the app has write permissions and the user is in the Dev/Test group...
if ((null != writeValuesClaim) && (null != groupDevTestClaim))
{
//
// Code to add the resource goes here.
//
return Request.CreateResponse(HttpStatusCode.Created);
}

61

else
{
return Request.CreateErrorResponse(
HttpStatusCode.Unauthorized, "You don't have permissions to write values.");
}
}

Note: As I pointed out in the last chapter, it is a good idea to organize


code like this into a customAuthorizeAttribute class or some other
common class so that your application logic and authorization logic are
not mixed together. Im intentionally leaving that as an exercise to you
the reader though.
Thats all there is to it! Now, lets observe the results of these changes
by examining the claims collection for the authenticated user

4.2.4 EXAMINING THE GROUP CLAIMS


I ran the application under the debugger and set a breakpoint in the POST
method so I could show you the new group claims in the claims collection.
As shown here in Figure 7, you can see there are two groups claims
present.

Figure 4.7

62

The value for the first groups claim should look familiar it is the Object
ID for the Dev/Test group I discussed earlier. The second one happens to
be a Developer security group in my directory for which John Doe is a
member. Figure 8 shows the membership for both security groups.

Figure 4.8

Notice that John Doe is explicitly identified as a member of the


Developer security group but not the Dev/Test group. Yet, in the token
issued to John Doe, a group claim was present for both of these security
groups. This is because the group claims feature in Azure AD is
transitive. So, since John Doe is a member of the Developer group and
the Developer group is a member of the Dev/Test group, John Doe is a
member of both security groups.
As you can imagine, in a real world production environment a user is
likely to be a member of many different security groups. When you
enable the group claims feature the tokens issued for users will contain
the group claims for all of these groups which could greatly increase the
63

size of the token. Therefore, there are limits on the number of group
claims that Azure AD will place in a token as follows:

JWT Tokens: Up to 200 group claims

SAML Tokens: Up to 150 group claims


Currently there is not a way to filter the group claims that Azure AD
places in a token. So, if users in your directory could potentially exceed
these limits you will need a different solution.

4.3

Working with the Azure AD Group Claims Limit

The Azure AD Graph API is a REST API that Azure Active Directory makes
available for each tenant. With it you can programmatically access the
directory and query about users, groups, contacts, tenant details and
more. In addition to querying the directory, the Azure AD Graph API can
be used to create, update and even delete entities in the directory.
For the scenario mentioned above, the Azure AD Graph API could be
used to look up the security groups a user belongs to or to check if a
user is in a specific security group. The latter is particularly applicable in
our scenario here and could be achieved using the IsMemberOf
function. To execute this query you need only the Object ID of the user
and the Object ID of the security group. The query will execute in Azure
AD (server side) and simply return true or false. Prior to the release of
the group claims feature in Azure AD discussed in this chapter, this was
the only way to check group membership for a user. In situations where
the number of groups a user is in could potentially exceed the limits
above, it is still available to you.

64

4.4 Summary
In this chapter, I showed how to take advantage of the new Azure Active
Directory group claims feature and apply it to our scenario to determine
a users membership in a particular security group. I also discussed the
group claims limit as it applies to JWT and SAML tokens issued by Azure
AD

and

how

you

can

fall

back

on

the

Azure

AD

Graph

APIs IsMemberOf function to query the directory and determine the


same.

65

Vous aimerez peut-être aussi