May 12, 2014 9:56:15 AM
Azure Active Directory, ADFS 3.0 and OWIN

With Windows AAD (Azure Active Directory), ADFS 3.0 (Active Directory Federation Service), and OWIN (Open Web Interface for .NET), you will find your corporate individual core identity, making connections between your corporation and the whole world for unlimited opportunities.

Currently AAD (Identity Provider and Authorization Server) supports the following identity standards:

  1. OpenId Connect
  2. OAuth2
  3. SAML-P
  4. WS-Federation and WS-Trust
  5. Graph web api

ADFS 3.0 (Identity Provider and Authorization Server) supports the following identity standards:

  1. SAML-P
  2. WS-Federation and WS-Trust
  3. OAuth2

OWIN (specification) and Katana (MS-implementation) provide reusable components for supporting identity authentication and authorization based on industry standards, such as OpenId Connect, OAuth2, WS-Federation, and OWIN components by third party communities. The subject of OWIN and Katana is great to read if you want to get into the details.

To quickly get started, one could build a single application (passive-mode Web UX and active-mode Web API) with OWIN reusable components for providing the services by authenticating and authorizing the users based on the industry standard of identity technologies.

The use cases for providing such service within this single application is as follows:

1. Support passive authentication and claims-based authorization based on WS-Federation. Any WS-Federation compliant identity providers such as AAD and ADFS in this single app.

2. Support passive authentication and authorization based on OpenId Connect. Any OpenId Connect compliant identity providers, such as AAD in this single app.

3. Support passive authentication and authorization for individual social identity, such as Facebook, Google, and Twitter in this single app.

4. Support active authentication and authorization based on OAuth2 authorization core grant flow. Any OAuth2 compliant authorization server, such as AAD and ADFS in this single app.

For this quick get- started single application, primarily based on article and related articles via links, if you like to get into the details.

As mentioned before, one could quickly and easily build a such single application by plug-in reusable OWIN authentication components to implement specific authentication and authorization scenarios.

1. Create .NET project with MVC and Web API checked. Also leave Individual User Accounts as is.

jc1

2. Install NuGet packages

PM> install-package Microsoft.IdentityModel.Protocol.Extensions –pre
PM> install-package Microsoft.Owin.Security.WsFederation –pre
PM> install-package Microsoft.Owin.Security.OpenIdConnect –pre
PM> install-package Microsoft.Owin.Security.ActiveDirectory -pre

3. Open up Startup.Auth.cs under App_Start folder to plug-in OWIN components.

public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Facebook social identity provider passive flow support
app.UseFacebookAuthentication(
appId: "xxx",
appSecret: "xxx");
// Azure OpenId Connect passive authentication and authorization support
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
Client_Id = "xxx",
Authority = "https://login.windows.net/xxx.onmicrosoft.com",
,
Post_Logout_Redirect_Uri = "http://localhost:xxxxx/",
Description = new Microsoft.Owin.Security.AuthenticationDescription
{
AuthenticationType = "OpenIdConnect",
Caption = "Azue OpenId Connect"
}
});
// Azure Ws-Fed Passive federated authentication support
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
MetadataAddress = "https://login.windows.net/xxx.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml",
Wtrealm = "http://myapp/wsfed",
});
// Azure OAuth2 active flow support
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = "http://myapp/webapi",
Tenant = "xxx.onmicrosoft.com",
AuthenticationType = "OAuth2Bearer",
});
// ADFS OAuth2 active flow support
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
Audience = "http://myapp/webapi",
MetadataEndpoint = "https://xxx/federationmetadata/2007-06/federationmetadata.xml"
});
}
}

CookieAuthentication and ExternalSignInCookie – OWIN components to support cookie-based authentication

FacebookAuthentication – OWIN component to support Facebook social identity provider passive flow

OpenIdConnectAuthentication – OWIN component to support Azure OpenId Connect passive authentication and authorization

WsFederationAuthentication – OWIN component to support AAD Ws-Fed Passive federated authentication

WindowsAzureActiveDirectoryBearerAuthentication – OWIN component to support AAD OAuth2 authorization code grant active flow

ActiveDirectoryFederationServicesBearerAuthentication – OWIN component to support ADFS OAuth2 authorization code grant active flow

4. Build and Run, and click Log in from home page.

You will see 3 buttons under “Use another service to log in”

Federation – WsFederationAuthentication starts passive WS-Federation authentication flow when user clicks the button.

Facebook – FacebookAuthentication starts Facebook login passive flow.

OpenId Connect - OpenIdConnectAuthentication starts Azure OpenId Connect passive authentication and authorization.

jc2

5. Implement Web UX which can be consumed by user through passive authentication flow, such as OpenId Connect, WS-Federation, and Social Identity federation.

Add controller by selecting “MVC 5 Controller – Empty."

jc3

public class MvcValuesController : Controller {     //     // GET: /MvcValues/     public string Index()     {         if (!Request.IsAuthenticated)         {             return "You are not authenticated";         }         else         {             var ctx = Request.GetOwinContext();             ClaimsPrincipal user = ctx.Authentication.User;             return user.Identity.Name;         }     }

Once you login by clicking on any button under “Use another service to log in”, access http://localhost:xxxxx/mvcvalues

6. Now Implement Web API which can be consumed by native client through active authentication flow, such as OAuth2 including OpenId Connect which is built on top of OAuth2.

Add controller by selecting “Web API 2 Controller - Empty."

jc4

public class ValuesController : ApiController {     // GET api/values     [HostAuthentication("OAuth2Bearer")]     [Authorize]     public IEnumerable&lt;string&gt; Get()     {         return (((ClaimsPrincipal)Thread.CurrentPrincipal).Claims.Select(c =&gt; c.Value));         //return new string[] { "value1", "value2" };     } } 7. Build native client (for instance Console application) to test active flow by accessing <a href="http://localhost:xxxxx/api/values">http://localhost:xxxxx/api/values</a> class Program {     static void Main(string[] args)     {         AuthenticationContext ac =             new AuthenticationContext("https://login.windows.net/xxx.onmicrosoft.com");         AuthenticationResult ar =             ac.AcquireToken("http://myapp/webapi",                             "8d9a9a6a-xxxx-xxxx-xxxx-5d25df4d7ca0",                             new Uri("http://any"));         string result = string.Empty;         HttpClient httpClient = new HttpClient();         httpClient.DefaultRequestHeaders.Authorization =             new AuthenticationHeaderValue("Bearer", ar.AccessToken);         HttpResponseMessage response =             httpClient.GetAsync("http://localhost:xxxxx/api/values").Result;         if (response.IsSuccessStatusCode)         {             result = response.Content.ReadAsStringAsync().Result;         }         Console.WriteLine(result);         Console.ReadLine();     } }

7. Build native client (for instance Console application) to test active flow by accessing http://localhost:xxxxx/api/values

class Program
{
    static void Main(string[] args)
    {
        AuthenticationContext ac =
            new AuthenticationContext("https://login.windows.net/xxx.onmicrosoft.com");
        AuthenticationResult ar =
            ac.AcquireToken("http://myapp/webapi",
                            "8d9a9a6a-xxxx-xxxx-xxxx-5d25df4d7ca0",
                            new Uri("http://any"));

        string result = string.Empty;
        HttpClient httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", ar.AccessToken);
        HttpResponseMessage response =
            httpClient.GetAsync("http://localhost:xxxxx/api/values").Result;

        if (response.IsSuccessStatusCode)
        {
            result = response.Content.ReadAsStringAsync().Result;
        }
        Console.WriteLine(result);
        Console.ReadLine();
    }
}