Chapter 4 Implement Azure security

Regardless of the application, most of them have a standard requirement— protect the information that it manages. When we talk about security, we need to think in the five dimensions of information security awareness: integrity, availability, confidentiality, authorization, and no-repudiation. Each of these dimensions is useful for evaluating the different risks and the countermeasures that you need to implement for mitigating the associated risks.

Implementing the appropriate security mechanism on your application can be tedious and potentially error prone. Azure offers several mechanisms for adding security measures to your applications, controlling the different security aspects for accessing your data, and controlling the services that depend on your applications.

Skills covered in this chapter:

Skill 4.1: Implement authentication

Skill 4.2: Implement access control Skill 4.3: Implement secure data solutions

Skill 4.1: Implement authentication

When a user wants to access your application, the user needs to prove that she is who she claims to be. Authentication is the action that the user performs to prove his or her identity. The user proves his or her identity using information known only to the user. An authentication system needs to address how to protect that information so only the appropriate user can access it while nobody else—not even the authorization system—can access it. A solution for this problem is to allow the user to access his or her data by using two different mechanisms for proving his or her identity—information that only the user knows and showing something, a token, only the user has. The approach is known as multifactor authentication.

Azure provides a secure mechanism for integrating authentication into your applications. You can use single-factor or multifactor authentication systems without worrying about the intricate details of implementing this kind of system.

This skill covers how to:

  • Implement authentication by using certificates, forms-based authentication, or tokens
  • Implement multifactor or Windows authentication by using Azure AD
  • Implement OAuth2 authentication
  • Implement Managed Service Identity (MSI)/Service Principal authentication

Implement authentication by using certificates, forms-based authentication, or tokens

The authentication process requires the user to provide evidence that the user is who he or she claims to be. In the real world, you can find multiple examples of authentication; for example, every time that you show your driver’s license to a police officer, you are actually authenticating against the police officer. In the digital world, this authentication happens by providing some information that only you know, such as a secret word (a password), a digital certificate, or any kind of token that only you possess.

You have a range of options for implementing such an authentication mechanism in your application. Each implementation has its pros and cons, and the appropriate authentication mechanism depends on the level of security that you require for your application.

The most basic way of authenticating a user is form-based authentication. When you use this mechanism, you need to program a web form that asks the user for a username and a password. Once the user submits the form, the information in the form is compared to the values stored in your storage system. This storage system can be a relational database, a NoSQL database, or even a simple file with different formats stored on a server. If the information provided by the user matches the information stored in your system, the application sends a cookie to the user’s browser. This cookie stores a key or some type of ID for authenticating subsequent requests to access your application without repeatedly asking the user for his or her username and password.

The main drawback of using this authentication method for your application is that data travels from the user’s browser to the server in plain text, meaning other malicious users could intercept the communications and get the password quickly. You can mitigate this risk by forcing your application and users to use HTTPS only. The following example shows how to implement form-based authentication. The example uses the template provided in Visual Studio for deploying an MVC ASP.NET application:

  1. Open Visual Studio 2017 on your computer.
  2. Click on File > New > Project.
  3. In the New Project window, in the tree control on the left side of the window, navigate to Installed > Visual C# > Web.
  4. In the list of templates in the center of the New Project window, select the template ASP.NET Web Application (.NET Framework).
  5. On the bottom side of the New Project window, provide a name for the project and the solution. Also, choose a location for storing the project.
  6. Click the OK button in the bottom-right corner of the New Project window.
  7. In the New ASP.NET Web Application window, select MVC from the list of templates in the center of the window.
  8. Ensure that the MVC option is checked under Add Folders And Core References For located below the templates.
  9. Click the Change Authentication button at the middle-right of the window.
  10. In the Change Authentication window, select Individual User Accounts.
  11. Click OK.
  12. On the New ASP.NET Web Application window, click OK.

At this point, you have created a basic ASP.NET Web Application configured for using form-based authentication. Also, this web application has configured other authentication mechanisms that we are going to review later in this section.

Now you can check how the authentication in this application works:

  1. Press F5 to run the project.
  2. In the top-right corner of your application’s web browser, click Register.
  3. On the Register form, enter an email address and password.
  4. Click on the Register button at the bottom of the form.
  5. Once you have registered, you are automatically logged on, and you can log off and log in again to ensure everything works properly.

This example is based on the ASP.NET Identity framework. This library allows you to quickly implement different authorization methods and control other essential aspects of the identity management operations that you need to perform on your application.

When you need to implement form-based authentication, you need to deal with three key components:

Authentication forms You need to provide the user with the appropriate web form, not only for providing the user’s credentials but also for resetting the user’s password in case the user forgot it. You might also need a form that allows new users to register to your application.

Credentials storage You need to store the passwords of your registered users. You use the password provided by the user to compare with your stored password. If the values match, then the user is authenticated.

Credentials management This is the piece of your code that makes the comparison between the value provided by the user and the value that you have stored in the application’s credential storage. You usually never store the user’s password in plain text. Instead, you use one of the available hashing algorithms for storing the hashed value of the real password. This component performs all these hashing operations, as well as password resets and new user registration.

Because you implemented the Model-View-Controller pattern in this example, as you selected the MVC template in step 7 of the previous procedure, you need to use views for creating the different forms that you need for presenting the necessary information to the user. The general operations that the user needs to perform are logging in, registering, and recovering a lost password. You use the following views for providing these functionalities to the users:

Login Managed by the Login.cshtml view.

Register Managed by the Register.cshtml view.

Forgot the password Managed by the ForgotPassword.cshtml view.

You can review the content of these views in the Visual Studio Solution Explorer; navigate to the Views > Accounts folder inside your project folder. Listing 4-1 shows the content of the Login.cshtml view. You can review this listing to see how to construct the login form to provide the necessary information to the controller. The bold parts in Listing 4-1 show the significant code for implementing the login form:

Listing 4-1 Login.cshtml

	
// C#. ASP.NET.
@using ch4_1_1.Models
@model LoginViewModel
@{
ViewBag.Title = "Log in";
}
<h2>@ViewBag.Title.</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.
ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role =
"form" }))
{
@Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 controllabel" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
<p>
@Html.ActionLink("Register as a new user", "Register")
</p>
@* Enable this once you have account confirmation enabled for password reset functionality
<p>
@Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*@
}
</section>
</div>
<div class="col-md-4">
<section id="socialLoginForm">
@Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel
{ ReturnUrl = ViewBag.ReturnUrl })
</section>
</div>
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
	

When you review the code in Listing 4-1, you need to focus on some key points. You used model binding for sending the information to the web application. In this example, the LoginViewModel model is used:

	
@model LoginViewModel
	

Another important point is where the information is sent when the user submits the form. In your code, you set the action URL or the route that is going to process the form when the user submits it, by providing the appropriate values to the BeginForm method:

	
Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.
Post, new { @class = "form-horizontal", role = "form" })
	

This method creates an HTML form tag where the attribute action is /Account/Login and where Account is the controller that manages the Login action. This method also sets HTTP POST as the method for sending the information to the application. Because you are using model binding, you bind the value of the input forms to the properties of the LoginViewModel, as you can see in the following lines highlighted in Listing 4-1:

	
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.CheckBoxFor(m => m.RememberMe)
	

When the user submits the information for creating a new login account, the application saves this information in the storage system. In this example, you use an SQL Server Express LocalDB database for storing the entities that your application needs. Your application uses the ApplicationUser class for managing the users who can access your application. This class, shown in Listing 4-2, inherits from the IdentityUser class defined in the ASP.NET Identity framework.

Listing 4-2 ApplicationUser class

	
// C#. ASP.NET. IdentityModels.cs
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager
<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in
// CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this,
DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
	

ASP.NET Identity uses the Entity Framework for managing the models needed by your application. The default entities provided by ASP.NET Identity are:

Users This entity stores the users registered in your application. The entity stores the username, email, the hashed password, and a security stamp for controlling any changes in the user credentials.

User Claims This entity stores different statements about the user and associates it with the user entity.

User Logins This entity stores information about external authentication providers, such as Twitter, a Microsoft Account, or Facebook.

Roles This entity represent groups of users who have specific access privileges to your application, like “Admin” or “User” roles.

When you run the example application for the first time, the Entity

Framework creates all the necessary tables for your application, as shown in Figure 4-1. You can view the users registered in your application by rightclicking the AspNetUsers table and clicking View Data in the contextual menu.

Figure 4-1 Tables for storing entities for a form-based authentication
Screenshot_30

The Identity Framework uses the UserManager<T> class for managing all the operations related to your application users. Because of the way the Identity Framework works, the UserManager class sends the information to the UserStore class that is in charge of persisting the information in the database. In your example, you can see how the UserManager class uses the CreateAsync method for persisting the newly created user in the database by reviewing the Register method in the AccountController.cs file. Listing 4-3 shows how you should use the CreateAsync method for creating new users in your database.

Listing 4-3 Persisting a new user in the database

	
// C#. ASP.NET. AccountController.cs
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form return View(model);
}
	

Because the Entity Framework is the base for the storage system of your user’s credentials and identities, you can easily change the underlying storage and use other systems, such as Azure Storage Table, or other relational databases engines, such as SQL Server.

Need More Review? Extending The Profile Information

By default, the ApplicationUser class that you use in the previous example only contains two properties: email and password. You can extend these properties by taking advantage of the Entity Framework. The following articles show how to extend the default user identity:

Customizing profile information in ASP.NET Identity in VS 2013 templates:

https://devblogs.microsoft.com/aspnet/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates/

Add, download, and delete custom user data to Identity in an ASP.NET Core project:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/add-user-data

When the users of your application submit the information for login or registering in your application, their web browsers send that information to your application, and then your application processes the request for creating the user in the database or authenticating the user. In a form-based authentication mechanism, the authentication process is performed by your code; it compares the value of the hashed password stored in your database with the hashed value of the password provided by the user on your web form. Your application also needs to ensure that any request made to the application needs to be authenticated before serving the content to the user. To avoid having the application prompt the user for credentials every single time the user tries to access to a protected section of your application, you need to save the credentials into a cookie that the user’s browser provides to your application. The application usually encrypts the content of this cookie, so no malicious user or process can easily guess the username and password of a valid user of your application.

Fortunately, the Identity Framework takes care of most of these operations for you, and you only need to correctly configure it to your needs. This configuration consists of two different steps:

Configuring the form-based authentication Configuring the middleware filtering

By using the MVC pattern to configure middleware filtering, you ensure that all requests to your application are evaluated before sending the information to the controllers. You configure your application to require authentication for all actions in your controllers. The middleware sits between the request and the controller to enforce this requirement.

This example uses the Open Web Interface for .NET (OWIN) specification for managing the interaction between the code and the web server. OWIN is an open-source specification that decouples the code from the implementation of the web server on which your code is supposed to run. OWIN can do this by running as a middleware in your application. This means you need to make the configurations to your code in the Startup class instead of using Global.asax.cs.

Need More Review? OWIN and Project Katana

OWIN is an open-source specification, not an implementation by itself. Each vendor can make its own implementation of the OWIN specification. Project Katana is Microsoft’s implementation of the OWIN specification.

You can read more about project Katana and OWIN by reviewing the Microsoft Doc An Overview of Project Katana at https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-andkatana/an-overview-of-project-katana

You configure the Identity Framework for managing the authentication of your application by using two different files—Startup.Auth.cs and IdentityConfig.cs. You use the Startup.Auth.cs class for making the basic configuration of the authorization features that you want to enable in your application. We saw that one of the characteristics of the form-based authentication is that you need to store the user and passwords needed to grant access to the application. You can use different storage solutions for this credential storage system, but you would typically use a relational database like SQL Server. Although the Identity Framework allows you to abstract from the storage details, you still need to provide some configuration for storing users and passwords. In the Startup.Auth.cs file, this line attaches the database connection, defined in the connectionStrings sections in the Web.config file, to your code:

	
app.CreatePerOwinContext(ApplicationDbContext.Create);
	

In this example, the ApplicationDbContext class inherits from the IdentityDbContext that provides the persistence layer to the UserManager class.

Once you added the persistence layer to the application, you need to add the UserManager and SignInManager classes, as shown in the following lines in the Startup.Auth.cs file:

	
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(Applic
	

The ApplicationUserManager class that inherits from the UserManager class manages all the operations related with the user, like creating new users, deleting old users, or checking the features that are enabled for the user. Remember that the UserManager class does not persist any information to the database by itself. It provides the needed information to the UserStore class that uses the IdentityDbContext for persisting the information in the database. You use this class in the AccountController class for registering new users in your application.

The ApplicationSignInManager that inherits from the SignInManager class performs the actual signing process of the user in the application. You use this class in your AccountController class for logging users in and out of your application.

Once you added the needed basic components for the authentication, you can now configure the type of authentication that you need for your application. In this example, you used form-based or cookie-based authentication. Remember that one of the parts of the form-based authentication is to provide the authenticated user with a cookie that stores some information that allows the user to access the application without needing to type his or her credentials each time the browser makes a request to the web server. You configure form-based authentication in the OWIN middleware by using the following lines:

	
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the
// user logs in. This is a security feature which is used when you
// change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity
<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) =>
user.GenerateUserIdentityAsync(manager))
}
});
	

As you can see in the code above, you add the cookie authentication to the middleware and configure some essential points for the authentication:

AuthenticationType You use this property for setting the identifier for the authentication type. You use different values of this property for using the same authentication middleware type more than once in the pipeline.

LoginPath If your user tries to access a protected resource, he or she gets a 401 Unauthorized status code. The middleware changes the 401 status code into a 302 redirection to the path provided by this property.

Provider The middleware makes calls to the authentication provider to give the application control when events occur in the pipeline, such as during the sign-in sign-out process. If you don’t provide an instance of

an authentication provider, then Katana provides an empty authentication provider.

Once you have configured the authentication methods for your application, you need to configure the UserManager class. You use this configuration to set the properties for the password length or complexity. You made this configuration in the IdentityConfig.cs file when you define the

IdentityUserManager class. This class implements the method Create, shown in Listing 4-4, which handles the configuration of features for your users and passwords. We intentionally omitted portions of the code in Listing 4-4.

Listing 4-4 Create method from ApplicationUserManager

	
// C#. ASP.NET. IdentityConfig.cs
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUser
Manager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>
(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
return manager;
}
	

Once you have configured the authentication method for your application, you can implement how to create the actual user authentication and registration in the corresponding endpoints defined in the AccountController.cs file.

When you configured the cookie authentication, you set the LoginPath property to the value /Account/Login. Now you can review the Login method shown in Listing 4-5, in the AccountController. You use the PasswordSignInAsync() method for authenticating a user with the with the username and password values provided by the form shown in Listing 4-1.

Listing 4-5 Login method for the Account Controller

	
// C#. ASP.NET. AccountController.cs
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to
// shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.

Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl,
RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
	

