2016-03-23 26 views
2

我創建了一個託管在Azure上的MVC 5 Web應用程序和一個WPF客戶端。我的短期目標(因爲如果我能做到,我就可以實現我的所有用途的情況下)如下:將本機客戶端認證爲Azure AD遇到麻煩的AD Securised MVC Web應用程序

  • 強制的WPF客戶端
  • Azure上的廣告認證有MVC的Web應用通過天青格拉夫檢查API中的客戶端鑑別的
  • 發送回圖形API對象給客戶端的用戶的AD組成員(IUSER,組...)
  • 使用組成員對控制器定義授權

我的實際問題如下: 用戶啓動應用程序,並提示您進行身份驗證。我猜這是工作,因爲我可以顯示用戶的郵件,我有一個訪問令牌。 用戶試圖訪問一個網絡API控制器,它工作正常 用戶試圖訪問另一個網頁API控制器裝飾[授權],我得到了一些HTML頁面,說明這一點:「我們不能簽署你in.Your瀏覽器目前設置爲阻止JavaScript,您需要允許JavaScript使用此服務。「

從我發現在網上搜索它似乎可能與我的網絡應用程序沒有正確配置(我已經嘗試添加我的webapp url在受信任的站點,我敢肯定,我的控制器URL是好的)。我無法在本地客戶端+ AAD + MVC上找到很多文檔,所以我不知道如何糾正它。

這裏是我的startup.auth.cs從Web應用程序:

public partial class Startup 
{ 

    private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; 
    private static string appKey = ConfigurationManager.AppSettings["ida:AppKey"]; 
    private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; 
    private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"]; 
    private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"]; 
    private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; 
    private static string certName = ConfigurationManager.AppSettings["ida:CertName"]; 

    public static readonly string Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant); 

    string graphResourceId = ConfigurationManager.AppSettings["ida:GraphUrl"]; 

    public void ConfigureAuth(IAppBuilder app) 
    { 
     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 
     app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

     app.UseOpenIdConnectAuthentication(
      new OpenIdConnectAuthenticationOptions 
      { 

       ClientId = clientId, 
       Authority = Authority, 
       PostLogoutRedirectUri = postLogoutRedirectUri, 

       Notifications = new OpenIdConnectAuthenticationNotifications() 
       { 
        // 
        // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away. 
        // 

        AuthorizationCodeReceived = (context) => 
        { 
         var code = context.Code; 

         #region Certs (not used) 
         if (certName.Length != 0) 
         { 
          // Create a Client Credential Using a Certificate 
          // 
          // Initialize the Certificate Credential to be used by ADAL. 
          // First find the matching certificate in the cert store. 
          // 

          X509Certificate2 cert = null; 
          X509Store store = new X509Store(StoreLocation.CurrentUser); 
          try 
          { 
           store.Open(OpenFlags.ReadOnly); 
           // Place all certificates in an X509Certificate2Collection object. 
           X509Certificate2Collection certCollection = store.Certificates; 
           // Find unexpired certificates. 
           X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false); 
           // From the collection of unexpired certificates, find the ones with the correct name. 
           X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false); 
           if (signingCert.Count == 0) 
           { 
            // No matching certificate found. 
            return Task.FromResult(0); 
           } 
           // Return the first certificate in the collection, has the right name and is current. 
           cert = signingCert[0]; 
          } 
          finally 
          { 
           store.Close(); 
          } 

          // Then create the certificate credential. 
          ClientAssertionCertificate credential = new ClientAssertionCertificate(clientId, cert); 

          string userObjectID = context.AuthenticationTicket.Identity.FindFirst(
           "http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
          AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID)); 
          AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId); 
          AuthenticationHelper.token = result.AccessToken; 
         } 
         #endregion 
         else 
         { 
          // Create a Client Credential Using an Application Key 
          ClientCredential credential = new ClientCredential(clientId, appKey); 
          string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
          AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID)); 
          AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId); 
          AuthenticationHelper.token = result.AccessToken; 
         } 


         return Task.FromResult(0); 
        } 

       } 

      }); 
    } 
} 

這裏是可以在不使用[授權]裝飾被加入,但在這種情況下,動作拋出一個空的異常控制器(但如果我不能把它修好我會發布另一個問題):

[System.Web.Http.Authorize] 
public class UserADGraphController : ApiController 
{ 

