<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ockamey</title>
    <description>The latest articles on DEV Community by ockamey (@ockamey).</description>
    <link>https://dev.to/ockamey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F370279%2Fa9ec5cf4-3cc6-4507-8340-2c04ef6aedda.jpg</url>
      <title>DEV Community: ockamey</title>
      <link>https://dev.to/ockamey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ockamey"/>
    <language>en</language>
    <item>
      <title>Configuring Roles in Azure Active Directory</title>
      <dc:creator>ockamey</dc:creator>
      <pubDate>Thu, 15 Oct 2020 04:53:00 +0000</pubDate>
      <link>https://dev.to/ockamey/configuring-roles-in-azure-active-directory-2gd0</link>
      <guid>https://dev.to/ockamey/configuring-roles-in-azure-active-directory-2gd0</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In my previous articles I've uncovered how to configure scopes in Azure Active Directory (If you haven't seen them, you can find the first part &lt;a href="https://dev.to/czmiel24/configuring-scopes-in-azure-active-directory-part-1-3bio"&gt;here&lt;/a&gt; and the second part &lt;a href="https://dev.to/czmiel24/configuring-scopes-in-azure-active-directory-part-2-3npp"&gt;here&lt;/a&gt;). In this tutorial, we'll work on roles, which is a great mechanism, used for authorization. Firstly I'll explain the basics of the RBAC concept, and then by using an example, I'll walk through the main features related to roles in AAD. So let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Concept&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the concept of scopes, the user &lt;strong&gt;allows&lt;/strong&gt; the client's application to perform particular actions on behalf of them in a resource application. The RBAC (Roles Based Access Control) concept states what a user/application is &lt;strong&gt;allowed&lt;/strong&gt; to do in a resource application, based on the particular roles they have. It means that, for example, the user that has the role of &lt;em&gt;Reader&lt;/em&gt; can read books, but they can't moderate them because they don't have the role of &lt;em&gt;Moderator&lt;/em&gt;. This means it's more focused on what the end-user/application can and cannot do. This is a really rough definition, thus, I encourage you to read some articles on the internet about it if you don't feel confident about RBAC. There are plenty of articles but &lt;a href="https://auth0.com/docs/authorization/concepts/rbac" rel="noopener noreferrer"&gt;this&lt;/a&gt; is one I can highly recommend.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First of all, we're going to need to create two applications in AAD(the same as in my Scopes tutorial): both a Client and a Resource application. You can do this by following these steps:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; New registration:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxvt238i13dhhlw8z3xoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxvt238i13dhhlw8z3xoi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to fill in the Name textbox (you can provide a different name, of course, but I suggest using the same one, because I’ll continue to use the same name throughout this tutorial):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj0pzwzds6bqg58g6h8sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj0pzwzds6bqg58g6h8sc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same requirement needs to be completed for the Resource Application. As shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frc5zznwuvfg3vq0vgxr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frc5zznwuvfg3vq0vgxr7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve created two different applications in AAD (these are not WebService or Azure Function applications or any other — both are only representations of physical applications in AAD):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClientApp&lt;/strong&gt; — this application represents the service that communicates with the Resource application directly, for example, service to service (e.g. an Azure Function communicates with another Azure Function). This is why we'll use this application when assigning roles to the application, and acquiring token using Client Credentials. For flow where a user is present I'll use OpenID Connect in which using the &lt;em&gt;ClientApp&lt;/em&gt; isn't needed, but won't feel afraid, I'll present the example step by step. If you aren't familiar with OpenID Connect, in my first tutorial about scopes I've attached great video about it, so feel free to watch it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BooksCollectionApp&lt;/strong&gt; — this application represents the Resource Application that may have sensitive information belonging to the User (e.g. WEB API could contain a User’s secret books).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to set up a few things before we go on to creating roles. Firstly, we have to add a redirect URL to both our applications. Second, we have to enable ID tokens for the BooksCollectionApp, as we want to use OpenID Connect to authenticate users.&lt;/p&gt;

&lt;p&gt;Let's go to the Authentication option in the &lt;em&gt;ClientApp&lt;/em&gt; by following:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; ClientApp -&amp;gt; Authentication&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click the "Add a platform" button, and on the panel on the right hand side, select "Web block":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc91cvq29v3gqf8aex7r6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc91cvq29v3gqf8aex7r6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, fill in the Redirect URLs as shown in the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhqutcoz7bvrk2xesclls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhqutcoz7bvrk2xesclls.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click the "Configure" button. You may notice that I've put the localhost there. This is because it's for testing purposes, and I don't want to be redirected (my code being sent) to other websites. In the real case scenario, you should provide the address to your real hosted application.&lt;/p&gt;

&lt;p&gt;We almost have to replicate the same actions for the &lt;em&gt;BooksCollectionApp&lt;/em&gt;, however, the ID tokens checkbox must also be selected, as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fymjpotwoh811e7hhmr4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fymjpotwoh811e7hhmr4q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again click the "Configure" button.&lt;br&gt;
Now the prerequsites have been completed, we can start to focus on, the main point of this tutorial, roles in our applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating roles&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the Azure Active Directory we can differentiate two types of roles: one for users, and another for applications. While this tutorial was being created, the only way to define roles in an application was to do it in the application's Manifest (application definition in JSON format). Let's go ahead and create one for a user and one for an application.&lt;/p&gt;

