asp.net-mvcasp.net-web-apiadfs2.1

Securing a Web API with Windows Server 2012 R2 ADFS 3.0 and Katana


I would like to make a MVC Web Application that talks to a Web API application and use ADFS 3.0 (on Windows 2012 R2) for authentication.

I managed to make the MVC Web Application to authenticate using ADFS. and configured everything as shown in this article by Vittorio Bertocci

http://www.cloudidentity.com/blog/2013/10/25/securing-a-web-api-with-adfs-on-ws2012-r2-got-even-easier/

Now I use the latest pre release of AAL from nuget

Now after authenticating with ADFS from web MVC app, I try to call the webapi

public async Task<String> CallSecuredAPI()
        {
            string authority = "https://fs.domain.com/adfs";
            string resourceURI = "https://{hostheader}/SecuredAPI";
            string clientID = "ExternalWebSite1";
            string clientReturnURI = "https://{hostheader}/ExternalSite";

            AuthenticationContext ac = new AuthenticationContext(authority, false);
            AuthenticationResult ar = ac.AcquireToken(resourceURI, clientID, new   Uri(clientReturnURI));

            string authHeader = ar.CreateAuthorizationHeader();
            var client = new HttpClient();
            HttpRequestMessage request =
                new HttpRequestMessage(HttpMethod.Get, "https://hostheader/SecuredAPI/api/Claims");
            request.Headers.TryAddWithoutValidation("Authorization", authHeader);
            HttpResponseMessage response = await client.SendAsync(request);
            string responseString = await response.Content.ReadAsStringAsync();
            return responseString;
        }

but I get this error which I think is with the client not being a UI based client or WPF , windows App. Can someone let me know whether I am doing something wrong.

![Error when trying to get Authorization code using AAL][1]

Server Error in '/ExternalSite' Application.

Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.

Source Error: 


Line 43: 
Line 44:             AuthenticationContext ac = new AuthenticationContext(authority, false);
Line 45:             AuthenticationResult ar = ac.AcquireToken(resourceURI, clientID, new Uri(clientReturnURI));
Line 46:             
Line 47:             string authHeader = ar.CreateAuthorizationHeader();

Source File: c:\Users\balakrishna.takkalla\Documents\Visual Studio 2013\Projects\ExternalSite\ExternalSite\Controllers\HomeController.cs    Line: 45 

Stack Trace: 


[InvalidOperationException: Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.]
   System.Windows.Forms.Form.ShowDialog(IWin32Window owner) +5701502
   Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.WindowsFormsWebAuthenticationDialog.ShowBrowser() +18
   Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.WindowsFormsWebAuthenticationDialog.OnAuthenticate() +23
   Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.WindowsFormsWebAuthenticationDialogBase.AuthenticateAAD(Uri requestUri, Uri callbackUri) +284
   Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.InteractiveWebUI.OnAuthenticate() +103
   Microsoft.IdentityModel.Clients.ActiveDirectory.OAuth2Request.SendAuthorizeRequest(Authenticator authenticator, String resource, Uri redirectUri, String clientId, String userId, PromptBehavior promptBehavior, String extraQueryParameters, IWebUI webUi, CallState callState) +363
   Microsoft.IdentityModel.Clients.ActiveDirectory.<>c__DisplayClass9b.<AcquireAuthorization>b__9a() +111
   System.Threading.Tasks.Task.Execute() +110

Solution

  • if I understood correctly: you want to access a Web API from the code-behind of an MVC application. That topology is possible with Azure Active Directory today, you can see that in action in the sample https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet (I am in the process of updating it to the latest ADAL refresh, you can take a peek at the RCUpdate branch to see the work in progress).

    However that topology is NOT achievable today from ADFS WS2012 R2. The reason is that an MVC app (and any other web site) is a confidential client, which OAuth2 handles differently from a public client (the WPF app you used as a starting point is a public client). In the scenario you are targeting, to use ADAL for getting a token from a confidential client you would use ADAL's method AcquireTokenByAuthorizationCode (see the sample I mentioned). However ADFS WS2012 R2 is incapable of processing that method. Today the OAuth2 support in ADFS WS2012 R2 is limited to public clients only.

    Sorry for bringing bad news! As a mitigation, you might consider federating your ADFS with an AAD tenant: at that point you would be able to do what you want, authenticating as an ADFS user but getting tokens from AAD (which does support the necessary OAuth2 grant). HTH V.