diff --git a/README.md b/README.md index db11ba2c4..3ee68d768 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Active Directory Authentication Library (ADAL) provides easy to use authentication functionality for your .NET client and Windows Store apps by taking advantage of Windows Server Active Directory and Windows Azure Active Directory. Here you can find the source code for the library. You can find the corresponding releases (both stable and prerelease) on the NuGet gallery at [http://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/](http://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/). -- The latest stable release is [2.10.10910.1511](https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/). +- The latest stable release is [2.11.10918.1222](https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/). - - There is no prerelease version available at this point. - diff --git a/src/ADAL.Common/ClientMetrics.cs b/src/ADAL.Common/ClientMetrics.cs index 6b2a64b2c..77a6f6162 100644 --- a/src/ADAL.Common/ClientMetrics.cs +++ b/src/ADAL.Common/ClientMetrics.cs @@ -41,6 +41,7 @@ internal class ClientMetrics private const string ClientMetricsHeaderLastEndpoint = "x-client-last-endpoint"; private static ClientMetrics pendingClientMetrics; + private static readonly object PendingClientMetricsLock = new object(); private Stopwatch metricsTimer; private string lastError; @@ -65,9 +66,12 @@ public void EndClientMetricsRecord(string endpoint, CallState callState) lastResponseTime = metricsTimer.ElapsedMilliseconds; lastCorrelationId = callState.CorrelationId; lastEndpoint = endpoint; - if (pendingClientMetrics == null) + lock (PendingClientMetricsLock) { - pendingClientMetrics = this; + if (pendingClientMetrics == null) + { + pendingClientMetrics = this; + } } } } @@ -79,20 +83,23 @@ public void SetLastError(string[] errorCodes) private static void AddClientMetricsHeadersToRequest(IHttpWebRequest request) { - if (pendingClientMetrics != null && NetworkPlugin.RequestCreationHelper.RecordClientMetrics) + lock (PendingClientMetricsLock) { - Dictionary headers = new Dictionary(); - if (pendingClientMetrics.lastError != null) + if (pendingClientMetrics != null && NetworkPlugin.RequestCreationHelper.RecordClientMetrics) { - headers[ClientMetricsHeaderLastError] = pendingClientMetrics.lastError; - } + Dictionary headers = new Dictionary(); + if (pendingClientMetrics.lastError != null) + { + headers[ClientMetricsHeaderLastError] = pendingClientMetrics.lastError; + } - headers[ClientMetricsHeaderLastRequest] = pendingClientMetrics.lastCorrelationId.ToString(); - headers[ClientMetricsHeaderLastResponseTime] = pendingClientMetrics.lastResponseTime.ToString(); - headers[ClientMetricsHeaderLastEndpoint] = pendingClientMetrics.lastEndpoint; + headers[ClientMetricsHeaderLastRequest] = pendingClientMetrics.lastCorrelationId.ToString(); + headers[ClientMetricsHeaderLastResponseTime] = pendingClientMetrics.lastResponseTime.ToString(); + headers[ClientMetricsHeaderLastEndpoint] = pendingClientMetrics.lastEndpoint; - HttpHelper.AddHeadersToRequest(request, headers); - pendingClientMetrics = null; + HttpHelper.AddHeadersToRequest(request, headers); + pendingClientMetrics = null; + } } } } diff --git a/src/ADAL.Common/CommonAssemblyInfo.cs b/src/ADAL.Common/CommonAssemblyInfo.cs index 3a0a8eb80..96e84410c 100644 --- a/src/ADAL.Common/CommonAssemblyInfo.cs +++ b/src/ADAL.Common/CommonAssemblyInfo.cs @@ -16,6 +16,7 @@ // limitations under the License. //---------------------------------------------------------------------- +using System; using System.Reflection; [assembly: AssemblyProduct("Active Directory Authentication Library")] @@ -26,11 +27,14 @@ [assembly: AssemblyCopyright("Copyright (c) Microsoft Open Technologies. All rights reserved.")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.10.0.0")] +[assembly: AssemblyVersion("2.11.0.0")] // Keep major and minor versions in AssemblyFileVersion in sync with AssemblyVersion. // Build and revision numbers are replaced on build machine for official builds. -[assembly: AssemblyFileVersion("2.10.00000.0000")] +[assembly: AssemblyFileVersion("2.11.00000.0000")] // On official build, attribute AssemblyInformationalVersionAttribute is added as well // with its value equal to the hash of the last commit to the git branch. // e.g.: [assembly: AssemblyInformationalVersionAttribute("4392c9835a38c27516fc0cd7bad7bccdcaeab161")] + +// Assembly marked as compliant. +[assembly: CLSCompliant(true)] diff --git a/src/ADAL.Common/HttpWebRequestWrapper.cs b/src/ADAL.Common/HttpWebRequestWrapper.cs index edd58f0f5..eb86236f9 100644 --- a/src/ADAL.Common/HttpWebRequestWrapper.cs +++ b/src/ADAL.Common/HttpWebRequestWrapper.cs @@ -16,6 +16,7 @@ // limitations under the License. //---------------------------------------------------------------------- +using System; using System.IO; using System.Net; using System.Threading.Tasks; @@ -26,6 +27,8 @@ internal class HttpWebRequestWrapper : IHttpWebRequest { private readonly HttpWebRequest request; + private int timeoutInMilliSeconds = 30000; + public HttpWebRequestWrapper(string uri) { this.request = (HttpWebRequest)WebRequest.Create(uri); @@ -73,6 +76,14 @@ public WebHeaderCollection Headers } } + public int TimeoutInMilliSeconds + { + set + { + this.timeoutInMilliSeconds = value; + } + } + public async Task GetResponseSyncOrAsync(CallState callState) { if (this.BodyParameters != null) @@ -86,10 +97,42 @@ public async Task GetResponseSyncOrAsync(CallState callState) #if ADAL_NET if (callState != null && callState.CallSync) { + this.request.Timeout = this.timeoutInMilliSeconds; return NetworkPlugin.HttpWebRequestFactory.CreateResponse(this.request.GetResponse()); } + + Task getResponseTask = this.request.GetResponseAsync(); + System.Threading.ThreadPool.RegisterWaitForSingleObject( + ((IAsyncResult)getResponseTask).AsyncWaitHandle, + delegate (object state, bool timedOut) + { + if (timedOut) + { + ((HttpWebRequest)state).Abort(); + } + }, + this.request, + this.timeoutInMilliSeconds, + true); + + return NetworkPlugin.HttpWebRequestFactory.CreateResponse(await getResponseTask); +#else + var timer = Windows.System.Threading.ThreadPoolTimer.CreateTimer( + delegate + { + this.request.Abort(); + }, + TimeSpan.FromMilliseconds(this.timeoutInMilliSeconds)); + + try + { + return NetworkPlugin.HttpWebRequestFactory.CreateResponse(await this.request.GetResponseAsync()); + } + finally + { + timer.Cancel(); + } #endif - return NetworkPlugin.HttpWebRequestFactory.CreateResponse(await this.request.GetResponseAsync()); } public async Task GetRequestStreamSyncOrAsync(CallState callState) diff --git a/src/ADAL.NET.WindowsForms/SilentWindowsFormsAuthenticationDialog.cs b/src/ADAL.NET.WindowsForms/SilentWindowsFormsAuthenticationDialog.cs index ed58d237b..89bcacfcd 100644 --- a/src/ADAL.NET.WindowsForms/SilentWindowsFormsAuthenticationDialog.cs +++ b/src/ADAL.NET.WindowsForms/SilentWindowsFormsAuthenticationDialog.cs @@ -56,7 +56,7 @@ public string Result { get { - return this.result; + return this.authenticationResult; } } diff --git a/src/ADAL.NET.WindowsForms/WindowsFormsWebAuthenticationDialogBase.cs b/src/ADAL.NET.WindowsForms/WindowsFormsWebAuthenticationDialogBase.cs index b1f02e79e..e792ea812 100644 --- a/src/ADAL.NET.WindowsForms/WindowsFormsWebAuthenticationDialogBase.cs +++ b/src/ADAL.NET.WindowsForms/WindowsFormsWebAuthenticationDialogBase.cs @@ -37,7 +37,7 @@ public abstract class WindowsFormsWebAuthenticationDialogBase : Form private Uri desiredCallbackUri; - protected string result; + protected string authenticationResult; protected IWin32Window ownerWindow; @@ -171,7 +171,7 @@ private bool CheckForClosingUrl(Uri url) { if (url.Authority.Equals(this.desiredCallbackUri.Authority, StringComparison.OrdinalIgnoreCase) && url.AbsolutePath.Equals(this.desiredCallbackUri.AbsolutePath)) { - this.result = url.AbsoluteUri; + this.authenticationResult = url.AbsoluteUri; this.StopWebBrowser(); // in this handler object could be already disposed, so it should be the last method @@ -202,7 +202,7 @@ private void StopWebBrowser() public string AuthenticateAAD(Uri requestUri, Uri callbackUri) { this.desiredCallbackUri = callbackUri; - this.result = null; + this.authenticationResult = null; // The WebBrowser event handlers must not throw exceptions. // If they do then they may be swallowed by the native @@ -214,7 +214,7 @@ public string AuthenticateAAD(Uri requestUri, Uri callbackUri) this.webBrowser.Navigate(requestUri); this.OnAuthenticate(); - return this.result; + return this.authenticationResult; } protected virtual void OnAuthenticate() @@ -303,7 +303,7 @@ protected AdalException CreateExceptionForAuthenticationUiFailed(int statusCode) return new AdalServiceException( AdalError.AuthenticationUiFailed, - string.Format("The browser based authentication dialog failed to complete for an unkown reason. StatusCode: {0}", statusCode)) { StatusCode = statusCode }; + string.Format("The browser based authentication dialog failed to complete for an unknown reason. StatusCode: {0}", statusCode)) { StatusCode = statusCode }; } protected static class DpiHelper diff --git a/tests/Test.ADAL.NET.Unit/NonInteractiveTests.cs b/tests/Test.ADAL.NET.Unit/NonInteractiveTests.cs index 7b0b86b0f..78c0adf38 100644 --- a/tests/Test.ADAL.NET.Unit/NonInteractiveTests.cs +++ b/tests/Test.ADAL.NET.Unit/NonInteractiveTests.cs @@ -65,16 +65,8 @@ public async Task UserRealmDiscoveryTest() Verify.IsNotNull(ex.ErrorCode, AdalError.UnknownUser); } - try - { - await UserRealmDiscoveryResponse.CreateByDiscoveryAsync(context.Authenticator.UserRealmUri, "ab@cd@ef", null); - Verify.Fail("Exception expected"); - } - catch (AdalException ex) - { - Verify.IsNotNull(ex.ErrorCode, AdalError.UserRealmDiscoveryFailed); - Verify.IsNotNull(ex.InnerException); - } + userRealmResponse = await UserRealmDiscoveryResponse.CreateByDiscoveryAsync(context.Authenticator.UserRealmUri, "ab@cd@ef", null); + Verify.AreEqual("Unknown", userRealmResponse.AccountType); try { diff --git a/tests/Test.ADAL.NET.Unit/Test.ADAL.NET.Unit.csproj b/tests/Test.ADAL.NET.Unit/Test.ADAL.NET.Unit.csproj index 7c53c0eeb..c01943078 100644 --- a/tests/Test.ADAL.NET.Unit/Test.ADAL.NET.Unit.csproj +++ b/tests/Test.ADAL.NET.Unit/Test.ADAL.NET.Unit.csproj @@ -17,6 +17,8 @@ False UnitTest TEST_ADAL_NET + ..\..\ + true true @@ -45,7 +47,23 @@ true + + False + ..\..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll + + + False + ..\..\packages\Microsoft.Owin.Host.HttpListener.2.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll + + + False + ..\..\packages\Microsoft.Owin.Hosting.2.1.0\lib\net45\Microsoft.Owin.Hosting.dll + + + False + ..\..\packages\Owin.1.0\lib\net40\Owin.dll + @@ -137,6 +155,7 @@ valid_cert2.pfx PreserveNewest + @@ -158,6 +177,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + +