Base solution for your next web application
Open Closed

Azure Active Directory Authentication #639


User avatar
0
antpstevens created

Hi Hikalkan,

Is there is any documentation of adding Azure Active Directory Authentication as as one of the option in external authentication . We are trying to implement the same .

We have a done some implementation as below

In StartUp.cs I having the below code to Azure Auth and which is working fine

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);          

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = ClientId,
                    Authority = String.Format(CultureInfo.InvariantCulture, AadInstance, "common"),
                    PostLogoutRedirectUri = PostLogoutRedirectUri,
                    RedirectUri = PostLogoutRedirectUri,
                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = false
                    },
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                        AuthenticationFailed = OnAuthenticationFailed,
                        RedirectToIdentityProvider = OnRedirectToIdentityProvider,
                    }
                });
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
        {
            // If the user is trying to sign up, we'll force the consent screen to be shown & pre-populate the sign-in name.
            if (notification.Request.Path.Value.ToLower() == "/account/signup/aad")
            {
                notification.ProtocolMessage.Prompt = "consent";
                string login_hint = notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["login_hint"];
                notification.ProtocolMessage.LoginHint = login_hint;
            }

            return Task.FromResult(0);
        }

        private Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            // When the user signs in, use ADAL to get a token and cache it for later use.
            ClientCredential credential = new ClientCredential(ClientId, AppKey);
            string userObjectId = notification.AuthenticationTicket.Identity.FindFirst(ObjectIdClaimType).Value;
            string tenantId = notification.AuthenticationTicket.Identity.FindFirst(TenantIdClaimType).Value;
            AuthenticationContext authContext = new AuthenticationContext(String.Format(CultureInfo.InvariantCulture, AadInstance, tenantId));
            AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                notification.Code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, GraphResourceId);
            if (result != null)
            {
                HttpContext.Current.Session["ADAuthResultUserName"] = result.UserInfo.GivenName.ToString();
            }
            else
            {
                HttpContext.Current.Session["ADAuthResultUserName"] = "";
            }
            return Task.FromResult(0);
        }

        private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
        {
            notification.HandleResponse();
            notification.Response.Redirect("/Error/ShowError?signIn=true&errorMessage=" + notification.Exception.Message);
            return Task.FromResult(0);
        }

andin the AccountController.cs

[HttpPost]
        [ValidateAntiForgeryToken]
        public void ExternalLoginAzureAD(string provider, string returnUrl)
        {
            HttpContext.GetOwinContext()
                .Authentication.Challenge(new AuthenticationProperties
                {
                    RedirectUri = Url.Action(
                        "ExternalLoginCallback",
                        "Account",
                        new
                        {
                            ReturnUrl = returnUrl,
                            tenancyName = _tenancyNameFinder.GetCurrentTenancyNameOrNull() ?? ""
                        })
                },
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);        
        }

With the above code I am able to successfully redirect user to Azure AD Authentication page and get the response in OnAuthorizationCodeReceived method. But after that when ExternalLoginCallback method is called I am getting loginInfo as null
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

[UnitOfWork]
        public virtual async Task<ActionResult> ExternalLoginCallback(string returnUrl, string tenancyName = "")
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

Do you have any idea why we are getting null on loginInfo or anything needs to be done additionally ?


4 Answer(s)
  • User Avatar
    0
    john_kattenhorn created

    We had this working pretty well, you can see our implementation in this PR which you can find here :

    <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero/pull/57">https://github.com/aspnetzero/aspnet-zero/pull/57</a>

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi @antpstevens,

    I've no experince on Azure AD. Can you check john's solution? If it does not help, you can ask here again.

    Thanks.

  • User Avatar
    0
    antpstevens created

    Thanks John.

    But do you have any pending changes to be checked-in? Currently I could see the changes in following files.

    src/MyCompanyName.AbpZeroTemplate.Web/App_Start/Startup.cs src/MyCompanyName.AbpZeroTemplate.Web/MyCompanyName.AbpZeroTemplate.Web.csproj src/MyCompanyName.AbpZeroTemplate.Web/Web.config src/MyCompanyName.AbpZeroTemplate.Web/packages.config

    Now while clicking on the Azure login button, it's taking the user to Azure login page and redirecting back to the ExternalLoginCallback(string returnUrl, string tenancyName = "") method

    But as loginInfo is coming as null it's again redirecting to the login page.

    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
                if (loginInfo == null)
                {
                    return RedirectToAction("Login");
                }
    
  • User Avatar
    0
    bspann created

    Place the following in your Startup.cs

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);