Azure Authentication using OAuth in ASP.NET WebForms (Owin)

Azure Authentication using OAuth in ASP.NET WebForms (Owin)

With all major deployment going to Azure WebApps – it is imperative for our organization to handle the Authentication from AAD perspective; so in order to use AAD Authentication, the approach is to use an App which serve as a “Bridge” between AAD & the solution which consume it. Follow this link If you wanna know more on how to Register an app with the Azure Active Directory v2.0 endpoint.

The requirement is based on a scenario where the user use the browser to access an ASP.NET website which authenticate the user automatically.

We need to use the following libraries:

  • Middleware that enables an application to use OpenIdConnect for authentication

Microsoft.Owin.Security.OpenIdConnect

Install-Package Microsoft.Owin.Security.OpenIdConnect        

  • Middleware that enables an application to maintain a user session by using cookies

Microsoft.Owin.Security.Cookies

Install-Package Microsoft.Owin.Security.Cookies        

  • Middleware that enables OWIN-based applications to run on Internet Information Services (IIS) by using the ASP.NET request pipeline

Microsoft.Owin.Host.SystemWeb

Install-Package Microsoft.Owin.Host.SystemWeb        

These libraries enable single sign-on (SSO) by using OpenID Connect through cookie-based authentication. After authentication is completed and the token representing the user is sent to your application, OWIN middleware creates a session cookie. The browser then uses this cookie on subsequent requests so that the user doesn’t have to retype the password, and no additional verification is needed.


Configure the authentication pipeline

The following steps are used to create an OWIN middleware Startup class to configure OpenID Connect authentication. This class is executed automatically when your IIS process starts. (If your project doesn’t have a?Startup.cs?file in the root folder:)

1. Add?OWIN?and?Microsoft.IdentityModel?references to Startup.cs:

using Microsoft.Owin;
using Owin;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Security.Notifications;
        

2. Replace Startup class with the following code:

public class Startup
{
    // The Client ID is used by the application to uniquely identify itself to Microsoft identity platform.
    string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];

    // RedirectUri is the URL where the user will be redirected to after they sign in.
    string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];

    // Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant)
    static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];

    // Authority is the URL for authority, composed of the Microsoft identity platform and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0)
    string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);

    /// <summary>
    /// Configure OWIN to use OpenIdConnect
    /// </summary>
    /// <param name="app"></param>
    public void Configuration(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

//"Katana bug #197" - https://stackoverflow.com/questions/49944071/idx21323-openidconnectprotocolvalidationcontext-nonce-was-null-openidconnectpro
app.UseKentorOwinCookieSaver();

        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                // Sets the ClientId, authority, RedirectUri as obtained from web.config
                ClientId = clientId,
                Authority = authority,
                RedirectUri = redirectUri,
                // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
                PostLogoutRedirectUri = redirectUri,
                Scope = OpenIdConnectScope.OpenIdProfile,
                // ResponseType is set to request the code id_token - which contains basic information about the signed-in user
                ResponseType = OpenIdConnectResponseType.CodeIdToken,
                // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application
                // To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name
                // To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter
                TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = false // This is a simplification
                },
                // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthenticationFailed = OnAuthenticationFailed
                }
            }
        );
    }

    /// <summary>
    /// Handle failed authentication requests by redirecting the user to the home page with an error in the query string
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
    {
        context.HandleResponse();
        context.Response.Redirect("/?errormessage=" + context.Exception.Message);
        return Task.FromResult(0);
    }
}        

3. Handle sign-in and sign-out requests:

In your Start Page where you want to handle authentication, add the following two methods to handle sign-in and sign-out to your controller by initiating an authentication challenge:

/// <summary>
/// Send an OpenID Connect sign-in request.
/// Alternatively, you can just decorate the SignIn method with the [Authorize] attribute
/// </summary>
public void SignIn()
{
    if (!Request.IsAuthenticated)
    {
        HttpContext.GetOwinContext().Authentication.Challenge(
            new AuthenticationProperties{ RedirectUri = "/" },
            OpenIdConnectAuthenticationDefaults.AuthenticationType);
    }
}

/// <summary>
/// Send an OpenID Connect sign-out request.
/// </summary>
public void SignOut()
{
    HttpContext.GetOwinContext().Authentication.SignOut(
            OpenIdConnectAuthenticationDefaults.AuthenticationType,
            CookieAuthenticationDefaults.AuthenticationType);
}

protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.IsAuthenticated)
            {
                Session["UserName"] = System.Security.Claims.ClaimsPrincipal.Current.FindFirst("name").Value;
                Session["UserUPN"] = System.Security.Claims.ClaimsPrincipal.Current.FindFirst("preferred_username").Value;
                Session["UserEmail"] = System.Security.Claims.ClaimsPrincipal.Current.FindFirst("https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
            }
            else
                SignIn();
        }        

Et voila! It is very easy to set up and use and it works like a charm.

So, in the context of deploying to Azure WebApps, it’s crucial to handle Authentication from the Azure Active Directory (AAD) perspective. The approach is to use an App as a “Bridge” between AAD and the consuming solution. This is particularly relevant when a user accesses an ASP.NET website via a browser, which authenticates the user automatically.

To achieve this, we use several libraries, including Microsoft.Owin.Security.OpenIdConnect, Microsoft.Owin.Security.Cookies, and Microsoft.Owin.Host.SystemWeb. These libraries enable single sign-on (SSO) using OpenID Connect through cookie-based authentication. Once authentication is complete, a session cookie is created, which the browser uses for subsequent requests, eliminating the need for the user to retype the password.

The authentication pipeline is configured using an OWIN middleware Startup class. This class, which is executed automatically when your IIS process starts, configures OpenID Connect authentication. It includes methods to handle sign-in and sign-out requests, and a method to handle failed authentication requests by redirecting the user to the home page with an error in the query string.

This setup is straightforward to implement and works effectively, providing a seamless authentication experience for users.

I hope you enjoyed reading and using it!

要查看或添加评论,请登录

Mourtaza Fazlehoussen的更多文章

社区洞察

其他会员也浏览了