As you can see in Listing 4-5, you use the SignInManager for authenticating the user by using the PasswordSignInAsync method and providing the parameters to the method based on the values that you got from the form and that are stored in the LoginViewModel. If you review Listing 41, you can see that you configured the form for sending the information by using the POST method. This means that you need to use the HttpPost attribute for telling the MVC that it should run this method when it receives a request to the /Account/Login route using the POST method. Another interesting attribute that you should consider is the AllowAnonymous attribute. Because you configured the authentication for all requests to your application in the Startup.Auth.cs file, you need to specify manually which routes accept requests without requiring authentication. At this point, the user is not authenticated yet, so you need to allow the user to access this route without requiring authentication. The CaludateAntiForgeryToken is also essential because it provides an additional security level by checking if the requests come from a valid user and preventing a malicious user from copying the authentication cookie from a valid user and reusing it for authentication to your application.

One of the most significant drawbacks of using form-based authentication is the authentication mechanism’s dependency on cookies. Another inconvenience is that this is stateful, which requires that your server keeps an authentication session for tracking the activity between the server and the client. This makes it more difficult to scale solutions using form-based authentication. One additional point to consider is that cookies don’t work well (or it’s challenging to work with them) on mobile apps. Fortunately, there are alternatives to form-based authentication that are more suitable for the requirements that have Mobile or IoT scenarios; also, there are alternatives that can improve the scalability of your web application.

Token-based authentication is the most extended authentication mechanism for environments and scenarios that require high scalability or do not support the usage of cookies. Token-based authentication consists of a signed token that your application uses for authenticating requests and granting access to the resources in your application. The token does not contain the username and password of your user. Instead, the token stores some information about the authenticated user that your server can use for granting access to your application’s resources.

When you use token-based authentication, you follow a workflow similar to the one shown in Figure 4-2:

Figure 4-2 Basic workflow of token-based authentication
Screenshot_31
  1. An unauthenticated user connects to your web application.
  2. Your web application redirects the user to the login page. This login page can be provided by your web application acting as a security server or by an external security server.
  3. The security server validates the information provided by the user— typically, the username and password—and generates a JWT token.
  4. The security server sends the JWT token to the user. The browser or mobile app that the user used to connect to your application is responsible for storing this JWT token for reusing it in the following requests.
  5. The browsers or mobile app provides the JWT token to your web application on each following request.

There are several token implementations, but the most extended one is JSON Web Token or JWT. A JWT token consists of:

Header The header contains the name of the algorithm used for signing the token.

Body or Payload The body or payload contains different information about the token and the purpose of this token. The body contains several standard fields or claims that are defined in the RFC 7519 and any other custom field that you may need for your application.

Cryptographic signature This is a string that validates your token and ensures that the token was not corrupted or incorrectly manipulated.

One of the main advantages of using token-based authentication is that you can delegate the process of managing the identity of the users to external security servers. This means you can abstract from the implementation of managing and storing JWT tokens and usernames and passwords. That is what you do when you want to allow your users to access your application by using their Facebook, Google, or Twitter accounts. Your application trusts the identification and authentication processes made by these external security servers or identity managers, and you grant access to your application based on the information stored in the JWT token provided by the security server. You still need to store some information about the user, but there is no need to know anything about the password or any other information that the user needed to provide to the security server for authentication.

Using the Identity Framework, you can add token-based authentication to your application. As we mentioned before, you can implement your own token-based authentication or use an external authentication provider that performs the verification of the user’s login and password. The following steps show how to enable Google authentication in the web application that you created in the previous example. You can use a similar procedure for enabling another social login to your application, such as Facebook, Twitter, or Microsoft accounts.

  1. In Visual Studio, open the example that we reviewed in Listings 4-1 to 4-5.
  2. On the Solution Explorer window, click on the project’s name and press F4 for opening the Properties tab of the project.
  3. On the Development Server section, change the value of the SSL Enabled setting to be True.
  4. Copy the SSL URL below the SSL Enabled setting and close the Properties window.
  5. In the Solution Explorer, right-click the project’s name and click Properties at the bottom of the contextual menu. This opens your project’s csproj file in a new tab.
  6. On your project’s csproj file tab, select the Web tab and paste the SSL URL in the Project Url text box in the Servers section.
  7. Open the cs file and add the RequireHttps attribute to the HomeController class:
  8. 	
    [RequireHttps]
    public class HomeController : Controller
    {
    public ActionResult Index()
    	
    
  9. Create a Google Project for integrating your web application with Google’s authentication platform. You need a Google account for these steps:
    • Log in to your Google account.
    • Navigate to https://developers.google.com/identity/signin/web/devconsole-project
    • Click Configure A Project.
    • On the Configure A Project For Google Sign-In dialog box, select Create A New Project from the drop-down menu.
    • Enter a name for your project and click Next at the bottom-left corner of the dialog box.
    • On the Configure Your OAuth Client dialog box, type the name of your web application. This name will be shown in the consent window that appears to the user during login.
    • On the Configure Your OAuth Client dialog box, select Web Server in the Where Are You Calling From? drop-down menu.
    • In the Authorized Redirect URIs text box, use the URL SSL that you copied in step 4 and create a redirect URI with this structure:<YOUR_URL_SSL>/signin-google Use the following example for your reference: https://localhost:44397/signin-google
    • Click Create in the bottom-left corner of the dialog box.
    • On the You’re All Set! dialog box, click the Download Client Configuration button. Alternatively, you can copy the Client ID and Client Secret fields. You will use these values later.
    • Click the API Console link at the bottom of the dialog box.
    • On the left side of the Google Console, click Library.
    • In the Search For APIs & Services textbox, type Google+.
    • In the result list, click Google+ API.
    • In the Google+ API window, click the Enable button.
  10. In the App_Start/Startup.Auth.cs file, in the ConfigureAuth method, uncomment the following lines:
  11. 	
    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
    ClientId = "",
    ClientSecret = ""
    });
    	
    
  12. Use the Client ID and Client Secret values that you copied in step 8.j and assign the value to the correspondent variable in the code above. (Note that these items are placed inside quotation marks.)
  13. Press F5 for running the application.
  14. Click Log In in the top-left corner of the web application.
  15. Under the Use Another Service To Log In option on the left side of the page, click the Google button.
  16. Log in using your Google account.
  17. Click the Register button. Once you are logged in with Google, you are redirected to the web application. Because your Google account does not exist on your application’s database, you get a registration form.
  18. Now you are registered and logged in to your application using a Google account.

Once you have logged in to the application using your Google account, you can review the database and look for the new login information. You can see in the AspNetUser table that there is a new entry for your new Google account login, but the PasswordHash field is empty. You can also review the AspNetUserLogins table. This table contains all the logins from external authorization providers, such as Google, that have been registered in your application.

In the same way that you configured the form-based authentication in the Startup.Auth.cs file, you configure the external authentication in the same file. Once you have configured the DbContext, UserManager, and SignInManager for your application, you add the external cookie management middleware, using this line:

	
app.UseExternalSignInCookie(DefaultAuthenticationType
	

You need this for managing the information that comes from the third party’s authentication providers. Finally, you register the authentication provider by providing the client ID and client secrets that allow your application to connect to the external authentication provider and get the token information.

If you run this example and review the headers in the different requests, you can see that the web browser still provides authentication information by using cookies. The token-based authentication on this example comes from the fact that you use an external authorization provider that uses OpenID Connect for authenticating your users. In the following sections, we review how to implement your own fully token-based authentication web API.

When the user is providing the credentials to your web application, you need to consider whether the authentication method that you are using transmits the username and password in plain text over the Internet. This is especially true for form-based authentication or basic authentication. In these situations, you can solve the problem by sending the authentication information through an encrypted SSL channel using digital certificates.

Using SSL certificates, you encrypt the communication channel between the client and server, and while you are authenticating the client, the client is also authenticating the server to which it is connecting. This server authentication is then performed automatically by the browser by checking that a trusted certification authority signs the server certificate, the certificate is not expired, and that the certificate is issued to the same host to which you are connecting.

You can also use SSL certificates for authenticating the clients for your application. Using that kind of authentication, you issue a certificate to your clients. When your client tries to connect to your web application, the web server asks the web browser to send an SSL certificate; then the web application checks whether the user provided a valid certificate and authenticates the connection without needing the user to provide a username and password. This authentication makes the communication between client and server more secure because you are authenticating both ends of the connection. However, it also is more complex to configure and manage in a production environment because you need to deploy a private-key infrastructure (PKI) and distribute the client certificates to the users in a secure way.

Need More Review? Configure TLS Mutual Authentication for Azure App Service

You can learn more about how to enable client certificate authentication by reviewing the Microsoft Docs article “Configure TLS mutual authentication for Azure App Service” at https://docs.microsoft.com/enus/azure/app-service/app-service-web-configure-tls-mutual-auth

Implement multifactor or Windows authentication by using Azure AD

One commonality that you can observe in the examples in the previous section is that all users or identities are stored in a conventional storage system, such as a relational database. If you are developing an application for a company with hundreds or thousands of users, using a distinct storage system for managing the identities of the users who need to access the application may create undesirable administrative overhead. This type of organization usually uses some identity or directory service that centralizes and eases the administration of all users who have some kind of relationship with the company. For Microsoft-based deployment, companies use Microsoft Active Directory Domain Services (AD DS), which provides the authentication and authorization capabilities needed for the company.

With the evolution of the cloud, Microsoft released Azure Active Directory (Azure AD), which provides identity and access management services for managing the access to the different services and resources that Microsoft offers. You should not confuse Active Directory Domain Services, with Azure AD. They both provide identity and access management services, but they are not the same service, they provide different features, and they apply to different scenarios. You can connect an Azure AD tenant with an Active Directory Domain Services domain, but you need to remember that you mainly use Azure AD for cloud-based scenarios, while you typically use AD DS domain for on-premises scenarios.

Windows authentication is the type of authentication that you perform in an on-premises environment where there is an AD DS domain deployed. The NTLM and Kerberos protocols are the protocols that support client authentication in an AD DS domain environment. Neither of these protocols is well suited for the Internet, so you need to use alternative authentication protocols when you need to authorize your users to access your application. You use Windows Authentication or Integrated Windows Authentication when your users are members of an AD DS domain and they are connecting to your application from a computer that is also joined to the same AD DS domain.

There are situations in which your company has both an AD DS domain and an Azure AD tenant. In that kind of scenario, it’s very common to connect your domain and tenant. This means any new user you add to your AD DS domain is automatically added to the Azure AD tenant. This configuration also allows your users to authenticate to your AD DS domain or Azure AD tenant using the same credentials. You can make this connection using two different methods: Azure AD Connect or Active Directory Federation Services (AD FS).

Need More Review? Hybrid Identity with Azure AD

You have several options when you configure the connection between an Azure AD tenant and an AD DS domain. You can review the different options by consulting the article “What is hybrid identity with Azure Active Directory?” at https://docs.microsoft.com/en-us/azure/activedirectory/hybrid/whatis-hybrid-identity

If you are writing a desktop or mobile application that needs to use Azure AD authentication and your desktop or mobile devices are joined to your AD DS domain or Azure AD tenant, you can use the Microsoft Authentication Library for .NET (MSAL.NET). Using this library, you can request an Azure AD token by using Integrated Windows Authentication. The following example shows how to implement Integrated Windows Authentication using MSAL.NET. Before you can run this example, you need to consider the following requirements:

You need to run the example from a computer that is a member of an Azure AD tenant or an AD DS domain. The Azure AD tenant and AD DS domain need to be connected using AD FS.

Your user needs to exist on the AD DS domain. This AD DS and the

Azure AD tenant need to connect using a federation service, such as AD FS. Using managed users—that is, users who only exist on the Azure AD tenant—is not valid for this scenario.

Because your application needs to connect to Azure AD to get the authentication token, you need to register the application in your Azure AD tenant before your application can access your tenant or AD DS domain. The following steps show how to register an application in your Azure AD tenant:

  1. Sign in to the management portal (http://portal.azure.com.
  2. On the left side of the Azure portal, in the list of your favorite resources, click Azure Active Directory.
  3. On the Azure Active Directory blade, click App Registrations.
  4. On the App Registrations blade, click the New Registration button in the top-left corner of the blade.
  5. On the Register An Application blade, type a name for your application.
  6. On the Supported Account Types radio button control, ensure that the Accounts In This Organization Only option is selected. This ensures that authentication is only valid for users in your organization.
  7. Click the Register button at the bottom of the blade.
  8. On your application blade, on the Overview panel, copy the Application (Client) and the Directory (Tenant) IDs.
  9. On your application blade, click the Authentication option in the Manage section.
  10. On the Authentication blade, in Advanced Settings, check the ID Tokens Implicit Grant option.
  11. Set Treat Application As A Public Client setting to Yes.
  12. Click the Save button at the top-left corner of the Authentication blade.
  13. On your application blade, click API Permissions in the Manage section.
  14. On the API Permissions blade, click the Add A Permission button.
  15. On the Request API Permissions panel, click the Microsoft Graph button.
  16. On the What Type Of Permissions Does Your Application Require? section, click Delegated Permissions.

  17. In the Permission list, expand the User node, and select User.ReadBasic.All. You may need to scroll down to find the User node.
  18. Click the Add Permissions button at the bottom of the Request API Permissions panel.
  19. On the API Permissions blade, in the Grant Consent section, click the button Grant Admin Consent For <Your_Tenant’s_Name>.
  20. Click the Yes button on the confirmation dialog.
  21. Clone the source code of this example:
  22. 	
    git clone https://github.com/Azure-Samples/act
    	
    
  23. Open the solution in Visual Studio.
  24. Edit the appsettings.json file and make the following changes:
    • Set the AadAuthrityuAudience to the value AzureAdMyOrg.
    • Inside the Authentication section, add a new key-value pair:
    • key TenantId
    • value insert the tenant ID you copied in step 8
    • Replace the value of the ClientId with the client ID that you copied in step 8.
  25. Edit the Program.cs file and comment the following line:
  26. 	
    .WithAuthority(appConfig.AzureCloudInstance, AadAuthorityAudience.
    AzureAdMultipleOrgs)
    	
    
  27. Run the application.

This console application tries to log in to your Azure AD tenant using the username that runs the application. When you run the application, you should get the information stored in the AD DS domain about your user.

During the login flow, your application needs to contact your AD FS servers. If you try to run this example on a computer that is joined to an Azure AD tenant or that is not a member of an AD DS domain federated with an Azure AD tenant, you will get an error. You should bear in mind that the previous example does not work if you have configured Multifactor Authentication (MFA) for your users in the Azure AD tenant.

Need More Review? Active Directory Federation Services

You can deploy a testing scenario for your experiments using virtual machines. You can review how to configure a federation trust between an AD DS domain and an Azure AD tenant by reviewing the article, {{#}}8220;Azure AD Connect and federation,” at https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-fed-whatis

When you work with MSAL, you need to start by creating a PublicClientApplication object. You use this object for managing the interactions with your Azure AD tenant. When you create this object, you need to provide some information stored in the appsettings.json file. You create this object in the Program.cs file, using the following lines of code:

	
SampleConfiguration config = SampleConfiguration.ReadFromJsonFile("appsettings.json");
var appConfig = config.PublicClientApplicationOptions;
var app = PublicClientApplicationBuilder.CreateWithApplicationOptions(appConfig).
Build();
	

In the previous example, the class PublicAppUsingIntegratedWindowsAuthentication performs the actual authentication with the Azure AD tenant. This class has two main methods:

AcquireATokenFromCacheOrIntegratedWindowsAuthenticationAsy

This method gets information from the currently logged-in user and tries to get any cached token. If there is no cached token, then it calls the GetTokenForWebApiUsingIntegratedWindowsAuthenticationAsync method for acquiring a new token.

GetTokenForWebApiUsingIntegratedWindowsAuthenticationAsync Uses the AcquireTokenByIntegratedWindowsAuth method for getting a token based on the information of the currently logged-in user.

Need More Review? Microsoft Identity Platform Authentication Libraries

The Microsoft identity platform authentication libraries are available for different languages. You can use these libraries for adding authentication features in your applications for different platforms, such as web, Android, iOS, Windows Universal, or desktop applications. You can review the detail of these libraries using the following link https://docs.microsoft.com/en-us/azure/activedirectory/develop/reference-v2-libraries

Using Azure AD as your identity manager service has some advantages over implementing your own identity solution. One of these advantages is the implementation of Multifactor Authentication (MFA). The MFA means that a user needs to provide additional proof of his or her identity before the user can be authenticated. You can configure different verification methods for your user, such as using notifications or verification codes from a mobile app or calling or sending a text message to the user’s phone. Microsoft provides the Microsoft Authenticator mobile app—available for Android, iOS, and Windows Phone platforms—for allowing your users to provide the verification needed.

When you enable the MFA feature that Microsoft offers in your Azure AD tenant, you can delegate the complexity of the MFA authentication to Azure.

Use the following procedure for enabling MFA authentication in your Azure AD tenant:

  1. Open the Azure Portal (https://portal.azure.com).
  2. On the left side of the Azure Portal, click Azure Active Directory.
  3. On the Azure Active Directory blade, click Users in the Manage section.
  4. On the All Users blade, click the Multi-Factor Authentication button. This opens a new window where you can enable the MFA for your users.
  5. On the Multi-Factor Authentication page shown in Figure 4-3, click the check box next to the display name of the user for whom you want to enable the MFA. (Note that Figure 4-3 has been intentionally blurred to protect the anonymity of the users.)
  6. Figure 4-3 Enable multifactor authentication
    Screenshot_32
  7. On the Multi-Factor Authentication page, click the Enable link on the right side of the page.
  8. On the About Enabling Multi-Factor Auth dialog box, click the Enable Multifactor Auth button.

Once you enable the MFA in your Azure AD tenant, your users need to use any of the additional verification methods when they authenticate to your application. Use the following steps for creating an example application that uses Azure AD authentication:

  1. Open your Visual Studio 2017.
  2. Create a new project by clicking File > New > Project.
  3. On the left side of the New Project window, click Installed > Visual C# > Web.
  4. On the New Project window, in the template area, click ASP.NET Core Web Application.
  5. Type a name for your example application and click the OK button.
  6. In the New ASP.NET Core Web Application window, select Web Application (Model-View-Controller).
  7. Click the Change Authentication button.
  8. On the Change Authentication window, select Work or School Accounts.
  9. On the right side of the Change Authentication window, in the first drop-down menu, ensure that the Cloud – Single Organization value is selected. This drop-down menu allows you to configure whether only the users from your organization can log in to this application.
  10. In the Domain drop-down menu, select the domain that you want to use for authenticating your users.
  11. Leave the other options as is and click the OK button.
  12. On the New ASP.NET Core Web Application window, click the OK button.
  13. Press F5 to run your application.

When you run your application, the web browser would present the Azure AD login. Once you provide the credentials for your user and if you configured the MFA for this user in the previous steps, you need to provide the second authentication by using one of the configured validation methods.

Need More Review? Azure AD Conditional Access

You can automatically configure the multifactor authentication for your organization’s users depending on different conditions. For example, you can enable MFA only for certain users and applications. You can extend the information about conditional access in Azure AD by reviewing the following article: https://docs.microsoft.com/en-us/azure/activedirectory/conditional-access/overview

Implement OAuth2 authentication

At the beginning of this chapter, we reviewed how to you can use third-party identity servers for authenticating users in your application, using the OAuth2 protocol. In this section, we are going to review how to create your own OAuth2 server. You usually add this type of authentication when you need these third-party applications to access some services or resources of your code. You can grant access to these applications by creating a token that authenticates the third-party application and grants access to specific parts of your HTTP service.

The OAuth protocol addresses the need to secure access to resources and information in your application by the third party’s process. Without OAuth, if you want to grant access to an external application to the resources of your application, you need to use a username and password. If the third-party application is compromised, then the username and password are also compromised, and your resources are exposed. The OAuth protocol defines four different roles:

Resource owner This is the person or entity that can grant access to the resources. If the resource owner is a person, it can also be referred to as the user.

Resource server This is the server that hosts the resources that you want to share. This server needs to be able to accept and respond to the access codes used for accessing the resource.

Client This is the third-party application that needs to access the resource. The client makes the needed requests to the resource server on behalf of the resource owner. The term “client” does not necessarily imply any specific implementation, like a server, a desktop, or any other kind of device.

Authorization server This is the server that issues the access token to the client for accessing the resources. The client needs to be authenticated before it can get the correct token.

Figure 4-4 shows the basic authentication flow for OAuth.

Figure 4-4 OAuth basic authentication flow
Screenshot_33

As you can see in Figure 4-4, the process of acquiring a token for accessing a protected resource consists of the following steps:

Authentication request The client requests access to the protected resource. The resource owner, based on the privileges of the client, grants access to the client for accessing the resource. The authentication of the client can be directly done by the resource owner or preferably by the authentication server.

Authentication grant When the resource owner grants client access to the resource, the client sends an authentication grant, which is is a code or credential that represents the permission to access the resource, which has been granted by the resource owner. The client uses this authentication grant credential to request an access token to the authorization server. There are four different mechanisms for handling this authentication:

Authorization code The client instructs the resource owner to request authentication to the authentication server. Once the resource owner is authenticated, the authentication server creates an authorization code that the resource owner sends back to the client. The client uses this authorization code as the grant for requesting the access token.

Implicit Using this authentication grant flow, the authentication server does not authenticate the client. Instead, the client gets the access token without needing to authenticate to the resource server using an authentication grant. This implicit flow is a simplified authorization code flow. To improve security in this flow, the resource server uses the redirect URI provided by the client.

Resource owner credentials Instead of using an authorization code or implicit authentication, the client uses the credentials of the resource owner for authenticating against the resource server. This type of authentication grant should be used only when there is a high level of trust between the client and the resource owner.

Client credentials The client provides his or her credentials for accessing the resource. This authentication grant is useful for scenarios in which the client needs access to resources that are protected by the same authorization server as the client and are under the control of the client. This is also useful if the resource server and the client arranged the same authorization for the resources and the client.

Access token The client requests an access token from the authorization server that allows the client to access the resource on the resource server. The client sends this access token to the resource server with each request to access the resource. This access token has an expiration date. Once the access token is expired, the token is invalid, and the client needs to request another access token. To ease the process of renewing the access token, the authentication server provides two different tokens—the actual access token and a refresh token. The client uses the refresh token when it needs to renew an expired access token.

Protected resource This is the resource that the client wants to access. The resource server protects the resource. The client needs to send the access token to the resource server every time it needs to access the resource.

Need More Review? The OAuth 2.0 Authorization Framework

You can get more information about the details of how the OAuth 2.0 Authorization Framework works by reviewing the official RFC 6749 at https://tools.ietf.org/html/rfc6749

The following example shows how to implement OAuth 2.0 authentication in your Web API application. In this example, you are going to create an authorization server, a resource server, and client that can request an access token before accessing the resource. For the sake of readability, we have split the steps for implementing this example into different parts. The following steps show how to create the authorization server:

  1. Open Visual Studio.
  2. Click File > New > Project.
  3. In the New Project window, in the tree control on the left side, click Installed > Visual C# > Web.
  4. Select the ASP.NET Web Application (.NET Framework) template.
  5. Type a Name for your project.
  6. Select the Location where you want to save your project.
  7. Type a name for your Solution.
  8. Click the OK button.
  9. In the New ASP.NET Web Application window, click the MVC template.
  10. Click the Change Authentication button on the right side of the window.
  11. On the Change Authentication window, click the Individual User Accounts option.
  12. On the New ASP.NET Web Application window, click the OK button.
  13. In Visual Studio, open the file at App_Start > Startup.Auth.cs, and add the following line to the beginning of the file:
  14. 	
    using Microsoft.Owin.Security.OAuth;
    	
    
  15. Add the code shown in Listing 4-6 to the Startup.Auth.cs file. You need to add this code to the ConfigureAuth() method, after the line
  16. 	
    app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.
    TwoFactorRememberBrowserCookie);
    	
    
  17. Add also the following using statements to the Startup.Auth.cs file for avoiding compilation errors:
    • using System
    • using Microsoft.AspNet.Identity; using
    • Microsoft.AspNet.Identity.Owin; using
    • Owin; using Microsoft.Owin;
    • using Microsoft.Owin.Security.Cookies; using
    • Microsoft.Owin.Security.OAuth; using
    • Microsoft.Owin.Security.Infrastructure; using
    • AuthorizationServer.Constants; using
    • System.Threading.Tasks; using
    • System.Collections.Concurrent; using
    • System.Security.Claims; using
    • System.Security.Principal; using System.Linq; using <your_project’s_name>.Models;

Listing 4-6 Adding OAuth Authorization Server

	
// C#. ASP.NET.
//Setup the Authorization Server
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
TokenEndpointPath = new PathString (Paths.TokenPath),
ApplicationCanDisplayErrors = true,
#if DEBUG
AllowInsecureHttp = true,
#endif
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
OnGrantClientCredentials = GrantClientCredentials
},
// The authorization code provider is the object in charge of creating and receiving the
// authorization code.
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode,
},
// The refresh token provider is in charge in creating and receiving refresh token.
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
}
});
//Protect the resources on this server.
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
});
	

This code configures the OAuth Authentication Server by using the UseOAuthAuthorization Server() method. This method accepts an OAuthAuthorizationServerOptions object for configuring several useful endpoints:

AuthorizeEndpointPath The authorize endpoint is the path in the authorization server to which the client application redirects the user-agent to obtain the user or resource owner’s consent to access the resource. With this consent, the client application can request an access token.

TokenEndpointPath This is the path in the authorization server that the client uses to obtain an access token. If the client is configured with a client secret, the client needs to provide this client secret on the request for obtaining a new token.

AllowInsecureHttp This setting allows the client to make requests to the authorize and token endpoints by using HTTP URIs instead of HTTPS URIs.

Provider Your authorization server application needs to provide the needed delegated methods for processing the different events that arise during the OAuth authorization flow. You can do this by implementing the OAuthAuthorizationServerProvider interface or using the default implementation provided by the OAuthAuthorizationServerProvider object. In this example, you use the OAuthAuthorizationServerProvider object and provide four delegate functions for the different events. Listings 4-7 to 410 show the different delegate methods that you use for the events managed by this provider.

AuthorizationCodeProvider When the authorization server authenticates the client, the server needs to send an authorization code to the server. This provider manages the events that arise during the management of the authentication code. Listings 4-11 and 4-12 show the delegate methods that manage the events of creating or receiving a code.

