Base solution for your next web application
Open Closed

OpenIDConnect with Azure AD #2474


User avatar
0
jhoiby created

Hello!

I'm trying to get ASP.NET Boilerplate with Module Zero (both MVC and AngularJS version) to authenticate against our Office 365/Azure AD system, without success. I've been working on it for two months, bought books on Azure AD Authentication and sought much help from friends but I'm at the end of my rope and my project is stalled. (Thanks for letting me rant...)

First: Tried adding UseOpenIdConnectAuthentication in a method similar to your Facebook and Google auth code in Startup.cs. Result: Transfers to my O365 login page before displaying AspNetBoilerplate login page. On callback it gets stuck in a loop and doesn't display any registration or login option.

Second: Per another thread in this forum on Azure AD I rearranged the OWIN modules in startup.cs. Result: I get the login page, click on "Use OpenIDConnect", login on my Azure AD page, get sent to the callback, and get an HTTP 400.0 error that the antiforgery token is not present or is invalid.

Third: Copied the code from the other Azure AD thread very closely. Result: Same

At one point I had the callback seemingly working but the problem I had then was AuthenticationManager.GetExternalLoginInfoAsync() would return null. Since then I started from scratch and this time I'm not able to get even that far.

My current code for web.startup.configuration:

app.UseAbp();
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = "9cf42fd3-48ee-4b37-b53d-(redacted)",
                    Authority = "https://login.microsoft.com/(mydomain).onmicrosoft.com",
                    PostLogoutRedirectUri = "https://localhost:44356/",
                    CallbackPath = new PathString("/Account/ExternalLoginCallback")
                });
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });
            app.MapSignalR();

I've tried what I can but I just don't have enough experience with OWIN to get this to work. I'm sorry to bother you with this but can you provide me with some guidance? With the exploding popularity of Office 365 and Azure AD it seems to me that Azure AD authentication would be a hugely useful feature for many of your users and would be a great feature to integrate into your codebase.

Thank you!

James