&lt;p&gt;To get to the Manifest, you have to follow:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; BooksCollectionApp -&amp;gt; Manifest&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once completed, you should see a similar screen, as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foqygecsv9b4tml6164yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foqygecsv9b4tml6164yd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The red underlined part shows the definitions of the roles, this means there haven't been any roles defined in our application yet. Let's create one by adding an item into the array, as shown in the snippet below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
        "allowedMemberTypes": [
            "User"
        ],
        "description": "Enables a user to read books",
        "displayName": "Reader",
        "id": "2ef66a29-eaa8-4b0d-8763-aaafb2002a5a",
        "isEnabled": true,
        "lang": null,
        "origin": "Application",
        "value": "Reader"
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We've created a &lt;em&gt;Reader&lt;/em&gt; role that only exists for users (because we've inserted a &lt;code&gt;User&lt;/code&gt; value into the &lt;code&gt;allowedMemberTypes&lt;/code&gt; array). In the final application (e.g. WebAPI or Azure Function) this role can be used to permit all users that have the &lt;em&gt;Reader&lt;/em&gt; role to read books. &lt;br&gt;
Next, we'll create another role, this time for applications only:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
        "allowedMemberTypes": [
            "Application"
        ],
        "description": "Enables an application to create/edit/delete books",
        "displayName": "Moderator",
        "id": "67d25112-7487-4cce-a131-d933adb7ff95",
        "isEnabled": true,
        "lang": null,
        "origin": "Application",
        "value": "Moderator"
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the snippet above, we've created the role &lt;em&gt;Moderator&lt;/em&gt; which can only be used by applications (the value &lt;code&gt;Application&lt;/code&gt; can be seen in the &lt;code&gt;allowedMemberTypes&lt;/code&gt;). This could mean that, only applications that contain a token with the role of &lt;em&gt;Moderator&lt;/em&gt;, can moderate books in the end application. &lt;br&gt;
After our changes, the &lt;em&gt;appRoles&lt;/em&gt; part of the Manifest file in the Portal should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwqzv6rxub7mx7ydm5wdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwqzv6rxub7mx7ydm5wdq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep in mind that, when you create a new role, you have to provide a unique &lt;code&gt;id&lt;/code&gt; every time. I encourage you to use a GUID generator for this purpose. The second thing that I'd like to point out is, you can create a role that can be assigned to both users and applications. You can do this by adding two items to the array.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Assigning user roles&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In order to assign a role to a user, you first have to go to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; Enterprise applications-&amp;gt; BooksCollectionApp -&amp;gt; Users and groups&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, click the button "Add user" as shown in the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft65i6v2uai1vearbfj0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft65i6v2uai1vearbfj0p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next screen, you can specify what role should be assigned to the user. For the non-testing solutions, I wouldn't recommend assigning a role to single users, hovever, I would instead assign a role to the whole group as it ensures less maintenance work in the future. For this tutorial though, we'll only assign a simple role to the user, namely the &lt;code&gt;Reader&lt;/code&gt; role.&lt;/p&gt;

&lt;p&gt;In the "Add Assignment" view select the user that you want to assign the &lt;code&gt;Reader&lt;/code&gt; role to, and as far as the role is concerned, you don't need to select anything because we've only specified this one specific role for the users purposes. The assignment should resemble the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdgvtntw6ogq6h1be5wdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdgvtntw6ogq6h1be5wdc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking the "Assign" button, you should be redirected to the "Users and groups" view, which shows the assignment that we've made:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1gzm0iiwn0r7yuf6mdxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1gzm0iiwn0r7yuf6mdxd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perfect, so now we can check if the &lt;code&gt;Reader&lt;/code&gt; role is visible in the user's token. In my previous tutorial, I've shown you how to get a token via Authorization Code and Client Credential flow, but now we'll take advantage of Open ID Connect to get a token for the user. &lt;br&gt;
Let's prepare the request in the Postman, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvrywfp4lnahbjdtxdrs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvrywfp4lnahbjdtxdrs2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember that in place of the black box (between domain name and &lt;code&gt;ouath2&lt;/code&gt; element in the URL) you have to place &lt;strong&gt;your&lt;/strong&gt; tenant id and in place of the &lt;code&gt;client_id&lt;/code&gt; value, you must insert the Client ID of &lt;strong&gt;your&lt;/strong&gt; BooksCollectionApp. The parameters &lt;code&gt;response_type&lt;/code&gt; and &lt;code&gt;scope&lt;/code&gt; show that we want to obtain a token using Open ID Connect. The &lt;code&gt;redirect_uri&lt;/code&gt; that was provided at the start of this tutorial must be inserted in the same way during the creation of the application. The &lt;code&gt;nonce&lt;/code&gt; parameter is there for security reasons, to prevent token &lt;a href="https://medium.com/@benjamin.botto/oauth-replay-attack-mitigation-18655a62fe53" rel="noopener noreferrer"&gt;replay attacks&lt;/a&gt; (it should be a random value, but in our case I've chosen a pretty round one).&lt;br&gt;
Copy the request's URL and paste it to the browser, then you'll be redirected to the login page. &lt;br&gt;
Remember that you have to log in as the user that you've specified in the role assignment view. After logging in, you should be able to see the consent view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdvdm6ky82ljskecaa5th.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdvdm6ky82ljskecaa5th.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you give the application consent, you'll be redirected to a localhost and in the query parameters you'll be able to see the token, as shown in bold below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;a href="https://localhost:44327/signin-oidc#id_token=%7B" rel="noopener noreferrer"&gt;https://localhost:44327/signin-oidc#id_token={&lt;/a&gt;&lt;b&gt;TOKEN&lt;/b&gt;}&amp;amp;session_state=7d973d4b-3c74-49be-c180abf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copy the token, and paste it into the input box, from this page: &lt;a href="https://jwt.ms" rel="noopener noreferrer"&gt;https://jwt.ms&lt;/a&gt; which will allow us to decode the token and to see what's inside. After doing that you should be able to see a view, similar to this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3lkiax2f41w53mqpsjwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3lkiax2f41w53mqpsjwr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see, that our token has two very important claims: &lt;code&gt;aud&lt;/code&gt; which points to the &lt;em&gt;BooksCollectionApp&lt;/em&gt;, and &lt;code&gt;roles&lt;/code&gt; which states what roles have been assigned to us. Based on this information, the end application e.g. Azure Function or WebAPI is able to authorize the action that we want to perform. In our case, it means that we're able to read books.&lt;/p&gt;

&lt;p&gt;Try getting a token for other users that haven't been assigned to this role, and check to see if they also have the same &lt;code&gt;Reader&lt;/code&gt; role in their token!&lt;/p&gt;