RefreshTokenProvider This object controls the events that happen when the client requests a refresh of an access token. Listings 4-13 and 4-14 show the delegate methods that control the events of creating and receiving a request of refreshing an access token.

  1. Add the content from Listings 4-6 to 4-13 to the Startup.Auth.cs file. Add these methods to the Startup class. The implementation for these delegates is not suitable for production environments. For example, the validation of the client redirect URI, and the authentication of the clients are based on a hard-coded value stored in the Client class. In a real-world scenario, you should have these entities stored in a database. In this example, the creation of the access token, shown in Listing 4-9, is stored in an in-memory dictionary. In a real-world scenario, you should save in a database the access tokens that you grant to the clients.
  2. Listing 4-7 OnValidateClientRedirectUri delegate

    	
    // C#. ASP.NET. private Task ValidateClientRedirectUri(OAuthVa
    {
    if (context.ClientId == Clients.Cl
    {
    context.Validated(Clients.Clie
    }
    else if (context.ClientId == Clien
    {
    context.Validated(Clients.Clie
    }
    return Task.FromResult(0);         }
    	
    

    Listing 4-8 OnValidateClientAuthentication delegate

    	
    // C#. ASP.NET.
    private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext
    context)
    {
    string clientId;
    string clientSecret;
    if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
    context.TryGetFormCredentials(out clientId, out clientSecret))
    {
    if (clientId == Clients.Client1.Id && clientSecret == Clients.Client1.
    Secret)
    {
    context.Validated();
    }
    else if (clientId == Clients.Client2.Id && clientSecret == Clients.
    Client2.Secret)
    {
    context.Validated();
    }
    }
    return Task.FromResult(0);
    }
    	
    

    Listing 4-9 OnGrantResourceOwnerCredentials delegate

    	
    // C#. ASP.NET.
    private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext
    context)
    {
    ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(context.
    UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new
    Claim("urn:oauth:scope", x)));
    context.Validated(identity);
    return Task.FromResult(0);
    }
    	
    

    Listing 4-10 OnGrantClientCredentials delegate

    	
    // C#. ASP.NET.
    private Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
    {
    var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId,
    OAuthDefaults.AuthenticationType), context.Scope.Select(x => new
    Claim("urn:oauth:scope", x)));
    context.Validated(identity);
    return Task.FromResult(0);
    }
    	
    

    Listing 4-11 Authorization code for OnCreate delegate

    	
    // C#. ASP.NET.
    private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
    {
    context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().
    ToString("n"));
    _authenticationCodes[context.Token] = context.SerializeTicket();
    }
    Listing 4-12 Authorization code for OnReceive delegate
    Click here to view code image
    // C#. ASP.NET.
    private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
    {
    string value;
    if (_authenticationCodes.TryRemove(context.Token, out value))
    {
    context.DeserializeTicket(value);
    }
    }
    	
    

    Listing 4-12 Authorization code for OnReceive delegate

    	
    // C#. ASP.NET.
    private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
    {
    string value;
    if (_authenticationCodes.TryRemove(context.Token, out value))
    {
    context.DeserializeTicket(value);
    }
    }
    	
    

    Listing 4-13 Refresh token for OnCreate delegate

    	
    // C#. ASP.NET.
    private void CreateRefreshToken(AuthenticationTokenCreateContext context)
    {
    context.SetToken(context.SerializeTicket());
    }
    	
    

    Listing 4-14 Refresh token for OnReceive delegate

    	
    // C#. ASP.NET.
    private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
    {
    context.DeserializeTicket(context.Token);
    }
    	
    
  3. Add the following private property to the Startup class in the Startup.Auth.cs file:
  4. 	
    private readonly ConcurrentDictionary<string, string> _authenticationCodes =
    new ConcurrentDictionary<string, string>
    (StringCompare
    	
    
  5. On the Solution Explorer window, add a new folder to your project called Constants.
  6. In the Constants project, right-click the Constants folder and click Add > New Item.
  7. On the New Item window, on the tree control on the left side of the window, click Installed > Visual C# Code.
  8. Click the template named Class.
  9. At the bottom of the Add New Item window, type Clients.cs in the Name text box.
  10. Click the Add button in the bottom-right corner of the window.
  11. Replace the content of the cs file with the content in Listing 4-15
  12. Change the namespace to match your project’s name.
  13. Listing 4-15 Clients.cs

    	
    // C#. ASP.NET.
    namespace <YOUR_PROJECT'S_NAME>.Constants
    {
    public class Clients
    {
    public readonly static Client Client1 = new Client
    {
    Id = "123456",
    Secret = "abcdef",
    RedirectUrl = Paths.AuthorizeCodeCallBackPath
    };
    public readonly static Client Client2 = new Client
    {
    Id = "78901",
    Secret = "aasdasdef",
    RedirectUrl = Paths.ImplicitGrantCallBackPath
    };
    }
    public class Client
    {
    public string Id { get; set; }
    public string Secret { get; set; }
    public string RedirectUrl { get; set; }
    }
    }
    	
    
  14. On the Solution Explorer window, click your project’s name and press F4.
  15. On your project’s properties window, change the value of SSL Enabled to True.
  16. Copy the value of the SSL URL setting.
  17. Right-click the project’s name and click the Properties menu item at the bottom of the contextual menu.
  18. On the project’s properties tab in Visual Studio, click the Web element on the left side of the window.
  19. In the Servers section, paste the SSL URL value that you copied in step 26 in the Project URL text box.
  20. Add a new empty C# class and name it cs. You can repeat the steps 18–22 to create a new C# class.
  21. Replace the content of the file cs with the code shown in Listing 4-16.
  22. Paste the value of the SSL URL that you copied on step 26 on the following constants:
    • AuthorizationServerBaseAddress
    • ResourceServerBaseAddress
    • ImplicitGrantCallBackPath Ensure that you don’t delete the URI part. This constant should look like <SSL URL>/Home/SignIn. AuthorizeCodeCallBackPath Ensure that you don’t delete the URI part. This constant should look like <SSL URL>/Manage.
  23. Listing 4-16 Paths.cs

    	
    // C#. ASP.NET.
    namespace <YOUR_PROJECT'S_NAME>.Constants
    {
    public class Paths
    {
    public const string AuthorizationServerBaseAddress = "https://localhost:44317";
    public const string ResourceServerBaseAddress = "https://localhost:44317";
    public const string ImplicitGrantCallBackPath = "https://localhost:44317/Home/
    SignIn";
    public const string AuthorizeCodeCallBackPath = "https://localhost:44317/
    Manage";
    public const string AuthorizePath = "/OAuth/Authorize";
    public const string TokenPath = "/OAuth/Token";
    public const string LoginPath = "/Account/Login";
    public const string LogoutPath = "/Account/Logout";
    public const string MePath = "/api/Me";
    }
    }
    	
    

    At this point, you need to create the API Controller that manages the requests to the Authorize and Token endpoint. When you configured the Authentication Server, you used the following code snippet for setting the endpoints that the server uses for attending OAuth requests:

    	
    app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
    {
    AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
    TokenEndpointPath = new PathString(Pa
    	
    

    If you review the value of the parameters AuthorizePath and TokenPath in your Paths class, you can see that their values are /OAuth/Authorize and /OAuth/Token, respectively. Now, you need to create the controller that manages the requests to these endpoints.

  24. On the Solution Explorer window, right-click the Controllers folders in your project, and then choose Add > Controller.
  25. On the Add Scaffold window, choose MVC 5 Controller – Empty.
  26. Click the Add button.
  27. On the Add Controller window, type OAuthController.
  28. Open the cs file and replace the content of the file with the code shown in Listing 4-17:
  29. Listing 4-17 Startup.WebApi.cs

    	
    // C#. ASP.NET.
    using System.Security.Claims;
    using System.Web;
    using System.Web.Mvc;
    namespace <your_project's_name>.Controllers
    {
    public class OAuthController : Controller
    {
    // GET: OAuth/Authorize
    public ActionResult Authorize()
    {
    if (Response.StatusCode != 200)
    {
    return View("AuthorizeError");
    }
    var authentication = HttpContext.GetOwinContext().Authentication;
    var ticket = authentication.AuthenticateAsync("ApplicationCookie").Result;
    var identity = ticket != null ? ticket.Identity : null;
    if (identity == null)
    {
    authentication.Challenge("ApplicationCookie");
    return new HttpUnauthorizedResult();
    }
    var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
    if (Request.HttpMethod == "POST")
    {
    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Grant")))
    {
    identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.
    NameClaimType, identity.RoleClaimType);
    foreach (var scope in scopes)
    {
    identity.AddClaim(new Claim("urn:oauth:scope", scope));
    }
    authentication.SignIn(identity);
    }
    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Login")))
    {
    authentication.SignOut("ApplicationCookie");
    authentication.Challenge("ApplicationCookie");
    return new HttpUnauthorizedResult();
    }
    }
    return View();
    }
    }
    }
    	
    
  30. Right-click Views > OAuth, and then select Add > View.
  31. On the Add View window, on the View Name field, type Authorize.
  32. Click OK.
  33. Replace the content of the file Authorize.cshtml with the code shown in Listing 4-18:
  34. Listing 4-18 Authorize.cshtml

    	
    // C#. ASP.NET.
    @{
    ViewBag.Title = "Authorize";
    }
    @using System.Security.Claims
    @using System.Web
    @{
    var authentication = Context.GetOwinContext().Authentication;
    var ticket = authentication.AuthenticateAsync("ApplicationCookie").Result;
    var identity = ticket != null ? ticket.Identity : null;
    var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
    }
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>@ViewBag.Title</title>
    </head>
    <body>
    <h1>Authorization Server</h1>
    <h2>OAuth2 Authorize</h2>
    <form method="POST">
    <p>Hello, @identity.Name</p>
    <p>A third party application wants to do the following on your behalf:</p>
    <ul>
    @foreach (var scope in scopes)
    {
    <li>@scope</li>
    }
    </ul>
    <p>
    <input type="submit" name="submit.Grant" value="Grant" />
    <input type="submit" name="submit.Login" value="Sign in as different user" />
    
    </p>
    </form>
    </body>
    </html>
    	
    
  35. Add another empty view named AuthorizeError.
  36. Replace the content of the file AuthorizeError.cshtml with the code shown in Listing 4-19:
  37. Listing 4-19 AuthorizeError.cshtml

    	
    // C#. ASP.NET.
    @{
    ViewBag.Title = "AuthorizeError";
    }
    @using System
    @using System.Security.Claims
    @using System.Web
    @using Microsoft.Owin
    @{
    IOwinContext owinContext = Context.GetOwinContext();
    var error = owinContext.Get<string>("oauth.Error");
    var errorDescription = owinContext.Get<string>("oauth.ErrorDescription");
    var errorUri = owinContext.Get<string>("oauth.ErrorUri");
    }
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>@ViewBag.Title</title>
    </head>
    <body>
    <h1>Katana.Sandbox.WebServer</h1>
    <h2>OAuth2 Authorize Error</h2>
    <p>Error: @error</p>
    <p>@errorDescription</p>
    </body>
    
    </html>
    	
    

In this example, we only provide an implementation for the Authorize endpoint for the sake of simplicity. An authorized user in your application needs to grant access to the resources in your application explicitly. When the user grants those privileges, the application automatically creates an inmemory OAuth token that you can use to make a request to the protected resources. In a real-world scenario, this process should be separated in the two different endpoints—Authorize and Token. You should use the Token endpoint for creating or refreshing the access token issued by the authorization server.

Now that you have created and configure your authorization server, you can create the resource server. In this example, you are going to create the resource server on the same application where you implemented the authorization server. In a real-world scenario, you can use the same application, or you can use a different application deployed by a different server or Azure App Service.

  1. On the Solution Explorer window, right-click the Controllers folder in your project and click Add > Controller.
  2. On the Add Scaffold window, select the Web API 2 Controller – Empty template.
  3. Click the Add button.
  4. On the Add Controller window, type MeController and click the Add button.
  5. Replace the content of the cs file with the code shown in Listing 4-20. This controller is quite simple and only returns the information stored in the token that you provide to the resource server when you try to access the resource.
  6. Listing 4-20 MeController.cs

    	
    // C#. ASP.NET.
    using System.Collections.Generic;
    using System.Linq;
    
    using System.Security.Claims;
    using System.Web.Http;
    namespace <your_project's_name>.Controllers
    {
    [Authorize]
    public class MeController : ApiController
    {
    // GET api/<controller>
    public IEnumerable<object> Get()
    {
    var identity = User.Identity as ClaimsIdentity;
    return identity.Claims.Select(c => new
    {
    Type = c.Type,
    Value = c.Value
    });
    }
    }
    }
    	
    
  7. On the Solution Explorer window, in the App_Start folder, rename the file cs to Startup.WebApi.cs.
  8. In the Visual Studio window, click Tools > NuGet Package Manager > Manage NuGet Packages For Solution.
  9. On the NuGet Package Manager tab, click Browse.
  10. Type Microsoft asp.net web api 2.2 owin and press Enter.
  11. Click the AspNet.WebApi.Owin package.
  12. On the right side of the NuGet Manager tab, click the checkbox beside your project.
  13. Click the Install button.
  14. On the Preview Changes window, click OK.
  15. On the License Acceptance, click the I Accept button.
  16. Open the WebApi.cs file and change the content of the file with the content shown in Listing 4-21:
  17. Listing 4-21 Startup.WebApi.cs

    	
    // C#. ASP.NET.
    using Microsoft.Owin.Security.OAuth;
    using Owin;
    using System.Web.Http;
    namespace <your_project's_name>
    {
    public partial class Startup
    {
    public void ConfigureWebApi(IAppBuilder app)
    {
    var config = new HttpConfiguration();
    // Web API configuration and services
    // Configure Web API to use only bearer token authentication.
    config.SuppressDefaultHostAuthentication();
    config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.
    AuthenticationType));
    // Web API routes
    config.MapHttpAttributeRoutes();
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    app.UseWebApi(config);
    }
    }
    }
    	
    
  18. Open the Startup.cs file and add the following line at the end of the Configuration() method:
  19. 	ConfigureWebApi(app);
    

Once you have implemented the resource server in your application, you should be able to make requests to the authorization server to get access to the resource published by the resource server. As you saw in the OAuth workflow, you need to get authenticated by the authorization server before you can get an access token. This means that you need to be logged in to the application before being able to make any requests to the /OAuth/Authorize endpoint.

Now you can create your client application that makes requests to the authorization server and resource server. That client application can be the same application that you used for implementing the authorization and resource servers. We are going to modify the default MVC template for making requests to the Authorization and Resource servers.

  1. In the Visual Studio window, click Tools > NuGet Package Manager > Manage NuGet Packages For Solution.
  2. In the NuGet Package Manager tab, click Browse.
  3. Type OAuth2.Client and press enter.
  4. Click the OAuth2.Client package. This NuGet package eases the interaction with OAuth servers.
  5. On the right side of the NuGet Manager tab, click the checkbox beside your project.
  6. Click the Install button.
  7. On the Preview Changes window, click OK.
  8. Open the cs file.
  9. Add the following using statements to the cs file:
  10. using System; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin.Security; using AuthorizationServer.Models; using AuthorizationServer.Constants; using DotNetOpenAuth.OAuth2; using System.Net.Http;

  11. Replace the Index() method with the code shown in Listing 4-22:
  12. Listing 4-22 Index method in ManageController.cs

    	
    // C#. ASP.NET.
    public async Task<ActionResult> Index(ManageMessageId? message)
    {
    ViewBag.StatusMessage =
    message == ManageMessageId.ChangePasswordSuccess ? "Your password has
    been changed."
    : message == ManageMessageId.SetPasswordSuccess ? "Your password has
    been set."
    : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor
    authentication provider has been set."
    : message == ManageMessageId.Error ? "An error has occurred."
    : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was
    added."
    : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was
    removed."
    : "";
    var userId = User.Identity.GetUserId();
    var model = new IndexViewModel
    {
    HasPassword = HasPassword(),
    PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
    TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
    Logins = await UserManager.GetLoginsAsync(userId),
    BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRemember
    edAsync(userId)
    };
    ViewBag.AccessToken = Request.Form["AccessToken"] ?? "";
    ViewBag.RefreshToken = Request.Form["RefreshToken"] ?? "";
    ViewBag.Action = "";
    ViewBag.ApiResponse = "";
    InitializeWebServerClient();
    var accessToken = Request.Form["AccessToken"];
    if (string.IsNullOrEmpty(accessToken))
    {
    var authorizationState = _webServerClient.ProcessUserAuthorization(Request);
    if (authorizationState != null)
    {
    ViewBag.AccessToken = authorizationState.AccessToken;
    ViewBag.RefreshToken = authorizationState.RefreshToken;
    ViewBag.Action = Request.Path;
    }
    }
    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Authorize")))
    {
    var userAuthorization = _webServerClient.PrepareRequestUserAuthorization
    (new[] { "bio", "notes" });
    userAuthorization.Send(HttpContext);
    Response.End();
    }
    else if (!string.IsNullOrEmpty(Request.Form.Get("submit.Refresh")))
    {
    var state = new AuthorizationState
    {
    AccessToken = Request.Form["AccessToken"],
    RefreshToken = Request.Form["RefreshToken"]
    };
    if (_webServerClient.RefreshAuthorization(state))
    {
    ViewBag.AccessToken = state.AccessToken;
    ViewBag.RefreshToken = state.RefreshToken;
    }
    }
    else if (!string.IsNullOrEmpty(Request.Form.Get("submit.CallApi")))
    {
    var resourceServerUri = new Uri(Paths.ResourceServerBaseAddress);
    var client = new HttpClient(_webServerClient.CreateAuthorizingHandler
    (accessToken));
    var body = client.GetStringAsync(new Uri(resourceServerUri, Paths.
    MePath)).Result;
    ViewBag.ApiResponse = body;
    }
    return View(model);
    }
    	
    
  13. Add the following property to the ManageController class:
  14. 	
    private WebServerClient _webServerClient;
    	
    
  15. Add the following helper method to the ManageController class:
  16. 	
    private void InitializeWebServerClient()
    {
    var authorizationServerUri = new Uri(Paths.AuthorizationServerBaseAddress);
    var authorizationServer = new AuthorizationServerDescription
    {
    AuthorizationEndpoint = new Uri(authorizationServerUri, Paths.
    
    AuthorizePath),
    TokenEndpoint = new Uri(authorizationServerUri, Paths.TokenPath)
    };
    _webServerClient = new WebServerClient(authorizationServer, Clients.Client1.
    Id, Clients.Client1.Secret);
    }
    	
    
  17. On the Application_Start() method in the Global.asax.cs file, add the following line:
  18. 	AntiForgeryConfig.SuppressXFrameOptionsHeader = t
    
  19. Add the following using statement to the Global.asax.cs file:
  20. 	
    using System.Web.Helpers;
    	
    
  21. In the Solution Explorer window, click Views > Manage > Index.cshtml.
  22. Add the code shown in Listing 4-23 after the section Two-Factor Authentication in the Index.cshtml file.
  23. Listing 4-23 Authorization Code Grant section

    	
    // C#. ASP.NET.
    <dt>Authorization Code Grant Client:</dt>
    <dd>
    <form id="form1" action="@ViewBag.Action" method="POST">
    <div>
    Access Token<br />
    <input id="AccessToken" name="AccessToken" width="604" type="text"
    value="@ViewBag.AccessToken" />
    <input id="Authorize" name="submit.Authorize" value="Authorize"
    type="submit" />
    <br />
    <br />
    Refresh Token<br />
    
    <input id="RefreshToken" name="RefreshToken" width="604" type="text"
    value="@ViewBag.RefreshToken" />
    <input id="Refresh" name="submit.Refresh" value="Refresh"
    type="submit" />
    <br />
    <br />
    <input id="CallApi" name="submit.CallApi" value="Access Protected
    Resource API" type="submit" />
    </div>
    <div>
    @ViewBag.ApiResponse
    </div>
    </form>
    </dd>
    	
    