7 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    We have successfully used OpenID with AzureAD in AspNet Zero. We used below configuration for that, can you give it a try ?

    app.UseOpenIdConnectAuthentication(CreateOpenIdConnectAuthOptions(configuration));
    
    private static OpenIdConnectOptions CreateOpenIdConnectAuthOptions(IConfiguration configuration)
    {
        var options = new OpenIdConnectOptions
        {
            ClientId = configuration["Authentication:OpenId:ClientId"],
            Authority = configuration["Authentication:OpenId:Authority"],
            PostLogoutRedirectUri = configuration["App:WebSiteRootAddress"] + "Account/Logout",
            ResponseType = OpenIdConnectResponseType.IdToken,
            SignInScheme = ExternalAuthenticationScheme
        };
    
        var clientSecret = configuration["Authentication:OpenId:ClientSecret"];
        if (!clientSecret.IsNullOrEmpty())
        {
            options.ClientSecret = clientSecret;
        }
    
        return options;
    }
    

    Thanks.

  • User Avatar
    0
    jhoiby created

    Thank you for the quick response!

    That looks like ASP.Net Core code, and I'm using the MVC 5.x template. However, in the interest of getting it working ANY way possible I've installed the Core template on my system and am testing with the code you supplied. If it works that will at least let me know my configuration is correct and I can proceed from there.

    The first issue I'm running into is building the code provided. I'm not able to identify what namespace the "ExternalAuthenticationScheme" object belongs to in your line:

    SignInScheme = ExternalAuthenticationScheme
    

    Neither VisualStudio or Google are helping me find what reference I need to add for that.

    Also, may I assume you left the rest of the code in AuthConfigurer.cs unchanged?

    Thank you!

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Sorry, it is different for MVC 5.x. Please try this one.

    private static OpenIdConnectAuthenticationOptions CreateOpenIdOptions()
    {
        var options = new OpenIdConnectAuthenticationOptions
        {
            Authority = ConfigurationManager.AppSettings["ExternalAuth.OpenId.Authority"],
            ClientId = ConfigurationManager.AppSettings["ExternalAuth.OpenId.ClientId"],
            PostLogoutRedirectUri = WebUrlService.WebSiteRootAddress + "Account/Logout",
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = notification =>
                {
                    var email = notification.AuthenticationTicket.Identity.Name;
                    notification.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Email, email));
                    return Task.FromResult(0);
                }
            }
        };
    
        var clientSecret = ConfigurationManager.AppSettings["ExternalAuth.OpenId.ClientSecret"];
        if (!clientSecret.IsNullOrEmpty())
        {
            options.ClientSecret = clientSecret;
        }
    
        return options;
    }
    
  • User Avatar
    0
    jhoiby created

    Hello, after having given up on this after many hours I'm trying to tackle it again. I'm getting better at OWIN debugging but I still need your help.

    When I start the solution with a clear browser cache I am sent straight to the Azure login page. After I submit the Azure credentials, the browser just keeps making looping calls over-and-over to the ABP website without displaying any page. When I trace the execution it is just re-executing the OWIN pipeline repeatedly.

    After the Azure login screen and the second pass through the OWIN pipeline, the OpenIDConnect middleware is properly setting the Identity.IsAuthenticated = true and I can see the claim info in the OWIN context, but then the pipeline just executes again and when it gets to the UseExteralSignInCookie middleware the IsAuthenticated property gets set back to false and the claims are nulled out.

    Another thing I'm noticing is that none of my breakpoints in the Account controller are ever getting hit. The Login page or ExternalLogin controller methods are never firing.

    I am using the MVC5/Angular template.

    Here is the current code I'm using for startup.cs:

    public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseAbp();
                app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login")
                });
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
                app.UseOpenIdConnectAuthentication(CreateOpenIdOptions());
                app.MapSignalR();
            }
    
            private static OpenIdConnectAuthenticationOptions CreateOpenIdOptions()
            {
                var options = new OpenIdConnectAuthenticationOptions
                {
                    Authority = ConfigurationManager.AppSettings["ExternalAuth.OpenId.Authority"],
                    ClientId = ConfigurationManager.AppSettings["ExternalAuth.OpenId.ClientId"],
                    //PostLogoutRedirectUri = WebUrlService.WebSiteRootAddress + "Account/Logout",
                    PostLogoutRedirectUri = ConfigurationManager.AppSettings["ExternalAuth.OpenId.LogoutUri"],
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        SecurityTokenValidated = notification =>
                        {
                            var email = notification.AuthenticationTicket.Identity.Name;
                            notification.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Email, email));
                            return Task.FromResult(0);
                        }
                    }
                };
    
                var clientSecret = ConfigurationManager.AppSettings["ExternalAuth.OpenId.ClientSecret"];
                if (!clientSecret.IsNullOrEmpty())
                {
                    options.ClientSecret = clientSecret;
                }
    
                return options;
            }
    
        }
    

    My web.config configuration settings:

    <add key="ExternalAuth.OpenId.Authority" value="https://login.microsoft.com/(mydomain).onmicrosoft.com/" />
    <add key="ExternalAuth.OpenId.ClientId" value="5cd0a368-(redacted)-f0a3eee24eae" />
    <add key="ExternalAuth.OpenId.LogoutUri" value="https://localhost:44305/Account/Logout" />
    

    My Azure AD configuration settings:

    Display Name: ACMETest
    Home Page: https://localhost:44305/
    Application ID: 5cd0a368-(redacted)-f0a3eee24eae
    Multi-tenanted: No (Note: ABP multi-tenancy is default ON)
    Reply URL: https://localhost:44305/Account/ExternalLoginCallback/ (I've tried several, see below)
    API Access Permissions/Keys: Default (None added or changed after initial app registration)
    

    MY QUESTIONS:

    1. What Reply URL should I be using in Azure AD? I've tried:
    https://localhost:44305/Account/Login/
    https://localhost:44305/Account/ExternalLogin/
    https://localhost:44305/Account/ExternalLoginCallback/
    https://localhost:44305/
    
    1. Does my pipeline setup look right to you?

    2. Do you have any other ideas?

    I keep seeing references in this forum to the "few lines of code needed" to get Azure OIDC working but I am never able to get it to work. If you help me get this going I would be happy to write a clear, concise step-by-step guide for posting here or in the ABP documentation!

    Thank you!

    James

    P.S. I just noticed that you have made an ASP.NET Core 1.x Angular2 template available! I've been using the MVC 5 template because it was the only one that supported Angular, but now that the new Core template is available I will try that as well.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Your configuration seems exactly the same as we use in AspNet Zero. Actually I don't remember the return url config in azure but it will try to find it.

    By the way, we use this package

    <package id="Microsoft.Owin.Security.OpenIdConnect" version="3.1.0-rc1" targetFramework="net461" />
    

    Do you use the same version ?

    Thanks.

  • User Avatar
    0
    jhoiby created

    I'm using 3.0.1 which should be compatible, but I'll try 3.1.x in the next couple of days.

    Thank you,

    James

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thanks for the update. Please let us know if it does not work.

    Thanks.