Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Supporting Individual User Accounts AND Organizational Accounts in MVC5 / ASP.Net Identity 2

I've created an ASP.Net MVC5 application, in which I have configured (and have working fine) Individual User Accounts via Google, Facebook, etc.

What I'd like to do is also support authentication against Azure Active Directory (Organizational Accounts). This would be for internal staff to be able to logon to the app as administrators.

All existing information/guides/documentation I've found typically deals with using one or the other. How would I enable them both together?

If there needs to be a separate logon form for each type of user, that would not be an issue.

EDIT:

I was looking at the Application configuration within Azure Active Directory portal, and notice that they define an "OAUTH 2.0 AUTHORIZATION ENDPOINT". Can MVC5 be configured within Startup.Auth.cs to use this?

like image 599
Brendan Green Avatar asked May 21 '14 12:05

Brendan Green


People also ask

How do I add Owin to an existing project?

Add OWIN startup and authentication configuration classesIn Solution Explorer, right-click your project, select Add, and then Add New Item. In the search text box dialog, type "owin". Name the class "Startup" and select Add.


1 Answers

I managed to implement this by doing the following:

First, adding a reference to the Microsoft.Owin.Security.OpenIdConnect Nuget package.

Second, configuring it in my Startup.Auth.cs:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    ClientId = "From the Azure Portal (see below)",
    Authority = "https://login.windows.net/<domain>.onmicrosoft.com",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        RedirectToIdentityProvider = (ctx) =>
        {
            if (ctx.Request.Path.Value.EndsWith("ExternalLogin"))
            {
                string appBasePathUrl = ctx.Request.Scheme + "://" + ctx.Request.Host + ctx.Request.PathBase;
                ctx.ProtocolMessage.RedirectUri = appBasePathUrl + "/";
                ctx.ProtocolMessage.PostLogoutRedirectUri = appBasePathUrl;
            }
            else
            {
                ctx.State = NotificationResultState.Skipped;
                ctx.HandleResponse();
            }

            return Task.FromResult(0);
        }
    },
    Description = new AuthenticationDescription
    {
        AuthenticationType = "OpenIdConnect",
        Caption = "SomeNameHere"
    }
});

Third, I setup the application in the Azure Portal (classic):

Azure Active Directory Application Configuration

Fourth, I added a separate logon page for admin users:

@using (Html.BeginForm("ExternalLogin", "Home"))
{
    @Html.AntiForgeryToken()
    <div class="ui basic segment">
        <div class="ui list">
            <div class="item">
                <button type="submit" name="provider" value="OpenIdConnect" class="left floated huge ui button social">
                    <i class="windows icon"></i>
                    <span>My Org Name</span>
                </button>
            </div>
        </div>
    </div>
}

Fifth, the ExternalLogin action doesn't need to change - we just let OWIN middleware redirect us to the external login page. The flow would then direct the user back to the ExternalLoginCallback action.

Finally, in the ExternalLoginCallback action, I check the incoming claims to determine that the login was via Azure AD, and instead of calling into ASP.NET Identity, I construct my own ClaimsIdentity, which has all my (application specific) claim information which my application recognises as an admin user.

Now, admin users navigate to https://example.com/admin, click the login button, are redirected to the Azure AD login, and windup back at the application as an admin user.

like image 148
Brendan Green Avatar answered Sep 19 '22 18:09

Brendan Green