At this point, your example application is ready for testing the implementation of the different actors that take part in the OAuth workflow. The following steps show how to test your OAuth implementation to ensure that it works correctly:

  1. Open the example project in Visual Studio and press F5 to run the project.
  2. Open the web application in a web browser and click the Register link located on the top-left corner of the page.
  3. On the Register page, add an email address and password and confirm the password. Then click the Register button. You are going to use this user to grant privileges to OAuth client for making requests to the /OAuth/Me
  4. Once you have registered the new user, you are automatically logged on and redirected to the Home page.
  5. On the Home page, click your user’s email link at the top-left corner of the Home page.
  6. On the Manage page, click the Authorize button, which redirects you to the Authorization Server page.
  7. On the Authorization Server page, review the information provided and click the Grant button. After you grant access to the OAuth client application, you get the access and refresh token shown in Figure 4-5, which is needed to make requests to the resource server.
  8. Figure 4-5 OAuth Access and Refresh Token
    Screenshot_34
  9. Click the Access Protected Resource API to make a request to the /OAuth/Me endpoint. You should get all information stored in the identity claim that you use for making this request, including the scopes bio and notes.

Need More Review? Oauth Authorization Server

In this example, you review how to implement the authorization and resource server, the client and the resource owner on the same web application. Although this is a valid scenario, you usually would find that these roles are implemented on a separate application. The code we reviewed is based on the example explained in the Microsoft Docs article at https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-andkatana/owin-oauth-20-authorization-server. In that article, you can review how to implement each role in separate applications.

Implement Managed Service Identity (MSI)/Service Principal authentication

When you are designing your application, you usually identify the different

services or systems on which your application depends. For example, your application may need to connect to an Azure SQL Database for storing data or may need to connect to Azure Event Hub for reading messages from other services. In all these situations, there is a common need to authenticate with the service before you can access it. In the Azure SQL Database case, you need to use a connection string; if you need to connect to an Azure Event Hub, you need to use a combination of event publishers and Shared Access Signature (SAS) tokens.

The drawback with this approach is that you need to store a security credential, token, or password to be able to authenticate to the service that you want to access. This is a drawback because you might find that this information is stored on developers’ computers or is checked in to the source control by mistake. You can address most of these situations by using the Azure Key Vault, but your code still needs to authenticate to Azure Key Vault to get the information for accessing the other services.

Fortunately, Azure Active Directory (Azure AD) provides the Managed Identities for Azure resources (formerly known as Managed Service Identity) that removes the need of using credentials for authenticating your application to any Azure service that supports Azure AD authentication. This feature automatically creates a managed identity that you can use for authenticating to any service that supports Azure AD authentication, without needing to provide any credential.

When you work with Managed Identities, you can work with two different types:

System-assigned managed identities These are identities that Azure automatically enables when you create an Azure service instance, like an Azure Virtual Machine or an Azure Data Lake Store. Azure creates an identity associated with the new instance and stores it to the Azure AD tenant associated with the subscription where you created the service instance. If you decide to delete the service instance, then Azure automatically deletes the managed instance associated with the service instance stored in the Azure AD tenant.

User-assigned managed identities You can create your managed identities in the Azure AD tenant associated with your Azure subscription. You can associate this type of managed identity to one or more service instances. The lifecycle of the managed identity is independent of the service instance. This means that if you delete the service instance, the user-assigned managed identity remains in the

Azure AD tenant. You need to remove the managed identity manually.

Usually, you use the system-assigned managed identities when your workload is contained within the same Azure resource or you need to independently identify each of the service instances, like Virtual Machines. On the other hand, if you need to grant access to a workload that is distributed across different resources or you need to pre-authorize a resource as part of a provisioning flow, you should use user-assigned managed identities.

When you work with Managed Identities, you need to bear in mind three concepts:

Client ID This is a unique identifier generated by Azure AD. This ID associates the application and the service principal during its initial provisioning.

Principal ID This is the ID of the service principal associated with the managed identity. A service principal and a managed identity are tightly coupled, but they are different objects. The service principal is the object that you use to grant role-based access to an Azure resource.

Azure Instance Metadata Service (IMDS) When you use Managed

Identities in an Azure VM, you can use the IMDS for requesting OAuth

Access Token from your application deployed within the VM. The IMDS is a REST endpoint that you can access from your VM using a non-routable IP address (169.254.169.254).

The following example shows how to create a system-assigned identity in an Azure App Service and how to use this managed identity from your code for accessing an Azure Key Vault. For this example, you need to have an empty Azure App Service, an Azure Key Vault, and at least one item on the Azure Key Vault. You also need to have your Visual Studio connected to the Azure Subscription where you have configured the Azure Key Vault.

  1. Open the Azure portal at https://portal.azure.com.
  2. In the search text box on top of the Azure portal, type the name of your Azure Web App. If you don’t have an Azure Web App, you can create a new Azure Web App by using the procedure at https://docs.microsoft.com/en-in/azure/app-service/app-service-webget-started-dotnet
  3. On the Azure Web App Service blade, click the Identity menu item in the Settings section.
  4. On the Status switch control, click the On option.
  5. Click the Save button.
  6. In the Enable System Assigned Managed Identity dialog box, click the Yes button.
  7. Once you enable the system-assigned managed identity, you get the Principal or Object ID, as shown in Figure 4-6.
  8. Figure 4-6 System assigned managed identity
    Screenshot_35
  9. In the Visual Studio window, click New > Project.
  10. In the New Project window, in the tree control on the left side of the window, click Installed > Visual C# > Cloud.
  11. Select the ASP.NET Web Application (.NET Framework) template.
  12. At the bottom of the New Project window, type a Name and a Solution Name for the project.
  13. Select the Location where you want to save your code.
  14. Click the OK button at the bottom-left corner of the window.
  15. In the New ASP.NET Web Application, select the MVC template.
  16. Click the OK button.
  17. In the Visual Studio window, click Tools > NuGet Package Manager > Manage NuGet Packages For Solution.
  18. In the NuGet Package Manager tab, click Browse.
  19. Type Azure.Services.AppAuthentication and press Enter.
  20. Click the Azure.Services.AppAuthentication package.
  21. At the right side of the NuGet Manager tab, click on the checkbox beside your project.
  22. Click the Install button.
  23. In the Preview Changes window, click OK.
  24. On the License Acceptance page, click the I Accept button.
  25. Repeat steps 11 to 23 and install the Azure.KeyVault package.
  26. Open the Controllers > cs file.
  27. Add the following statements to the cs file:
    • using Microsoft.Azure.KeyVault;
    • using Microsoft.Azure.Services.AppAuthentication;
  28. Replace the content of the Index() method with the content of Listing 4-24. The important pieces of code related to accessing the Azure Key Vault are highlighted in bold.