&lt;p&gt;In this tutorial, we've used OpenID Connect to get the token, hovever, it should be noted, that you can also use Authorization Code flow, just as we've used in the previous tutorials. You can treat this as homework ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Assigning application roles&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this scenario, we would like to assign the role of &lt;em&gt;Moderator&lt;/em&gt; to the &lt;em&gt;ClientApp&lt;/em&gt;. This can be extremely helpful when, there are for example, many services that connect to one service and we only want to allow certain services to perform particular actions, in this case, role based access control fits well. To configure it in AAD, first of all, you have to go to the "API Permissions" view in your &lt;em&gt;ClientApp&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; ClientApp -&amp;gt; API Permissions&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Firstly, click the "Add a permission" button, subsequently the panel on the right-hand side should be displayed. The "My APIs" button must be selected and the "BooksCollectionApp" clicked, as shown in the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frniwy7u353jg356x1xh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frniwy7u353jg356x1xh5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The panel should change to the one presented below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fujbyhxtdj6j6t4na5qmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fujbyhxtdj6j6t4na5qmg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the panel, you can see two types of permissions: Delegated and Application. In the previous articles about scopes, I've explained that "Delegated permissions" are related to scopes. Application permissions though are related to the different roles that can be assigned to applications. This means that if you click "Application permissions", you'll get a list which shows all the roles from the selected application that are defined by "Application" in the &lt;code&gt;allowedMemberTypes&lt;/code&gt; contained within Manifest. This is why you can only see the &lt;em&gt;Moderator&lt;/em&gt; role, without the &lt;em&gt;Reader&lt;/em&gt; role. &lt;/p&gt;

&lt;p&gt;Let's select Application permissions, check &lt;em&gt;Moderator&lt;/em&gt; role, and click the "Add permissions" button. &lt;/p&gt;

&lt;p&gt;After that you should see the list of scopes and roles, as presented below, that have been assigned to the &lt;em&gt;ClientApp&lt;/em&gt; application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F76c8cdld00sqzshpqtq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F76c8cdld00sqzshpqtq3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that the &lt;em&gt;ClientApp&lt;/em&gt; application has two permissions assigned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User.Read - which is a scope (this is because the type column is "Delegated").&lt;/li&gt;
&lt;li&gt;Moderator - the role that we've just assigned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All application roles require "Admin consent", this means that the Global Administrator has to click the button "Grant admin consent for..." to make these roles work with the application. Go ahead and click the button "Grant admin consent for..." which can be seen above in the permissions table. After clicking it, you should see that the status of the permission has changed to allow access, as can be seen with the green tick. A similar view is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmhh0idfgfm3twxru2jgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmhh0idfgfm3twxru2jgk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step to ensure you have the "Moderator" role is to get a token to check if the "Moderator" role is contained. We'll use the Client Credentials flow, because this is an OAuth flow that doesn't require a user. So let's generate a request in the Postman:&lt;/p&gt;

&lt;p&gt;Keep in mind that the &lt;code&gt;client_id&lt;/code&gt; and the &lt;code&gt;client_secret&lt;/code&gt; are the Client ID and the Client Secret of your &lt;em&gt;ClientApp&lt;/em&gt;. The &lt;code&gt;grant_type&lt;/code&gt; parameter specifies that we're using the Client Credentials flow, and the &lt;code&gt;scope&lt;/code&gt; parameter should be either &lt;code&gt;{{Application ID URI}}/.default&lt;/code&gt; or &lt;code&gt;{{Resource application ClientID}}/.default&lt;/code&gt; (I've described it better in my previous tutorial). In your case you should provide &lt;code&gt;{{Your BooksCollectionApp ClientID}}/.default&lt;/code&gt;. As can be seen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F69ss3kjud9yndmijtlgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F69ss3kjud9yndmijtlgr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Send the request, copy the token and paste it to the following: &lt;a href="https://jwt.ms" rel="noopener noreferrer"&gt;https://jwt.ms&lt;/a&gt;. If you've done everything correctly, the &lt;em&gt;Moderator&lt;/em&gt; role should be visible in your JWT. The token that has been obtained in jwt.ms looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe80e8v6lan2rmiw8asdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe80e8v6lan2rmiw8asdg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the role in the token contains &lt;em&gt;Moderator&lt;/em&gt;, then you have correctly assigned it to the &lt;em&gt;ClientApp&lt;/em&gt;. Additionaly, you can create another application in AAD and try to obtain a token for it, to ensure that there is no &lt;em&gt;Moderator&lt;/em&gt; role included.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now finished my basic tutorial on how to configure roles in Azure Active Directory. I hope that I have enlightened you on the Roles concept in AAD and it is now more familiar to you. If you want more information I advice you to check out Microsoft's documentation to get more details. If you have any further questions, feel free to write some comments below. &lt;/p&gt;

</description>
      <category>azure</category>
      <category>oauth</category>
      <category>roles</category>
      <category>aad</category>
    </item>
    <item>
      <title>Configuring Scopes in Azure Active Directory (Part 2)</title>
      <dc:creator>ockamey</dc:creator>
      <pubDate>Mon, 08 Jun 2020 08:06:07 +0000</pubDate>
      <link>https://dev.to/ockamey/configuring-scopes-in-azure-active-directory-part-2-3npp</link>
      <guid>https://dev.to/ockamey/configuring-scopes-in-azure-active-directory-part-2-3npp</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Welcome to the second part of my tutorial about scopes in Azure Active Directory. During the first part, I described the basics about scopes e.g. how to get a token that contains specific scopes or how to add scopes into your application. You can find a link to it &lt;a href="https://dev.to/czmiel24/configuring-scopes-in-azure-active-directory-part-1-3bio"&gt;here&lt;/a&gt;.&lt;br&gt;