    [ResponseType(typeof(IUser))] 
    [System.Web.Http.Route("api/UserADGraphController/GetMyInformations")] 
    public IHttpActionResult GetMyInformations() 
    { 
     try 
     { 
      string uID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
      if (uID == null) 
       return Ok("UId null"); 
      ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient(); 
      if (client == null) 
       return Ok("Client null"); 
      IUser adUser = client.Users.Where(u => u.ObjectId == uID).ExecuteAsync().Result.CurrentPage.SingleOrDefault(); 

      if (adUser == null) 
      { 
       return NotFound(); 
      } 

      return Ok(adUser); 
     } 
     catch (Exception e) 
     { 
      return Ok(e.Message + " " + e.StackTrace); 
     } 

終於在這裏是客戶端的相關部分:

在mainviewmodel類:

#region Azure AD auth properties 
    private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; 
    private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"]; 
    private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; 
    Uri redirectUri = new Uri(ConfigurationManager.AppSettings["ida:RedirectUri"]); 

    private static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant); 

    private static string AppServiceResourceId = ConfigurationManager.AppSettings["todo:AppServiceResourceId"]; 
    private static string AppServiceBaseAddress = ConfigurationManager.AppSettings["todo:AppServiceBaseAddress"]; 

    private HttpClient httpClient; 
    private AuthenticationContext authContext = null; 
    #endregion 

在mainviewmodel構造:

authContext = new AuthenticationContext(authority); 
httpClient = new HttpClient(); 

我的方法的標誌:

{ 
      AuthenticationResult result = null; 
      try 
      { 
       result = authContext.AcquireToken(AppServiceResourceId, clientId, redirectUri, PromptBehavior.Auto); 
       httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); 
       SignInLabelContent = "Connected to azure AD as " + result.UserInfo.DisplayableId; 

      } 
      catch (AdalException ex) 
      { 
       if (ex.ErrorCode == "user_interaction_required") 
       { 

       } 
       else 
       { 
        // An unexpected error occurred. 
        string message = ex.Message; 
        if (ex.InnerException != null) 
        { 
         message += "Inner Exception : " + ex.InnerException.Message; 
        } 
        Messenger.Default.Send<NotificationMessage>(new NotificationMessage(message)); 
        //MessageBox.Show(message); 
       } 
       return; 
      } 
     } 

訪問受保護的控制器的方法:

IUser me = null; 

      AuthenticationResult result = null; 

      result = authContext.AcquireToken(AppServiceResourceId, clientId, redirectUri, PromptBehavior.Auto); 

      string authHeader = result.CreateAuthorizationHeader(); 
      HttpClient client = new HttpClient(); 
      client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); 
      //HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AppServiceBaseAddress + "/api/UserADGraphController/GetMyInformations"); 
      //request.Headers.TryAddWithoutValidation("Authorization", authHeader); 
      //HttpResponseMessage response = await client.SendAsync(request); 
      //string responseString = await response.Content.ReadAsStringAsync(); 
      //LogManager.log(responseString); 
      //Messenger.Default.Send<NotificationMessage>(new NotificationMessage(responseString)); 

      HttpResponseMessage response = await httpClient.GetAsync(AppServiceBaseAddress + "/api/UserADGraphController/GetMyInformations"); 

      if (response.IsSuccessStatusCode) 
      { 
       var jsonString = await response.Content.ReadAsStringAsync(); 
       LogManager.log(jsonString); 
       me = JsonConvert.DeserializeObject<IUser>(jsonString); 

       //Messenger.Default.Send<NotificationMessage>(new NotificationMessage(jsonString)); 

      } 

在我的情況下的響應有狀態代碼200但是jsonString包含告訴我關於javascript禁用的網頁。

如果有人有一個想法,這將是偉大的!

謝謝!

回答

0

如果有人進入這個問題,我設法改變我的configureAuth方法這種方式來解決這個問題:

 var azureADBearerAuthOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions 
     { 
      Tenant = tenant 
     }; 

     azureADBearerAuthOptions.TokenValidationParameters = new TokenValidationParameters() 
     { 
      ValidAudience = audience 
     }; 

     app.UseWindowsAzureActiveDirectoryBearerAuthentication(azureADBearerAuthOptions); 
0

此錯誤信息是非常誤導的。我遇到了同樣的問題,並發現我的問題實際上與Client Secret/AppURI設置不匹配。

從錯誤消息中,我認爲這是我在ConfigureAuth方法中做的事情。原來我正在混合開發和測試設置。

也許這將幫助其他人最終在這個混淆錯誤信息。

相關問題