Listing 4-24 Getting a secret from the key vault

	
// C#. ASP.NET.
string keyVaultName = "<PUT_YOUR_KEY_VAULT_NAME_HERE>";
string secretName = "<PUT_YOUR_SECRET_NAME_HERE>";
//Get a token for accessing the Key Vault.
var azureServiceTokenProvider = new AzureServiceTokenProvider();
//Create a Key Vault client for accessing the items in the vault.
var keyVault = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(
TokenProvider.KeyVaultTokenCallback));
var secret = Task.Run(async () => await keyVault.GetSecretAsync($"https://
{keyVaultName}.vault.azure.net/secrets/{secretName}")).GetAwaiter().GetResult();
ViewBag.KeyVaultName = keyVaultName;
ViewBag.keyName = secretName;
ViewBag.secret = secret.Value;
return View();
	

Before you can access the Azure Key Vault, you need to get an OAuth token by using the AzureServiceTokenProvider class. Then you can create your Azure Key Vault client and get any item stored in the vault. When you create the Azure Key Vault client, make sure you provide the KeyVaultTokenCallback. Even if you get a valid access token, you still need to grant access to your Azure App Service application in the Azure Key Vault.

  • Open the Views > Home > Index.cshtml file.
  • Append the content of Listing 4-25 to the end of the file.
  • Listing 4-25 Adding secret information to the home page

    	
    // C#. ASP.NET.
    <div class="row">
    <div class="col-lg-12">
    <dl class="dl-horizontal">
    
    <dt>Key Vault Name: </dt>
    <dd>@ViewBag.keyVaultName</dd>
    <dt>Key Name: </dt>
    <dd>@ViewBag.keyName</dd>
    <dt>Key Secret: </dt>
    <dd>@ViewBag.secret</dd>
    </dl>
    </div>
    </div>
    	
    

    At this point, you could run your project and see the results. Depending on the access policies defined in your Azure Key Vault, your Azure user may already have access to the secrets stored in the key vault. In that case, you should be able to access the secret stored in the Azure Key Vault. If you get an exception when running the web application, there are good chances that you don’t have access to the Azure Key Vault. The following steps show how to grant access to your Azure App Service application in the Azure Key Vault.

    1. Open the Azure Portal.
    2. Type the name of your Azure Key Vault in the search text box at the top of the Azure Portal. If you don’t already have an Azure Key Vault and need to create a new one, you can use the procedure at https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal
    3. On your Azure Key Vault blade, click Access Policies in the Settings section.
    4. On the Access Policies blade, click Add New.
    5. On the Add Access Policy page, select Secret Management in the Configure From Template drop-down menu.
    6. Click the Select Principal control.
    7. In the Principal panel, type the name of your Azure App Service in the Select text box. Your Azure App Service should appear on the list below the text box.
    8. Click your App Service name in the list below the Select text box.
    9. Click the Select button at the bottom of the panel.
    10. Click the OK button at the bottom of the Add Access Policy blade.
    11. Click the Save button at the top of the Access Policies blade.
    12. In the Visual Studio window, right click your project’s name in the Solution Explorer window.
    13. In the contextual menu, click Publish.
    14. In the Pick A Publish Target window, ensure that App Service is selected on the left side of the window.
    15. In the Azure App Service section, click Select Existing.
    16. Click the Publish button at the bottom-right corner of the window.
    17. In the App Service window, in the tree view at the bottom of the window, look for your App Service and click it.
    18. Click the OK button.

    At this point, Visual Studio starts publishing your web application to the selected Azure App Service. When the publishing operation finishes, you should be able to see your web application showing the content of the secret stored in your Key Vault.

    You can configure two different types of Managed Identities: System and User assigned. System-assigned Managed Identities are tied to the service instance. If you delete the service instance, the system-assigned managed identity is automatically deleted as well. You can assign the same Userassigned Managed Identities to several service instances.

    Skill 4.2: Implement access control

    Authentication is only the first step in the process of securing access to the resources managed by your application. Once you successfully authenticate the user for accessing your application, you need to grant access to the different areas of your application. Not all users need to access the same kind of information. You can grant access to your resources based on the actions that a user needs to do in your application. Or you could grant user access to your application based on information the user provides when he or she tries to access some information.

    Granting access based on the group of actions that a user needs to do in your application is knowns as Role-Based Access Control. If you control the access to your application based on the information that the user provides, then you are performing Claims-Based Access Control.

    This skill covers how to:

    • Implement CBAC (Claims-Based Access Control) authorization
    • Implement RBAC (Role-Based Access Control) authorization
    • Create shared access signatures

    Implement CBAC (Claims-Based Access Control) authorization

    When you need to control the access to your application, one of the mechanisms that you can use to make the distinction between users who can access a resource, those who can’t is CBAC (Claims-Based Access Control) authorization. Those who cannot access are referred to as claims. When we talk about claims, you should think about a property associated with the user. Once the user has been authenticated, the object that represents the user in your application can have attached some attributes, such as email address, birthdate, department membership, or nearly any other attribute. In general terms, a claim represents a fact about the authenticated identity. An authenticated identity can be a real user or an application.

    Using claims-based access control means that you use one or more of these attributes—represented as a key/value pair—for restricting or granting access to the resources managed by your application. For example, you could grant access to users that are of legal age by using the birthdate claim, or you could use the department membership claim for granting access to the contract documents stored in your application only to the members of the legal department. You can also create complex access control rules by using several claims in the access control.

    When you work with claims, you are very dependent on the identity management service that you use for providing authentication. If you relay the authentication to external identity management services, such as Azure AD, Google, or Facebook, you are limited to the claims that those providers add to the access token. A solution for that limitation could be adding your claims to the identity once the users have been authenticated. In that case, you need to extend the identity model to store the values of your application’s claims and add those claims programmatically to the identity when the user is authenticated. On the other hand, if you decide to implement your authorization server, you have the flexibility of adding the claims that your application needs to work.

    In both cases, you need to follow the same pattern for implementing claims-based access control. You can control the access to your application at the controller or actions within the controller level. You use the

    AuthorizeAttribute applied to the correct level. Before you can work with the claims in your controllers, you need to define a policy in your code. Using that policy, you define the conditions that the identity should meet. For example, you can define a policy for ensuring that the EmployeeID claim is present in the user’s identity, or you can check whether the user is of legal age by checking the birthdate claim. The following example shows how to check the claims for a user and make claims-based access control. For the sake of simplicity, you are going to use Azure AD authentication in this example.

    1. Open Visual Studio 2017.
    2. Click File > New > Project.
    3. On the New Project window, in the tree control on the left side of the window, click Installed > Visual C# > Cloud.
    4. Select the ASP.NET Core Web Application template.
    5. Type a Name for your project.
    6. Select the Location where your project will be stored.
    7. Click the OK button.
    8. In the New ASP.NET Core Web Application window, select the Web Application (Model-View-Controller) template.
    9. Click the Change Authentication button.
    10. On the Change Authentication window, select the Work or School Accounts option on the left side of the window.
    11. On the right side of the window, select Cloud – Single Organization from the first drop-down menu.
    12. In the Domain drop-down menu, select your Azure AD tenant’s domain.
    13. In the Directory Access Permissions, check the Read Directory Data option. Your window should look similar to Figure 4-7.
    14. Figure 4-7 Configuring Authentication
      Screenshot_36
    15. Click the OK button.
    16. In the New ASP.NET Core Web Application window, click the OK button.
    17. Open the cs file.
    18. Add the following code snippet after the line that starts with
    19. 	
      .AddAzureAD:
      services.AddAuthorization(options =>
      {
      options.AddPolicy("RequireMFA", policy => policy.
      RequireClaim("http://schemas.microsoft.com/claims/
      authnmethodsreferences", "mfa"));
      });
      	
      

      The previous code snippet creates a policy named RequireMFA. You use this policy to control the access to resources in your application. When you define the policy, you use the RequireClaim() method for setting which claims you require to be present in a user’s identity to access your resources. In this example, you only allow access to the protected resources to users who have enabled the Multifactor Authentication feature.

    20. In the Solution Explorer window, right-click the Controllers folder. In the contextual menu, click Add > Controller.
    21. In the Add Scaffold window, select the MVC Controller – Empty template.
    22. Click the Add button.
    23. In the Add Empty MVC Controller, type SecureController.
    24. In the Solution Explorer window, right click on the Views folder. In the contextual menu, click Add > New Folder.
    25. Type Secure as the new folder’s name.
    26. In the Solution Explorer window, right-click the Secure folder. In the contextual menu, click Add > View.
    27. In the Add MVC View window, type Index in the View Name textbox.
    28. Click the Add button.
    29. Open the cshtml file in the Views > Secure folder.
    30. Replace the content of the cshtml file with the following code:
    31. 	
      @{
      ViewData["Title"] = "Secure access";
      }
      <h1>Your user has MFA enabled</h1>
      	
      
    32. Open the Views > Home > Index.cshtml file.
    33. Replace the content of the file with the code shown in Listing 4-26:
    34. Listing 4-26 Showing claims in the home page

      	
      // C#. ASP.NET.
      @using System.Security.Claims;
      @{
      ViewData["Title"] = "Home Page";
      }
      <div class="text-center">
      <h1 class="display-4">Welcome</h1>
      <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps
      with ASP.NET Core</a>.</p>
      <p>Access <a asp-action="Index" asp-controller="Secure">secure</a> content</p>
      </div>
      <div>
      <table class="table-hover claim-table">
      <tr>
      <th>Claim Type</th>
      <th>Claim Value</th>
      </tr>
      <tbody>
      @foreach (Claim claim in User.Claims)
      {
      <tr>
      <td>@claim.Type</td>
      <td>@claim.Value</td>
      </tr>
      
      }
      </tbody>
      </table>
      </div>
      	
      

    At this point, if you run your application and you log in using any user account existing in the tenant that you configured on step 12, your home page should show you the list of the claims provided by Azure AD attached to the logged-in user’s identity. If you click the Secure link on top of the list of claims, you should be able to see the secured page with the message Your user has MFA enabled. You can see this page using any Azure AD user because you didn’t protect the access to this resource yet. The following steps show how to protect the access to these resources by only allowing users who have the MFA feature enabled to access them.

    1. Open the cs file.
    2. Add the following class attribute to the class. You should put this code snippet before the declaration of the class:
    3. 	
      [Authorize(Policy = "RequireMFA")]
      	
      
    4. Run your code again and log in to the application using a user who does not have the MFA feature enabled. When you try to access the Secure page, you get an AccessDenied If you use a user with the MFA feature enabled, you should be able to access the Secure page and see the Your user has MFA enabled message.

    Note: Access error

    In this example, when you get the AccessDenied error, you actually get a NotFound HTTP ERROR 404. The reason for this is that you didn’t implement the error control and your code is redirecting you to the route that should show the AccessDenied error. For the sake of brevity, we decided not to implement that error control. In a real-world application, you should implement the appropriate error control.

    Need More Review? Claims-Based Authorization In Asp.Net Core

    You can find more information about how to create more complex policies for protecting your resources by reviewing the following articles:

    Claims-based authorization in ASP.NET Core:

    https://docs.microsoft.com/enus/aspnet/core/security/authorization/claims

    Policy-based authorization in ASP.NET Core: https://docs.microsoft.com/enus/aspnet/core/security/authorization/policies

    Implement RBAC (Role-Based Access Control) authorization

    In the previous section, we reviewed how to control the access to your application based on properties of the user, such as birthdate or if the user has Multifactor Authentication enabled. In this section, we are going to review how to control the access to your application based on the actions that your user is allowed to do in your application. For example, a user could have permission to delete data from your application. Another user could update data related to prices in an online shopping application. Or another user could perform all possible actions in the web application. You can also group the available actions in your application into groups of actions, or roles.

    A role represents the group actions or permissions that your users have for doing things in your application. For example, a user with the Administrator role would have full access to all areas in your application. In the online shopping application, the administrator could create new products, add a new currency, or configure a new payment gateway. Using the same online shopping application, a user with the Contributor role could add, update, or remove products but not configure currencies or payment gateways.

    When you are developing your web application, you can implement RoleBased Access Control by defining which roles are meaningful for your application and adding the needed constraints to your code. Azure Active Directory allows you to define your custom roles in the manifest of your application registered in the Azure AD tenant. Once you have defined your roles, you can use these roles in your code for making the appropriate access control. The following example shows how to define and implement a RoleBased Access Control (RBAC) using Azure AD app roles. These roles are sent to your application as role claims inserted in your user’s identity.

    1. Open a command-line window.
    2. Change your working directory to the path where you want to save the project. For example:
    3. 	
      cd c:az2013_examples
      	
      
    4. Clone the repository with the source code for this example:
    5. 	
      git clone https://github.com/Azure-Samples/microsoft-identity-platform-aspnetcorewebapp-tutorial.git
      	
      
    6. Open Visual Studio 2017.
    7. Open the solution in the 5-WebApp-AuthZ5-1-Roles folder, which is located in the folder where you cloned the project.Once you have the code of the example, you need to register an application in your Azure AD Tenant before you can authenticate users in the application:
    8. Open the Azure Portal (https://portal.azure.com).
    9. On the left side of the portal, click the Azure Active Directory item.
    10. On the Azure Active Directory blade, in the Manage section, click App Registrations.
    11. In the App Registrations blade, click the New Registration button.
    12. In the Register An Application blade, type a name for your application.
    13. In the Supported Account Types radio button control, ensure that the selected option is Accounts In this Organizational Directory Only.
    14. Click the Register button at the bottom of the blade.
    15. In your registered application’s blade, copy the Application (Client) ID and Directory (Tenant) ID values from the Overview panel. You need these values later, so be sure to copy them.
    16. In the Manage section, shown in Figure 4-8, click Manifest.
    17. Figure 4-8 Manage section in a registered application
      Screenshot_37
    18. In the Manifest panel, change the value of the setting groupMembershipClaims to SecurityGroup. This setting should look like the following code snippet:
    19. 	
      "groupMembershipClaims": "SecurityGroup",
      	
      
    20. In the next step, you are going to add the roles that your application needs for performing the Role-Based Access Control. You need to provide a valid GUID for each application role that you add to your application’s manifest. You can generate new GUIDs using the NewGuid PowerShell cmdlet, the uuidgen command for Linux and MacOSX or any of the existing online GUID generators.
    21. When you define new application roles, you need to ensure that the Value property matches exactly with the role name that you configure in your application.
    22. In the Manifest panel, add the JSON code shown in Listing 4-27 to the appRoles
    23. Listing 4-27 JSON Application Roles definition

      	
      "appRoles": [
      {
      "allowedMemberTypes": [
      "User"
      ],
      "description": "User readers can read basic profiles of all users in the
      directory",
      "displayName": "UserReaders",
      "id": "a816142a-2e8e-46c4-9997-f984faccb625",
      "isEnabled": true,
      "lang": null,
      "origin": "Application",
      "value": "UserReaders"
      },
      {
      "allowedMemberTypes": [
      "User"
      ],
      "description": "Directory viewers can view objects in the whole directory.",
      "displayName": "DirectoryViewers",
      "id": "72ff9f52-8011-49e0-a4f4-cc1bb26206fa",
      "isEnabled": true,
      "lang": null,
      "origin": "Application",
      "value": "DirectoryViewers"
      }
      ],
      	
      
    24. In the Manifest panel, click the Save button.
    25. In the navigation menu on the left side of your application’s blade, click Certificates & Secrets.
    26. On the Certificates & Secrets panel, click the New Client Secret button.
    27. Type a Description for the client secret. This description is only foryour reference.
    28. Click the Add button.
    29. In the Client Secrets lists, copy the value of the new client secret. You are going to use it in a later step, so you should copy this value now. Once you leave the Certificates & Secrets blade, you won’t be able to see the value of any client secret.
    30. In the navigation menu on the left side of your application’s blade, click Authentication.
    31. On the Redirect URIs section, add a new redirect URI. Ensure that the selected type is Web.
    32. On the Redirect URI textbox, type https://localhost:44321/signingoidc
    33. On the Advanced settings, in the Logout URL setting, type https://localhost:44321//signout-callback-oidc.
    34. In the Implicit Grant section, check the ID Tokens option.
    35. At the top of the Authentication blade, click the Save button.
    36. In the Visual Studio 2017 window, on the Solution Explorer, open the json file in the WebApp-OpenIDConnect-DotNet project.
    37. In the json file, replace the values of the following properties with the values that you copied in steps 13 and 22:

    Domain This is the domain name of your tenant and should be a DNS fully qualified name, such as contoso.com. You can find the name of your tenant at the top of the Overview blade of your Azure Active Directory tenant in the Azure Portal.

    TenantId You got this value in step 13.

    ClientId You got this value in step 13.

    ClientSecret You got this value in step 22.

    At this point, you should be able to run the example application in Visual

    Studio. Because you didn’t assign any of the application roles to any of your

    Azure AD users, in order for users to access protected items, you need to assign application roles to your Azure AD users. The next steps show how to assign an application role to any of your Azure AD users. For this example, you should use two different users to test the different application roles.

    1. Open the Azure Portal (https://portal.azure.com.
    2. In the navigation menu on the left side of the portal, click Azure Active Directory.
    3. On the Azure Active Directory blade, in the Manage section on the navigation menu, click Enterprise Applications.
    4. On the Enterprise Applications blade, look for your application’s name in the list of applications and click it.
    5. On your application’s blade, on the Manage section in the navigation menu, click Users And Groups.
    6. On the Users And Groups panel, click the Add User button.
    7. On the Add Assignment panel, click the Users And Groups item.
    8. On the Users And Groups panel, look for the user to whom you want to assign a role.
    9. Click each user for whom you want to assign the application role.
    10. Click the Select button.
    11. On the Add Assignment panel, click the Select Role item.
    12. On the Select Role panel, shown in Figure 4-9, select the role that you want to assign to your users.
    13. Figure 4-9 Assigning an application role
      Screenshot_38
    14. Click the Select button.
    15. In the Add Assignment panel, click the Assign button.
    16. Repeat steps 5-12 for any additional role assignment.
    17. In Visual Studio, rebuild your solution by clicking Build > Rebuild Solution.
    18. Press F5 to run your solution.
    19. When you log in the first time to your application using your Azure AD user, Azure AD should ask your consent to access your Azure AD tenant information. On the Permissions Requested page, check the Consent On Behalf Of Your Organization option.
    20. Click the Accept button.
    21. On the application’s home page, click the List All Users In The Tenant (You Need To Be A Member Of The ‘UserReaders’ Role) If you assigned your user the UserReaders role, you should be able to see a list of all users in your Azure AD tenant.
    22. On the application’s home page, click the link List All The Groups And Roles The Signed In User Is A Member Of (You Need To Be A Member Of The ‘DirectoryViewers’ Role). If you assigned your user the DirectoryViewers role, you should be able to see a list of all roles and groups that your user is a member of.

    If you get a Denied Access error, review the role that you assigned to the user who you are using for login to the application.

    During the configuration of this example, we reviewed how to create your custom application roles. Now we are going to review how to use those application roles in your code for controlling the access to the different parts of your application.

    You configure the role-based authentication in the ConfigureService() method in the Startup.cs file. In this example, your code extracts the role membership based on the claims contained in the JWT token. For this reason, you need to tell your code which claims contain the roles. You do this by using the following code snippet:

    	
    services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
    {
    // The claim in the Jwt token where App roles are available.
    options.TokenValidationParameters.RoleClaimType = "roles";
    });
    	
    

    When your code extracts and maps the claims from the JWT token, it uses the default claims mapping. The drawback of using this default mapping is that the claims are mapped using the old format for accommodating old SAML applications. This means that using the default mapping, the name of the claim that contains the role membership of your user would be http://schemas.microsoft.com/ws/2008/06/identity/claims/role instead of just “roles.” You can change this behavior by adding the following line of code before configuring the OAuth authentication:

    	
    JwtSecurityTokenHandler.DefaultMapInboundClaims = false
    	
    

    Once you have configured your code for extracting the roles from the JWT token, you need to configure the access control on each controller for which you need to restrict the access. In this example, you use the AppRoles helper class for storing the different application roles, which is shown in the following code snippet:

    	
    /// <summary>
    /// Contains a list of all the Azure Ad app roles this app works with
    /// </summary>
    public static class AppRoles
    {
    public const string UserReaders = "UserReaders";
    public const string DirectoryViewers = "DirectoryViewers";
    }
    	
    

    Bear in mind that the strings defined for the properties of this class match exactly with the Value property of each application role that you configured in the application’s manifest.

    You control which role is allowed to access a resource in your application by using the Authorize attribute on each action method that you want to protect. The following code snippets show how to protect the Groups() action in the Account controller and the Users() action in the Home controller:

    	
    //Allow access only to users with the DirectoryViewers role.
    [Authorize(Roles = AppRoles.DirectoryViewers)]
    public async Task<IActionResult> Groups()
    {
    //Allow access only to users with the UserReaders role.
    [Authorize(Roles = AppRoles.UserReaders )]
    public async Task<IActionResult> Users()
    {
    	
    

    Exam Tip

    Role-Based Access Control grants access to the different resources of your application based on the actions that the user is allowed to perform in your application. Claims-Based Access Control grants access to the resource based on the information that the user has; for example, this information could be the birthdate or if Multifactor Authentication option is enabled for the user. You should not confuse the RBAC roles that you can define for your application with the built-in RBAC roles available for managing the access to the Azure Resources.

    Create shared access signatures

    Until now, all the protection and access control mechanisms that we have reviewed in this section had to do with protecting the information managed directly by your application. These mechanisms are good if your application manages and presents the information to the user, but they are not appropriate

    for other services that can also store information managed by your application. If your application uses Azure Storage accounts for storing some reports, images, or documents in a table, and you want to grant access to third parties to that information, none of the mechanisms we already reviewed are appropriate for this scenario.

    Azure provides you with the ability to control the access to information stored in Azure Storage Accounts without needing to grant access to external user accounts to the Azure Storage Account or sharing the Access Keys with third parties. This mechanism is the Shared Access Signature.

    A Shared Access Signature (SAS) is a special token that you can use for granting granular access to only specific parts of your Azure Storage Account. When you create an SAS token, you define which service (blobs, files, queues, or tables) can access the user, and which operation the user can perform in that service. You can define an SAS at different levels:

    Service You grant access to all containers and elements related to the same service. For example, if you define an SAS for the Blob service, the user has access to all containers and blobs in the Azure Blob storage account.

    Container You grant access only to all elements stored in a single container inside a storage service. For example, if you define an SAS for the blob container test, the user can access any blob created in the test container.

    Element You grant access only to specific elements in a container. You can only create SAS tokens for blobs and files. For example, you can create an SAS for a file in a file share or a blob in a blob container.

    The following example shows how to create a Shared Access Signature for a blob in a blob container. For this example, you need an Azure Storage Account with a blob container that is configured with a private access level and a blob stored in the blob container:

    1. Open the Azure Portal (https://portal.azure.com.
    2. In the search text box on the top of the Azure Portal, type the name of your Azure Storage Account.
    3. In the Results list, click the name of your Azure Storage Account.
    4. On your Azure Storage Account’s blade, click StorageExplorer (preview) in the navigation menu on the left side of the blade.
    5. On the Storage Explorer (preview) panel shown in Figure 4-10, expand the Blob Containers node and click on the container that stores the blob to which you need to grant access.
    6. Figure 4-10 Storage services in the Storage Explorer (preview)
      Screenshot_39
    7. In the Blob Containers panel, right-click the blob and click Get Share Access Signature on the contextual menu.
    8. In the Shared Access Signature panel shown in Figure 4-11, configure the Start Time, Expiry Time, and Permissions that you want to grant to the SAS token.
    9. Figure 4-11 Creating a Shared Access Signature
      Screenshot_40
    10. Click the Create button at the bottom of the panel.
    11. On the Shared Access Signature panel, copy the URL of the newly generated SAS. You can share this SAS URL with any third party who needs to access this specific blob.

    You can use these same steps for creating an SAS for a container. Rightclick on the container for which you want to create the SAS and click Get Shared Access Signature in the contextual menu.

    As you can imagine, one drawback of using this approach is that anyone who has access to the SAS URL can access the information protected by that SAS. You can improve the security of the SAS tokens by creating an Access Policy and attaching the policy to the SAS token. In the “Design and Implement Policies for Tables” section in Chapter 3, we reviewed how Access Policy works for Azure tables. The same concepts that you reviewed in that section apply to the rest of services available in the Azure Storage Account.

    Skill 4.3: Implement secure data solutions

    In the previous skills, we reviewed how to protect the access to the data by authenticating and authorizing users who try to access the information managed in your application. This protection is only a portion of the mechanisms that you should put in place for protecting your data. You also need to ensure that your data is unreadable by non-authorized users while the data is traveling from the server to your users’ application or browser and vice-versa. You should also ensure that once your users don’t need to work with your application data, this data is securely stored on your servers. You can achieve both objectives by applying encryption techniques to your data while they are traveling over the internet (encryption in transit) or while they are stored in your server (encryption at rest).

    When you encrypt your data, you need to use encryption and decryption keys or secrets for accessing and protecting the data. Storing these secrets and encryption keys is as important as encrypting the data. Losing an encryption or decryption key is similar to losing the keys to your house. The Azure Key Vault allows you to securely store these encryption/decryption keys as well as other secrets or certificates that your applications may require in a secured encryption store in Azure. In conjunction with Managed Identities, the Azure Key Vault services allow you to securely store your secrets without needing to store a password, certificate, or any kind of credentials for accessing your secrets.

    Encrypt and decrypt data at rest and in transit

    When you access an Azure service, you are sending and receiving information that travels over the Internet. If that information is not protected, a malicious user could steal that information. The solution for protecting your information while it is traveling over the Internet is to encrypt that information before it is sent from the source and decrypt it when it arrives at the destination. This process is known as encryption in transit. Azure offers different techniques for applying encryption in transit to your communications with the Azure services:

    SSL/TLS Microsoft uses TLS for encrypting the connections between Azure services and its customers. TLS is a well-known protocol for encrypting connections. This protocol is the base for other secure protocols like HTTPS or RDP. Microsoft also uses the Perfect Forward Secrecy (PFS) feature for ensuring the uniqueness of the keys used for the encryption in the TLS protocol.

    SAS When you configure a Shared Access Signature for your storage account, you have the option to enforce the use of the HTTPS protocol. This means you ensure that your data is encrypted in transit while it is traveling from or to the Azure datacenter.

    SMB 3.0 You can use the SMB 3.0 protocol for accessing data in your

    Azure File Storage or your Windows Server 2012 or newer Azure Virtual Machines. This protocol supports encryption that is enabled by default for Azure File Storage. If you want to use SMB 3.0 in your Azure VMs, you need to enable the encryption on the file shares. Azure only allows encrypted connections to the Azure Files from outside the region or datacenter if SMB 3.0 encryption is enabled.

    RDP You can access your IaaS Windows Virtual Machines by using the Remote Desktop Protocol (RDP). This protocol uses TLS for encrypting the connection from your Windows, Linux, or MacOSX RDP client to your Azure VM.

    SSH You can access your IaaS Linux Virtual Machines by using the Secure Shell protocol (SSH). The SSH protocol encrypts all the communications between the client and the server. You can use a public/private key pair for authentication, eliminating the need for using usernames and passwords.

    VPN The Virtual Private Network (VPN) allows you to establish a secure connection with your Azure Virtual Networks using different secure and well-known protocols, such as IPSec/IKE or SSTP (based on

    HTTPS connections). You can even use your internal Public Key Infrastructure (PKI) for using your internal certificates for authenticating Point-to-Site VPN clients.

    Use the following procedure for enforcing HTTPS connections on your Azure App Service application:

    1. Open the Azure Portal (https://portal.azure.com).
    2. In the search textbox at the top of the Azure Portal, type the name of your Azure App Service application.
    3. In the result list, click your Azure App Service application.
    4. On your Azure App Service application’s blade, on the navigation menu at the left side of the blade, click TLS/SSL Settings in the Settings section.
    5. On the TLS/SSL Settings panel shown in Figure 4-12, click the HTTPS Only switch control and set this control to On.
    6. Figure 4-12 Configuring HTTPS options in an Azure App Service
      Screenshot_41

    Encryption at rest is the capability that Azure offers of encrypting your data while it is stored in any of the services offered by Azure. When encryption at rest is enabled on Azure services, such as Azure Storage, Azure SQL Database, Azure Data Lake, or Azure Cosmos DB, the data is encrypted when it is committed to the storage system, and it is decrypted when you need to access it. Microsoft takes care of the encryption keys for these services.

    Azure uses symmetric cryptography for encrypting and decrypting a large amount of data using a Data Encryption Key (DEK). This data can be partitioned. In that case, Azure uses different encryption keys for different partitions. Azure stores the encryption keys in a secure location with identitybased access control and audit policies. Azure uses asymmetric keys, or Key Encryption Keys (KEK), for encrypting the symmetric key on the secure location. Using that asymmetric key enhances the security level when storing the encryption key used for your data. When you plan to enable encryption at rest, you should consider three different data encryption models:

    Server-side encryption using Service-Managed keys In this model, the Azure service provides and manages the encryption keys. The Azure Resource Provider performs all the encryption and decryption operations.

    Server-side encryption using Customer-Managed keys in Azure Vault In this model, the customer provides and manages the encryption keys. The encryption keys are stored in an Azure Key Vault managed by the customer. The Azure Resource Provider performs all the encryption and decryption operations.

    Server-side encryption using Customer-Managed keys on customercontroller hardware In this model, the customer provides and manages the encryption keys. The encryption keys are stored using specialized hardware controlled by the customer. The Azure Resource Provider performs all the encryption and decryption operations. Not all Azure services support this type of integration with external services.

    Customer-side encryption The customer encrypts the data before uploading it to the Azure service and decrypts the data after downloading from the Azure service. In this model, the Azure service cannot see the decrypted data. The encryption keys are managed by the customer, using on-premises or cloud-based keys stores.

    The following example shows how to ensure that encryption at rest is enabled for an Azure SQL Database:

    1. Open the Azure Portal (https://portal.azure.com).
    2. Type the name of your SQL Database in the search text box at the top of the Azure Portal.
    3. On the Azure SQL Database blade of your database, click Transparent Data Encryption on the Security section on the navigation menu.
    4. On the Transparent Data Encryption blade shown in Figure 4-13, ensure that the Data Encryption switch is set to On.
    5. Figure 4-13 Transparent Data Encryption
      Screenshot_42

    Need More Review? Azure Encryption-at-Rest

    You can find more information about how Encryption at Rest works by reviewing the article at https://docs.microsoft.com/enus/azure/security/azure-security-encryption-atrest.

    You can also extend your information about the different encryption options available in Azure by reviewing the article at https://docs.microsoft.com/en-us/azure/security/security-azureencryption-overview.

    Create, read, update, and delete keys, secrets, and certificates by using the KeyVault API

    Azure Key Vault is the service provided by Microsoft for securely storing

    secret keys and certificates in a centralized, secure store. By using Azure Key Vault, your developers no longer need to store this sensitive information on their computers while they are developing an application. Thanks to the identity-based access control, you only need to configure a policy for granting access to the needed service or user principals to the secure store. Another advantage is that you can apply fine-grained access control, allowing access to specific secrets only to the needed application or user.

    The next example shows how to use the KeyVault API for creating, reading, updating, or deleting the different elements that you can store in the Azure Key Vault. You need an empty Azure App Service and an Azure Key Vault configured in your Azure subscription to run this example.

    1. Open the Azure portal at https://portal.azure.com.
    2. In the search text box on top of the Azure portal, type the name of your Azure Web App. Click the name of your Azure Web App.
    3. On the Azure Web App Service blade, click on the Identity menu item in the Settings section.
    4. In the Status switch control, click the On option.
    5. Click Save.
    6. In the Enable System Assigned Managed Identity dialog box, click Yes.
    7. Once you enable the system-assigned managed identity, you get the Principal or Object ID associated with your Azure App Service.
    8. In the search text box at the top of the Azure portal, type the name of your Azure Key Vault. Click the name of your Azure Key Vault.
    9. On the Key Vault blade, click Access Policies in the Settings section in the navigation menu.
    10. On the Access Policies blade, click Add New.
    11. On the Add Access Policy panel, click the Configure From Template drop-down menu and select the Key, Secret, and Certificate Management option.
    12. Click Select Principal.
    13. On the Principal panel, type the name of your Azure App Service in the Select textbox.
    14. In the results list, click the name of your Azure App Service.
    15. Click the Select button.
    16. On the Add Access Policy panel, click OK.
    17. On the Access Policies blade, click Save.
    18. Repeat steps 10 to 17 and add the user account that you use for accessing your Azure subscription. You need to add this policy to be able to debug your code using Visual Studio. You need to ensure that you add the policy for granting access to the same user account that you use accessing your Azure subscription from Visual Studio.
    19. Open Visual Studio 2017.
    20. Click File > New > Project.
    21. On the New Project window, on the navigation menu on the left of the window, click Installed > Visual C# > Cloud.
    22. In the template list, select ASP.NET Web Application (.NET Framework).
    23. At the bottom of the window, type a Name for the project.
    24. Select the Location where this project will be saved.
    25. Click OK.
    26. On the New ASP.NET Web Application window, select the MVC template.
    27. Click OK.
    28. In the Visual Studio window, click Tools > NuGet Package Manager > Manage NuGet Packages For Solution.
    29. On the NuGet Package Manager tab, click Browse.
    30. Type Azure.Services.AppAuthentication and press Enter.
    31. Click the Azure.Services.AppAuthentication package.
    32. On the right side of the NuGet Manager tab, click the checkbox next to your project.
    33. Click the Install button.
    34. In the Preview Changes window, click OK.
    35. In the License Acceptance window, click the I Accept button.
    36. Repeat steps 27 to 34 and install the Azure.KeyVault package.
    37. Open the cs file.
    38. Replace the content of the Index() method with the content of Listing 428. You may need to add the following namespaces to the cs file:

    Microsoft.Azure.KeyVault

    Microsoft.Azure.KeyVault.Models

    Microsoft.Azure.Services.AppAuthentication

    System.Threading

    System.Threading.Tasks

    Listing 4-28 Creating, deleting, updating, and reading Key Vault items

    	
    // C#. ASP.NET.
    public ActionResult Index()
    {
    string keyVaultName = "<YOUR_VAULT's_NAME>";
    string vaultBaseURL = $"https://{keyVaultName}.vault.azure.net";
    //Get a token for accessing the Key Vault.
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    //Create a Key Vault client for accessing the items in the vault;
    var keyVault = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(
    azureServiceTokenProvider.KeyVaultTokenCallback));
    // Manage secrets in the Key Vault.
    // Create a new secret
    string secretName = "secret-az203";
    Task.Run(async () => await keyVault.SetSecretAsync(vaultBaseURL, secretName,
    "This is a secret testing value")).Wait();
    var secret = Task.Run(async () => await keyVault.GetSecretAsync
    ($"{vaultBaseURL}/secrets/{secretName}")).GetAwaiter().GetResult();
    // Update an existing secret
    Task.Run(async () => await keyVault.SetSecretAsync(vaultBaseURL, secretName,
    "Updated the secret testing value")).Wait();
    secret = Task.Run(async () => await keyVault.
    GetSecretAsync($"{vaultBaseURL}/secrets/{secretName}")).GetAwaiter().
    GetResult();
    // Delete the secret
    Task.Run(async () => await keyVault.DeleteSecretAsync(vaultBaseURL,
    secretName)).Wait();
    // Manage certificates in the Key Vault
    string certName = "cert-az203";
    // Create a new self-signed certificate
    var policy = new CertificatePolicy
    {
    IssuerParameters = new IssuerParameters
    {
    Name = "Self",
    },
    KeyProperties = new KeyProperties
    {
    Exportable = true,
    KeySize = 2048,
    KeyType = "RSA"
    },
    SecretProperties = new SecretProperties
    {
    ContentType = "application/x-pkcs12"
    },
    X509CertificateProperties = new X509CertificateProperties
    {
    Subject = "CN=AZ203KEYVAULTDEMO"
    }
    };
    Task.Run(async () => await keyVault.CreateCertificateAsync(vaultBaseURL,
    certName, policy, new CertificateAttributes { Enabled = true })).Wait();
    // When you create a new certificate in the Key Vault it takes some time
    // before is ready.
    // We added some wait time here for the sake of simplicity.
    Thread.Sleep(10000);
    var certificate = Task.Run(async () => await keyVault.GetCertificateAsync
    (vaultBaseURL, certName)).GetAwaiter().GetResult();
    // Update properties associated with the certificate.
    CertificatePolicy updatePolicy = new CertificatePolicy
    {
    X509CertificateProperties = new X509CertificateProperties
    {
    SubjectAlternativeNames = new SubjectAlternativeNames
    {
    DnsNames = new[] { "az203.examref.testing" }
    }
    }
    };
    Task.Run(async () => await keyVault.UpdateCertificatePolicyAsync(vaultBase
    URL, certName, updatePolicy)).Wait();
    Task.Run(async () => await keyVault.CreateCertificateAsync(vaultBaseURL,
    certName)).Wait();
    Thread.Sleep(10000);
    certificate = Task.Run(async () => await keyVault.GetCertificateAsync(vaultB
    aseURL, certName)).GetAwaiter().GetResult();
    Task.Run(async () => await keyVault.UpdateCertificateAsync(certificate.
    CertificateIdentifier.Identifier, null, new CertificateAttributes { Enabled
    = false })).Wait();
    Thread.Sleep(10000);
    // Delete the self-signed certificate.
    Task.Run(async () => await keyVault.DeleteCertificateAsync(vaultBaseURL,
    certName)).Wait();
    // Manage keys in the Key Vault
    string keyName = "key-az203";
    NewKeyParameters keyParameters = new NewKeyParameters
    {
    Kty = "EC",
    CurveName = "SECP256K1",
    KeyOps = new[] { "sign", "verify" }
    };
    Task.Run(async () => await keyVault.CreateKeyAsync(vaultBaseURL, keyName,
    keyParameters)).Wait();
    var key = Task.Run(async () => await keyVault.GetKeyAsync(vaultBaseURL,
    keyName)).GetAwaiter().GetResult();
    // Update keys in the Key Vault
    Task.Run(async () => await keyVault.UpdateKeyAsync(vaultBaseURL, keyName,
    null, new KeyAttributes { Expires = DateTime.UtcNow.AddYears(1)})).Wait();
    key = Task.Run(async () => await keyVault.GetKeyAsync(vaultBaseURL,
    keyName)).GetAwaiter().GetResult();
    // Delete keys from the Key Vault
    Task.Run(async () => await keyVault.DeleteKeyAsync(vaultBaseURL, keyName)).
    Wait();
    return View();
    }
    	
    

    At this point, you should be able to run the example. Because we didn’t make any modifications to any view, you should not be able to see any changes in your Azure Key Vault. To be able to see how this code creates, reads, modifies, and deletes the different item types in your Azure Key Vault, you should set some breakpoints:

    1. Add a breakpoint to the following lines:
    2. 		
      string secretName = ”secret-az203”;
      string certName = ”cert-az203”;
      string keyName = ”key-az203”;
      		
      	
    3. Open your Azure Key Vault in the Azure Portal, as shown in step 8 of the previous procedure.
    4. On your Azure Key Vault blade, click Secrets in the Settings section in the navigation menu.
    5. In Visual Studio, press F5 to debug your project.
    6. When you hit the breakpoint, press F10 and go back to the Azure Portal to see the results. You should use the Refresh button to see the changes in your Azure Key Vault.

    Note: Forbidden Access

    If you get a Forbidden Access Error while you are debugging your application in Visual Studio, ensure that you created an Access Policy for the user account that you have configured in your Visual Studio for connecting with your Azure subscription. You need to ensure that the Access Policy grants all the needed privileges to the different object types in the Azure Key Vault.

    When you work with the KeyVault API, you need to create a KeyVaultClient object that is responsible for the communication with the Azure Key Vault services. As we saw in the example shown in the “Implement Managed Service Identity (MSI)/Service Principal authentication” section, you need to get an access token for authenticating your service or user principal to the Azure Key Vault. The following code snippet shows how to perform this authentication:

    	
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    var keyVault = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureService
    TokenProvider.KeyVaultTokenCallback));
    	
    

    Now you can use the keyVault variable for working with the different item types. The KeyVault API provides specialized methods for each item type. This way, you should use the SetSecretAsync() method for creating a new secret in your Azure Key Vault. The following code snippet shows how to create a new secret:

    	
    Task.Run(async () => await keyVault.SetSecretAsync(vaultBaseURL, secretName, "This is a
    secret testing value")).Wait();
    	
    

    If you try to create a new secret, key, or certificate using the same name of an object that already exists in the vault, you are creating a new version of that object, as shown in Figure 4-14. You can click on each version to review the properties of the object for that version.

    Figure 4-14 A secret object with different versions
    Screenshot_43

    Most of the methods in the KeyVault API that work with items require the vault URL and the name of the item that you want to access. In this example, you define a variable with the correct value at the beginning of the Index() method, as shown in the following code snippet:

    	
    string keyVaultName = "<YOUR_VAULT's_NAME>";
    string vaultBaseURL = $"https://{keyVaultName}.vau
    	
    

    These methods are usually overloaded for accepting an object identifier instead of the vault base URL and the object’s name. The identifier has the following form:

    	
    https://{keyvault-name}.vault.azure.net/{object-type}/{object-
    name}/{object-version} Where:
    	
    

    Keyvault-name This is the name of the key vault where the object is stored.

    Object-type This is the type of object that you want to work with. This value can be secrets, keys, or certificates.

    Object-name This is the name that you give the object in the vault.

    Object-version This is the version of the object that you want to access.

    Creating a key or certificate uses a slightly different approach from the one that you used for creating a secret. Keys and certificates are more complex objects and require some additional configuration for creating them. The following code snippet extracted from Listing 4-28 shows how to create a new self-signed certificate in the Azure Key Vault:

    	
    // Create a new self-signed certificate
    var policy = new CertificatePolicy
    {
    IssuerParameters = new IssuerParameters
    {
    Name = "Self",
    },
    KeyProperties = new KeyProperties
    {
    Exportable = true,
    KeySize = 2048,
    KeyType = "RSA"
    },
    SecretProperties = new SecretProperties
    {
    ContentType = "application/x-pkcs12"
    },
    X509CertificateProperties = new X509CertificateProperties
    {
    Subject = "CN=AZ203KEYVAULTDEMO"
    }
    };
    Task.Run(async () => await keyVault.CreateCertificateAsync(vaultBaseURL, certName,
    policy, new CertificateAttributes { Enabled = true }
    	
    

    You need to create a CertificatePolicy object before you can create the certificate. A certificate policy is an object that defines the properties of how to create a certificate and any additional version associated with the certificate object. You use this certificate policy object as a parameter of the CreateCertificateAsync() method. If you need to modify any property of an existing certificate, you need to define a new certificate policy, update the policy using the UpdateCertificatePolicyAsync() method, and create a new certificate version using the CreateCertificateAsync() method, as shown in the following code snippet:

    	
    // Update properties associated with the certificate.
    CertificatePolicy updatePolicy = new CertificatePolicy
    {
    X509CertificateProperties = new X509CertificateProperties
    {
    SubjectAlternativeNames = new SubjectAlternativeNames
    {
    DnsNames = new[] { "az203.examref.testing" }
    }
    }
    };
    Task.Run(async () => await keyVault.UpdateCertificatePolicyAsync(vaultBaseURL, certName,
    updatePolicy)).Wait();
    Task.Run(async () => await keyVault.CreateCertificateAsync(vaultBaseURL, certName)).
    Wait();
    	
    

    Deleting an object from the key vault is quite straightforward; you only need to provide the vault base URL and the object’s name to the DeleteSecretAsync(), DeleteCertificateAsync(), or DeleteKeyAsync() method. Azure Key Vault also supports soft-delete operations on the protected objects or the vault itself. This option is not enabled by default. When you soft delete an object or a vault, the Azure Key Vault provider automatically marks them as deleted but holds the object or vault for a default period of 90 days. This means you can recover the deleted object later if needed.

    Need More Review? More details About Keys, Secrets, And Certificates

    You can find more information about the details of the different object types that are available in the Azure Key Vault service by reviewing this article: https://docs.microsoft.com/en-us/azure/key-vault/about-keyssecrets-and-certificates

    Chapter summary

    Authentication is the act of proving that a user is who he or she claims claims to be.

    A user authenticates by providing some information that the user only knows.

    There are several mechanisms of authentication that provide different levels of security.

    Some of the authentication mechanisms are form-based, token-based, or certificate-based.

    Using form-based authentication requires your application to store your users’ passwords.

    Form-based authentication requires HTTPS to make the authentication process more secure.

    Using token-based authentication, you can delegate the authorization to third-party authentication providers.

    You can add social logins to your application by using token-based authentication.

    Certificate-based authentication requires that the user send a valid digital certificate for authenticating to the server.

    Multifactor Authentication is an authentication mechanism that requires the users to provide more than one more piece of information that only the user knows.

    You can easily implement Multifactor Authentication by using Azure Active Directory.

    There are four main actors in OAuth authentication: client, resource server, resource owner, and authentication server.

    The resource owner needs to authenticate the client before sending the Authorization Grant.

    The access token grants access to the resource hosted on the resource server.

    The authorization grant or authorization code grants the client the needed rights to request an Access Token to the Authorization Server.

    The client uses the refresh token to get a new access token when it expires without needing to request a new authorization code.

    The JSON web token is the most extended implementation of OAuth tokens.

    Claim-based access control authorization controls the access to your application based on properties of the users.

    The identity manager adds claims to the user’s identity.

    You need to define a policy in your code for asking for the presence of a claim or the accepted values for a claim.

    Role-Based Access Control (RBAC) authorization controls the access to your application based on the actions that a user can do in your

    application.

    You need to modify the manifest of your application registered in Azure AD for creating your custom application roles.

    Application roles are attached to the user’s identity as role claims.

    Shared access signature tokens provide fine-grained access control to your Azure storage accounts.

    You can create an SAS token for service, container, and item levels.

    Azure provides encryption features for protecting the information on your service instances.

    Azure encrypts the information while it is traveling over a virtual network or the Internet by using encryption in transit.

    Azure encrypts the information when it is stored and not accessed by using encryption at rest.

    Data stored with encryption at rest enabled is encrypted and decrypted when the user needs to access the data.

    Azure Key Vault allows you to store three types of objects: keys, secrets, and certificates.

    You should use Managed Service Identity authentication for accessing the Azure Key Vault.

    You need to define a certificate policy before creating a certificate in the Azure Key Vault.

    If you import a certificate into the Azure Key Vault, a default certificate policy is automatically created for you.

    Thought experiment

    In this thought experiment, demonstrate your skills and knowledge of the topics covered in this chapter. You can find answers to this thought experiment in the next section.

    You are developing a web application for your company. The application is in the early stages of development. This application is an internal application that will be used only by the employees of the company. Your company uses Office 365 connected with your company’s Active Directory domain. Answer the following questions about the security implementation of this application:

    1. The employees need to be able to access the application using the same username and password they use for accessing Office 365. What type of authentication should you use?
    2. Some parts of the application manage sensitive information. The security policy of the company requires users who need to access this information to use Multifactor Authentication. How should you implement the access control to these sensitive areas?
    3. You are using Azure App Services for developing the application. You need to ensure that the web application can access other Azure services without using credentials in your code. What should you do?

    Thought experiment answers

    This section contains the solution to the thought experiment. Each answer explains why the answer choice is correct.

    1. You should use OAuth authentication with Azure Active Directory
    2. (Azure AD). When you connect Office 365 with an Active Directory (AD) domain, users in the AD domain can authenticate to Office 365 using the same username and password they use in the AD domain. Office 365 uses an Azure AD tenant for managing the identities of the users in the subscription. Your organization already has configured the synchronization between AD and Office 365 and Azure AD. By using OAuth authentication with Azure AD, your users should be able to access your application using the same username and passwords that they use in the AD domain.
    3. You should implement a Claims-Based Access Control (CBAC) authentication. You need to control the access to sensitive parts of the application based on a feature of the user that is trying to get access. In this situation, the user needs to have configured the Multifactor Authentication (MFA) feature. You use CBAC authentication when you need to control the access based on properties of the user. You should not use Role-Based Access Control (RBAC) authentication for this scenario because you cannot guarantee that the user in the role has the MFA feature enabled.
    4. You should use the Managed Service Identity (MSI) authentication. Using the feature, Azure authenticates services based on a service principal configured in a service instance. You can use MSI
    5. authentication with services that support Azure AD authentication, like Azure Key Vault or Azure SQL Databases. You need to enable a system-assigned or user-assigned managed identity on your Azure App Service. Using MSI, the Azure SQL Database authenticates the identity assigned to your Azure App Service without needing to provide any password.
    UP

    LIMITED OFFER: GET 30% Discount

    This is ONE TIME OFFER

    ExamSnap Discount Offer
    Enter Your Email Address to Receive Your 30% Discount Code

    A confirmation link will be sent to this email address to verify your login. *We value your privacy. We will not rent or sell your email address.

    Download Free Demo of VCE Exam Simulator

    Experience Avanset VCE Exam Simulator for yourself.

    Simply submit your e-mail address below to get started with our interactive software demo of your free trial.

    Free Demo Limits: In the demo version you will be able to access only first 5 questions from exam.