In this part, I'll cover how to complete more advanced features or setup features that you don't normally configure on a daily basis. If you haven't looked at the first part of my tutorial, I highly recommend doing it because in this part I'll continue working on the applications that have already been created. In addition, I'll sometimes briefly mention procedures that are expanded upon in more detail in the first part. E.g. the first request required for getting a token means "sending GET request in your browser", and a second request means "sending POST request to exchange the authorization code for a token".&lt;br&gt;
Let's begin once again from approving consent scopes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Administrator only consent scopes - another way to approve&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There is another way that an administrator can give consent to a scope. If the Global Administrator clicks the link below: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;a href="https://login.microsoftonline.com/" rel="noopener noreferrer"&gt;https://login.microsoftonline.com/&lt;/a&gt;&lt;b&gt;{tenant_id}&lt;/b&gt;/adminconsent?client_id=&lt;b&gt;{client_id}&lt;/b&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;They'll be redirected to another consent view, and after giving consent, the status of the scope should change to green. Bear in mind that in place of &lt;code&gt;{tenant_id}&lt;/code&gt; in the above link you need to place your Tenant ID and similarly in place of &lt;code&gt;{client_id}&lt;/code&gt;, the Client ID of your &lt;em&gt;ClientApp&lt;/em&gt; should be placed.&lt;br&gt;
The outcome will be the same as clicking the button "Grant consent for …" as I presented in the "Scopes that only Administrators can consent to" section in the first part.&lt;/p&gt;

&lt;p&gt;It's also possible to enable users to send a request to the administrator, requesting them to Grant permission using the build-in flow. In order to turn on this feature, you need to go to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; Enterprise applications -&amp;gt; User settings -&amp;gt; set "Users can request admin consent to apps they are unable to consent to"&lt;/em&gt; to Yes.&lt;/p&gt;

&lt;p&gt;After the administrator who will receive requests to their email is selected, the window stating that administrator approval is required will change slightly, as can be seen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe2856muwx31z3vau0386.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe2856muwx31z3vau0386.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Manifest&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There is another way to create scopes. If you go to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; BooksCollectionApp -&amp;gt; Manifest&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You'll see the following Manifest file, it's in JSON format and contains the whole configuration of your application. In this JSON there is an &lt;em&gt;oauth2Permissions&lt;/em&gt; array, underlined below, which contains all scopes in your application. You can easily create scopes by just adding items to the array, it must be remembered, that every single scope needs to have a unique property id and you can use any kind of GUID generator to generate this id. Below it can be seen how the &lt;em&gt;Books.Read&lt;/em&gt; scope is set out in the &lt;em&gt;BooksCollectionApp&lt;/em&gt; manifest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4u1fyot2ue8f1pumzi30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4u1fyot2ue8f1pumzi30.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Authorized Client Applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the &lt;em&gt;"Expose an API"&lt;/em&gt; view there is another feature, apart from Scopes definitions, that I'd like to cover here. This feature is called &lt;em&gt;"Authorized Client Applications"&lt;/em&gt;, which is found below the table of scopes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gd7tx6gxk2acv5271uh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gd7tx6gxk2acv5271uh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To analyze this feature, let's create another scope in the &lt;em&gt;BooksCollectionApp&lt;/em&gt; (bear in mind that this process is contained within the &lt;em&gt;BooksCollectionApp&lt;/em&gt;, not in the &lt;em&gt;ClientApp&lt;/em&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiy80hq5ukejcpx0cjx2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiy80hq5ukejcpx0cjx2b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's add in an authorized client application, you do this by clicking the &lt;em&gt;"Add a client application"&lt;/em&gt; button in the &lt;em&gt;"Expose an API"&lt;/em&gt; view. As can be seen below, you need to paste the &lt;em&gt;ClientApp's&lt;/em&gt; Client ID into the Client ID input and then tick the box: &lt;em&gt;Books.ReadWrite&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmwuhscbntxeeqjszmw5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmwuhscbntxeeqjszmw5m.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And click the "Add application" button. &lt;/p&gt;

&lt;p&gt;Please note, you should wait a couple of minutes before trying to get the token. After waiting a few minutes, send the request to obtain an Authorization Code in your browser, be sure to use the &lt;em&gt;Books.ReadWrite&lt;/em&gt; scope and the &lt;em&gt;ClientApp's&lt;/em&gt; Client ID and Client Secret. It can be seen that the consent window didn't show up at all, even though this action was performed for the first time. While not being apparently obvious, you were redirected to the localhost and provided with an Authorization Code immediately. This is the main idea of this feature. As long as you trust the &lt;em&gt;BooksCollectionApp&lt;/em&gt;, and the &lt;em&gt;BooksCollectionApp&lt;/em&gt; trusts the &lt;em&gt;ClientApp&lt;/em&gt; (by adding it to the Authorized client applications), thus, there was no need to show you the consent view. It was made in a more granular way, meaning enabling specific scopes for the &lt;em&gt;ClientApp&lt;/em&gt; but not all of them.&lt;/p&gt;

&lt;p&gt;I have discovered the following: when you add any scope in the &lt;em&gt;"Authorized client applications"&lt;/em&gt; section, then you can't get a scope that requires administrator consent for a user. To display this, leave &lt;em&gt;"Authorized client applications"&lt;/em&gt; with the &lt;em&gt;Books.ReadWrite&lt;/em&gt; scope ticked, and try to get a token which specifies the &lt;em&gt;Books.Read.All&lt;/em&gt; scope in the request. You should receive an error message which states that you need to be provided with admin consent. Once you remove the scope &lt;em&gt;Books.ReadWrite&lt;/em&gt; from the &lt;em&gt;"Authorized client applications"&lt;/em&gt;, you'll once again be able to get the token.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Disabling the option that allows users to consent&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you'd like to disable the future user from being able to give consent in your organization. You can read Microsoft's recommendations &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-user-consent" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To carry out the above, go to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; Enterprise applications -&amp;gt; User settings -&amp;gt; set "Users can consent to apps accessing company data on their behalf"&lt;/em&gt; to No. &lt;/p&gt;

&lt;p&gt;As below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwv8zw0jc9ed0pzshr1is.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwv8zw0jc9ed0pzshr1is.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To see this feature in action, one additional scope in the &lt;em&gt;BooksCollectionApp&lt;/em&gt; should be added:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5vh9wf38iomdu1w1pwa3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5vh9wf38iomdu1w1pwa3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill in the inputs like above and click the &lt;em&gt;"Add scope"&lt;/em&gt; button. Let's try to get a new token, using the new scope, firstly compose the Authorization Code request and copy this from the Postman to your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp9pmu65taqak6ik21nu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp9pmu65taqak6ik21nu5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After sending the request, the consent window should look like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fymqfguh32j6k3eapmwzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fymqfguh32j6k3eapmwzz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can see, despite the fact that the scope is set for admins and users, only a Global Administrator can give consent to the &lt;em&gt;ClientApp&lt;/em&gt;. Since a regular user can't, the only way to allow regular users to get a token containing the specific scope is to add the application and scope to the &lt;em&gt;"Authorized client applications"&lt;/em&gt; as found in the &lt;em&gt;"Authorized Client Applications"&lt;/em&gt; section. This option gives the owner of the &lt;em&gt;BooksCollectionApp&lt;/em&gt; control over which applications can have access to which scopes.&lt;br&gt;
Note that we have seen this feature in action, to continue this tutorial switch &lt;em&gt;"Users can consent to apps accessing company data on their behalf"&lt;/em&gt; back to &lt;em&gt;"Yes"&lt;/em&gt;. Please note, it can take a while to make this particular option work properly, in my case it took about 10min.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prompt Query Parameter&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After you give consent to a scope, the consent window won't pop up again, asking you to give your consent, a second time for the same scope. To force AAD to show a user the consent window every single time, you have to add one additional query parameter into the first request, the parameter's name is prompt. Go ahead and send the same request from your browser as in the example provided at the beginning of the first part tutorial with the modification that is shown below. Another important consideration, is that you shouldn't have any &lt;em&gt;Authorized client application&lt;/em&gt; scopes in the &lt;em&gt;BooksCollectionApp&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4r1f8foxn4v9efgjpy63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4r1f8foxn4v9efgjpy63.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may have probably noticed, every single time you send the request you receive the consent window, even though you have consented already earlier. &lt;br&gt;
There are a few different options for the prompt parameter, these include, e.g.: &lt;em&gt;login&lt;/em&gt;, &lt;em&gt;none&lt;/em&gt; and &lt;em&gt;select_account&lt;/em&gt;. You can read about them &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Display names&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While creating scopes, you should know that you need to provide display names and descriptions for the scope (actually, only the display name and description for administrators are required). The display name and description for users are displayed on the regular consent window. The administrator’s display name and description will only show up when the administrator grants consent for the client's app using the following link:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://login.microsoftonline.com/{tenant_id}/adminconsent?client_id={client_id}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you'd like more information on the  granting consent by following a link process, you'll find it in the section &lt;em&gt;"Administrator only consent scopes - another way to approve"&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Scopes in Authorization Endpoint V1 and V2&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the &lt;em&gt;"API permission"&lt;/em&gt; view we didn't have to add any scopes to our client's application that didn't require administrator consent, because we used Azure AD V2 Authorization Endpoint, instead we specified them in the request's query parameters (dynamic consent). If we had used V1, we would have had to specify all scopes in the &lt;em&gt;"Api permission"&lt;/em&gt; view (static consent) instead of in the request's query parameter, this is because in V1 there is a &lt;strong&gt;resource&lt;/strong&gt; query parameter (where you add Application URI or Client ID), not the &lt;strong&gt;scope&lt;/strong&gt; query parameter. You can find more information by clicking the following &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Client Credentials flow&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the Client Credentials flow, in comparison to the Authorization Code flow, a user can't be present, therefore, this flow is popular in the case of service to service connections (e.g. One Azure Function sends a request to a different Azure Function). In order to obtain an access token, only one request is required. On the screen below, you can find the details of the request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feoufltlga8v4eswlu1s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feoufltlga8v4eswlu1s8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may have probably noticed, this request is similar to the JWT exchange request, not only is it a POST request, it also has the /token endpoint. The two main differences are shown above, in the &lt;code&gt;grant_type&lt;/code&gt; parameter Client Credentials flow can be easily seen. What about Scopes? I'll give a detailed explanation below.&lt;/p&gt;

&lt;p&gt;In case of the Client Credentials flow scopes aren't possible, this is because it is not feasible for a user to be able to give consent, this is especially because, as was mentioned before, there is no user in this flow. It must be mentioned, however, that a scope parameter is required in a request, so in order to comply with this rule, the value of the scope parameter should be either &lt;code&gt;{{Application ID URI}}/.default&lt;/code&gt; or &lt;code&gt;{{Resource application ClientID}}/.default&lt;/code&gt;. &lt;br&gt;
If you decide to send the above request and decode the access token using e.g. &lt;a href="https://jwt.ms" rel="noopener noreferrer"&gt;https://jwt.ms&lt;/a&gt;, you'll discover that there is actually no &lt;em&gt;"scp"&lt;/em&gt; claim at all, because it's not relevant in this scenario. &lt;br&gt;
In the next article I'll explain Roles in the Azure Active Directory, these will be able to be assigned to both applications and users, that being said, they can be visible in the JWT for both cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;More than one scope&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There is a possibility to specify more than one scope, in the scope parameter in the request you can add another scope by inserting a space between them. If you look closely you can see this below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7d7cdtarbmvqq4cyrfhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7d7cdtarbmvqq4cyrfhe.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The space is the separator between scopes, however, they must be from the same application e.g. &lt;code&gt;https://bookscollectionapp.com&lt;/code&gt;. You'll receive an error message if you specify more than one scope from different applications:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsc0qle8ogri2emd6dcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsc0qle8ogri2emd6dcc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Client ID instead of Application ID URI&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Whenever you send a scope in the request, there is another way to specify the resource application. Up until now, we have always used &lt;code&gt;{{Application ID URI}}/{{scope}}&lt;/code&gt; pattern, but instead of providing the &lt;em&gt;Application ID URI&lt;/em&gt; we can just use &lt;code&gt;{{Resource application ClientID}}/{{scope}}&lt;/code&gt;. So in our case, the first request should look like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frt7r8zr86oovfalludx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frt7r8zr86oovfalludx5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bear in mind that in your case, the value of the &lt;em&gt;BooksCollectionApp&lt;/em&gt; Client ID must equal &lt;strong&gt;your&lt;/strong&gt; &lt;em&gt;BooksCollectionApp&lt;/em&gt; Client ID. Using this approach has one consequence that comes to my mind. If you exchange the Authorization Code for the JWT, and decode it (I've shown how to obtain it in the first part of the tutorial), it should be apparent, that instead of the Application ID URI in the &lt;em&gt;"aud"&lt;/em&gt; claim, you'll see your Resource Client ID in your token. Below you can find the specific fragment of my access token:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fif0u17yzi2004ybmz6lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fif0u17yzi2004ybmz6lc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now finished the second part of my scope tutorial. In the next coming weeks, I'm going to release a similar tutorial to this one which will cover Roles in Azure Active Directory. I hope that scopes are now more familiar to you than at the beginning of the tutorial. If you have any further questions feel free to write some comments below.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>oauth</category>
      <category>scopes</category>
      <category>aad</category>
    </item>
    <item>
      <title>Configuring Scopes in Azure Active Directory (Part 1)</title>
      <dc:creator>ockamey</dc:creator>
      <pubDate>Mon, 20 Apr 2020 17:12:44 +0000</pubDate>
      <link>https://dev.to/ockamey/configuring-scopes-in-azure-active-directory-part-1-3bio</link>
      <guid>https://dev.to/ockamey/configuring-scopes-in-azure-active-directory-part-1-3bio</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When I started learning Azure Active Directory, I was pretty overwhelmed by the Microsoft documentation, which in my opinion was pretty complicated (especially for people who don’t have much experience at configuring any OAuth Authorization Servers — like me). Since I’ve spent a lot of time reading Microsoft documents, blogs, and have experimented by myself and with my teammates (thanks &lt;a href="https://www.linkedin.com/in/tpadams89/" rel="noopener noreferrer"&gt;Tim&lt;/a&gt;!), I’d like to share with you what I’ve learned about AAD during this time.&lt;/p&gt;

&lt;p&gt;I’ve always been a big fan of the “Example first” way. Using this idea, I’m going to walk you through some examples and, hopefully, after reading this tutorial, you can approach Microsoft Documentation fearlessly.&lt;/p&gt;

&lt;p&gt;This article assumes that you already have a good understanding of OAuth 2.0, especially Authorization Code flow. If you don’t, I highly recommend you watch this great video: &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/996OiexHze0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://oauth2.thephpleague.com/terminology/" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is the OAuth terminology that will be used throughout this tutorial.&lt;/p&gt;

&lt;p&gt;I also assume that you have your own tenant in Azure and it’s associated with the valid subscription. If not, you can find tutorials how to do it &lt;a href="https://docs.microsoft.com/bs-latn-ba/azure/active-directory/fundamentals/active-directory-access-create-new-tenant" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/pl-pl/azure/active-directory/fundamentals/active-directory-how-subscriptions-associated-directory" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Throughout this tutorial I’ll be using only Azure AD Endpoint V2, however, in one section I’ll add in some basic differences between V1 and V2.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First, we’ll create two applications in AAD, that will represent both Client and Resource Applications. You can do this by following these steps:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your Azure Active Directory instance -&amp;gt; App registration -&amp;gt; New registration:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjek8t0is4wfuly1r75gd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjek8t0is4wfuly1r75gd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to fill in the Name textbox and the Redirect URI as shown on the screenshot below (you can provide different names, of course, but I suggest using the same ones, because I’ll use these during this tutorial):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg3flvfvb1c509un7a2hr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg3flvfvb1c509un7a2hr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same requirement needs to be completed for the Resource Application. Here is the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh7ixn3b4fiohy4b9s3so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh7ixn3b4fiohy4b9s3so.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve created two applications in AAD (these are neither WebService nor Azure Function applications and so on — both are only representations of physical applications in AAD):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClientApp&lt;/strong&gt; — this application represents the application that communicates with the user directly (e.g. ASP.NET application) and acts on behalf of the User when communicating with the BooksCollectionApp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BooksCollectionApp&lt;/strong&gt; — this application represents the Resource Application that may have sensitive information belonging to the User (e.g. WEB API contains User’s data).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating scopes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, let’s create scopes. To do this, let’s first go to the details of the &lt;em&gt;BooksCollectionApp&lt;/em&gt; in App Registrations. Next, select Expose an API, then click the &lt;em&gt;“Add a scope”&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;When you click this button for the first time, you should see a new window stating that you need to add an &lt;em&gt;“Application ID URI”&lt;/em&gt; before proceeding. Let’s assign a URI that will represent your application (like Domain Name). I’ve used &lt;code&gt;https://bookscollectionapp.com&lt;/code&gt;. You can pick any valid URI, that’s unique across your tenant; you don’t need to buy a domain.&lt;/p&gt;

&lt;p&gt;Next fill in the panel like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9ggqxav1rh4o7wqwbxrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9ggqxav1rh4o7wqwbxrr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It means that this scope is meant for everybody, not only for administrators. These administrators won’t have to give consent to enable this scope for users (I’ll explain it better later on). Both the Display name and the Description input above, will be shown on the consent page while getting JWT.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Getting access token&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now let’s use Postman to get a token which will contain the scope created above. Normally, a web app or mobile app would redirect you to log-in to the Microsoft website to receive an Authorization Code. Then the app would exchange the Authorization Code for a JWT. Exchange for a JWT only occurs during Authorization Code flow. To keep things simple and to better understand, we won’t build an app, we’ll just use Postman.&lt;/p&gt;

&lt;p&gt;In order to get a JWT, there will be two stages:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Getting an Authorization Code
&lt;/h3&gt;

&lt;p&gt;During this stage, we actually don’t need Postman at all, only a browser. However, I use Postman to generate URLs that are copied and pasted to a browser later.&lt;/p&gt;

&lt;p&gt;To create a GET request like in the screen below, you need to paste your Tenant ID in the black box. I’ve changed my Tenant ID to black in the hope that you won’t hack me :D. Second, change the &lt;em&gt;client_id&lt;/em&gt; value to &lt;strong&gt;your&lt;/strong&gt; &lt;em&gt;ClientApp&lt;/em&gt; Client ID. Then, change the scope value in a way that replicates the following:&lt;br&gt;
&lt;code&gt;{{your BooksCollectionApp Application ID URI}}/Books.Read&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can find your Client ID and Tenant ID in the Overview of your application in the Application Registration panel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyvxspwoaieiqa3zmzvaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyvxspwoaieiqa3zmzvaf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following on, copy the link from the Postman (the one that is underlined in red above) to your browser. After sending the request, you should be able to see the following screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8t44t7z7k3kfzhi650rw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8t44t7z7k3kfzhi650rw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The consent view shows the user what the &lt;em&gt;ClientApp&lt;/em&gt; will be able to do on behalf of them.&lt;/p&gt;

&lt;p&gt;Next, press accept and you should be redirected to &lt;em&gt;&lt;a href="https://localhost:44327/signin-oidc" rel="noopener noreferrer"&gt;https://localhost:44327/signin-oidc&lt;/a&gt;&lt;/em&gt;, and in the query parameter code your Authorization Code will be contained:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;a href="https://localhost:44237/signin-oidc?code=" rel="noopener noreferrer"&gt;https://localhost:44237/signin-oidc?code=&lt;/a&gt;&lt;b&gt;AQABAAIAAAAm-06blBE1TpVMil8KPQ41DmEwZFwyAM06SoXS0-M0oC2oKw85100IlRqALFCc8x3_XbOql3smPubHvda7WBiUNRIAxYnnCRWj7WBXD0QGK-1xDtuBxzCauxKd5N9ZEEKv_vn4I4x4tC6EsU7SlH81Abmlxw8njiHtuVszhQiRonSP7xLubXYvJ0MEvit_YExvfx0EkPPQh1nZlN8KQwde05zIvXvpgHFqyw1QxH52bs7bgFGauhFBnd8tn1iwmE74BKLufGOwCtBT4dqhpTK17s49s-FzRckDeKGQJouD758Pf0qsyTzdIUNst2rWNk2A7IL_Hv_BX1vb9T_KCpyzphPre7iVCLJdm3cGNrYUzVVUFwMrOPBWyHtsdei8Zf4BJqFYSFvVBs5Xa6CSuDWfVy0HVWJlTYnSRUBz6hFYsgP4sAlrMpT4IAA&lt;/b&gt;&amp;amp;session_state=c67ad588-c6b5-4419&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copy the code, but be careful not to press Shift + End because there is one more query parameter at the very end.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Exchanging Authorization code for an access token (JWT)
&lt;/h3&gt;

&lt;p&gt;The next step is to exchange the access code for JWT. We must send a POST request from Postman as shown in the screenshot below. The value of &lt;code&gt;{{client_id}}&lt;/code&gt; is the &lt;em&gt;ClientApp’s&lt;/em&gt; Client ID. You can generate the &lt;code&gt;{{client_secret}}&lt;/code&gt; by going to “Certificates &amp;amp; secrets” in the &lt;em&gt;ClientApp&lt;/em&gt; view, and &lt;code&gt;{{tenant_id}}&lt;/code&gt; is your Tenant ID. You can take advantage of the Environments feature in Postman, the same as what I’ve used. During the last step you must insert your Authorization code in place of “HERE PASTE YOUR AUTHORIZATION CODE”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmgonmfxogpglkyi38tyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmgonmfxogpglkyi38tyl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking the Send button, your response should resemble below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2z5j6ougu275ztzccyso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2z5j6ougu275ztzccyso.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After generating your Client Secret, it may take some time to propagate the changes, thus, if you receive the error that states the Client Secret value is invalid, you should consider sending the request again in about 1–2min.&lt;/p&gt;

&lt;p&gt;Copy the value of the access_token property (it’s a JWT), ensuring not to include the quotation marks, and paste the token at &lt;a href="https://jwt.ms" rel="noopener noreferrer"&gt;https://jwt.ms&lt;/a&gt;. Now you should be able to see that your token has been decoded. The parts you should focus on are the &lt;em&gt;“aud”&lt;/em&gt;, &lt;em&gt;“appid”&lt;/em&gt; and &lt;em&gt;“scp”&lt;/em&gt; properties. Below, you can see some parts of my token (I’ve removed parts of it for security reasons):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F048s7nbos37lcuknnhws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F048s7nbos37lcuknnhws.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;“aud”&lt;/em&gt; claim is the abbreviation for &lt;em&gt;Audience&lt;/em&gt; and its value is the &lt;em&gt;BooksCollectionApp’s&lt;/em&gt; Application ID URI — AAD takes the Application ID URI from the scopes parameter from the first request. The &lt;em&gt;“appid”&lt;/em&gt; is the &lt;em&gt;ClientApp’s&lt;/em&gt; Client ID. The &lt;em&gt;“scp”&lt;/em&gt; above is the space separated scope (there can be more than one value). As you can see, the scope is exactly the same value that we had previously used in our &lt;em&gt;BooksCollectionApp&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This means that when the &lt;em&gt;ClientApp&lt;/em&gt; (e.g. ASP.NET application) passes our token to the &lt;em&gt;BooksCollectionApp&lt;/em&gt; (e.g. WEB API), the &lt;em&gt;BooksCollectionApp&lt;/em&gt; knows that it shouldn’t allow the &lt;em&gt;ClientApp&lt;/em&gt; to perform any other action than reading the user’s books. The &lt;em&gt;ClientApp&lt;/em&gt;, on behalf of us, won’t be able to write anything to the &lt;em&gt;BooksCollectionApp&lt;/em&gt;. This can only happen if we trust the &lt;em&gt;BooksCollectionApp&lt;/em&gt; to follow the scopes provided in your token.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;An alternative way to get an access token from Postman&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the previous section, I showed you how to get an access token using Postman, however, there is actually an easier and quicker way to receive it from there. If you select any request in Postman, you’ll be able to see an &lt;em&gt;Authorization&lt;/em&gt; tab, like in the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3uza3no83cisutiqwm98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3uza3no83cisutiqwm98.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to get JWT from AAD, you should select &lt;em&gt;OAuth 2.0&lt;/em&gt; from the type menu and click the &lt;em&gt;“Get New Access Token”&lt;/em&gt; button. After the pop-up window has appeared, you’ll need to fill in the inputs as shown in the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4pm17stjxegdwl2wu6gf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4pm17stjxegdwl2wu6gf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After accomplishing the above, click the &lt;em&gt;“Request Token”&lt;/em&gt; button. A new window will pop up, containing the consent view. If it’s accepted, the &lt;em&gt;Access Token&lt;/em&gt; input in the request will be filled in with the desired JWT. Please be advised, if you ask for the same scope as in the previous section, you won’t get the consent view, because you’ll have already given consent for this scope.&lt;br&gt;
The result of the above will be the same as the method described in the previous section, but if something goes wrong (e.g. if you pass a wrong parameter), this method won’t provide you with many details about the error. Taking everything into consideration, this is why I prefer the explicit (previous) flow.&lt;br&gt;
One important thing that should be remembered is the following difference between &lt;em&gt;Auth URL&lt;/em&gt; and &lt;em&gt;Access Token URL&lt;/em&gt;. These are both similar, but not the same. The first endpoint points to the function of actually getting the Authorization Code, and the second one points to the function of exchanging the Authorization Code for JWT.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Scopes that only Administrators can consent to&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, let’s create a different scope that requires administrator’s consent. Return to the &lt;em&gt;BooksCollectionApp&lt;/em&gt; and to the “Expose an API” panel and add a new scope (make sure to select &lt;em&gt;“Admins only”&lt;/em&gt; in the &lt;em&gt;“Who can consent option”&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmma9fchemgqj5ul89izn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmma9fchemgqj5ul89izn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s now try to get a new token using the new scope:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8h1ubini2fitrf068f1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8h1ubini2fitrf068f1v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should probably get the token without any problems; you might ask yourself why? Since it’s been changed so that only administrators can consent! The answer to your possible question is that you are probably a Global Administrator. In order to get a better idea of this option, you should be a regular User. If you don’t have any regular users in your tenant, you can add them in by creating a new one by going to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your tenant -&amp;gt; Users -&amp;gt; All users -&amp;gt; New user.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After completing the above, let’s now try getting an Authorization Code by logging in as a regular user. After logging in as a regular user you should see the view below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjwwdtct6q495meyyt6b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjwwdtct6q495meyyt6b6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that the user wants to use the admin only scope. We’ve created the scope &lt;em&gt;Book.Read&lt;/em&gt;.&lt;strong&gt;&lt;em&gt;All&lt;/em&gt;&lt;/strong&gt; for this reason, it means that everybody who uses the scope, will also be able to read all users books (not just the logged-in user’s books), of course, only if the physical application is implemented in this way. In a real scenario, the Owner of the &lt;em&gt;ClientApp&lt;/em&gt; (the Owner is the person who has created the application — you can see the list of owners in the &lt;em&gt;Owners&lt;/em&gt; panel contained within your application) should ask a Global Administrator to give consent, if the &lt;em&gt;ClientApp&lt;/em&gt; needs to use this scope. In order to allow an administrator to give consent, the Owner must go to the &lt;em&gt;ClientApp&lt;/em&gt; and add the scope to the &lt;em&gt;API Permissions&lt;/em&gt; panel. Let’s go ahead and do this.&lt;/p&gt;

&lt;p&gt;Go to:&lt;br&gt;
&lt;em&gt;ClientApp in App Registrations -&amp;gt; ClientApp -&amp;gt; API permissions -&amp;gt; Add a permission -&amp;gt; My API’s -&amp;gt; BooksCollectionApp -&amp;gt; Delegated permissions -&amp;gt; Check “Books.Read.All”&lt;/em&gt;. As below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj3gwhpzlkmfvpvc5qnpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj3gwhpzlkmfvpvc5qnpc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may have noticed, there are two different types of permissions: &lt;em&gt;Delegated&lt;/em&gt; and &lt;em&gt;Application&lt;/em&gt;. When thinking about scopes, these are &lt;em&gt;Delegated&lt;/em&gt; permissions. &lt;em&gt;Application&lt;/em&gt; permissions are &lt;em&gt;App Roles&lt;/em&gt; which contains an &lt;em&gt;Application&lt;/em&gt; allowed member type (I’ll write a similar tutorial for &lt;em&gt;App Roles&lt;/em&gt; in the future). After the scope has been added, you should see the table below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fse21z5qefkj39pcbtc8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fse21z5qefkj39pcbtc8o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a real case scenario, the Owner of the &lt;em&gt;ClientApp&lt;/em&gt; should ask the Global Administrator to grant permission to the &lt;em&gt;ClientApp&lt;/em&gt; application, this can be done by clicking the button &lt;em&gt;“Grant admin consent for…”&lt;/em&gt;. The Global Administrator, after validating the request, should click &lt;em&gt;“Grant admin consent for…”&lt;/em&gt; button, giving consent for the application. In our case the button &lt;em&gt;“Grant admin consent for…”&lt;/em&gt; only needs to be clicked. After completing this, the following should be visible below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2bfjq4j5z9wohanq9xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2bfjq4j5z9wohanq9xw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once again, let’s try to get a token as a regular user. If you have copied everything provided in this tutorial correctly, you will be presented with the JWT which contains the &lt;strong&gt;Books.Read.All&lt;/strong&gt; scope.&lt;/p&gt;

&lt;p&gt;Hold on, how was I able to get the token with the proper scope without the consent view showing up?! This has happened because you’re not an administrator and as it has been shown previously, this specific scope requires Administrator Consent to obtain. At first, it may be a little bit confusing, especially because the purpose of scopes is to show the user what the Client can do on behalf of them and now there is no consent view, however, there is logic behind this concept. The scope requires administrator consent and it must be remembered that you don’t have administrator privileges. It took me some time to clarify this and I recommend you to go over this section a few times to ensure it’s clear :D.&lt;/p&gt;

&lt;p&gt;Now in your JWT there should be more than one scope, as can be seen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo049i2guxfqfpsr8topy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo049i2guxfqfpsr8topy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I hope that this tutorial has helped you better understand Scopes in Azure Active Directory. It hasn’t comprehensively covered everything required to understand all details related to scopes. In the next coming weeks, I plan to release the second part of this tutorial, which includes more features that you can perform with Scopes. In the meantime, if you have any questions feel free to get in touch with messages and comments below.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>oauth</category>
      <category>scopes</category>
      <category>aad</category>
    </item>
  </channel>
</rss>
