Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for system browser on netcore #1142

Merged
merged 6 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
437 changes: 437 additions & 0 deletions LibsNetCore.sln

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
<!--<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworkMac)</TargetFrameworks>-->
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworkNetDesktop);$(TargetFrameworkNetStandard);$(TargetFrameworkNetCore);$(TargetFrameworkUap);$(TargetFrameworkIos);$(TargetFrameworkAndroid);$(TargetFrameworkMac)</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(TargetFrameworkNetStandard);$(TargetFrameworkNetCore);$(TargetFrameworkIos);$(TargetFrameworkAndroid);$(TargetFrameworkMac)</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(TargetFrameworkNetStandard);$(TargetFrameworkNetCore);</TargetFrameworks>
</PropertyGroup>
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Linux')) Or '$(NetCoreOnly)' !='' ">$(TargetFrameworkNetStandard);$(TargetFrameworkNetCore);</TargetFrameworks> </PropertyGroup>

<PropertyGroup>
<!-- The MSAL.snk has both private and public keys -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Globalization;
using Microsoft.Identity.Client.Core;
using Microsoft.Identity.Client.Internal;
using Microsoft.Identity.Client.Utils;

namespace Microsoft.Identity.Client.ApiConfig.Executors
Expand All @@ -23,10 +22,7 @@ protected AbstractExecutor(IServiceBundle serviceBundle, ClientApplicationBase c

protected RequestContext CreateRequestContextAndLogVersionInfo(Guid telemetryCorrelationId)
{
var requestContext = new RequestContext(
_clientApplicationBase.AppConfig.ClientId,
MsalLogger.Create(telemetryCorrelationId, ServiceBundle.Config),
telemetryCorrelationId);
var requestContext = new RequestContext(ServiceBundle, telemetryCorrelationId);

requestContext.Logger.Info(
string.Format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ public PublicClientExecutor(IServiceBundle serviceBundle, PublicClientApplicatio
coreUiParent.UseCorporateNetwork = _publicClientApplication.AppConfig.UseCorporateNetwork;
#endif
#endif
return ServiceBundle.PlatformProxy.GetWebUiFactory().CreateAuthenticationDialog(coreUiParent, requestContext);
bgavrilMS marked this conversation as resolved.
Show resolved Hide resolved
return ServiceBundle.PlatformProxy.GetWebUiFactory().CreateAuthenticationDialog(
coreUiParent,
requestContext);
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Identity.Client/ClientApplicationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ internal static Authority GetAuthority(IServiceBundle serviceBundle, IAccount ac
// For service calls, the request context should be created in the **Executor classes as part of request execution.
private RequestContext CreateRequestContext(Guid telemetryCorrelationId)
{
return new RequestContext(AppConfig.ClientId, MsalLogger.Create(telemetryCorrelationId, ServiceBundle.Config), telemetryCorrelationId);
return new RequestContext(ServiceBundle, telemetryCorrelationId);
}

/// <summary>
Expand Down
25 changes: 6 additions & 19 deletions src/Microsoft.Identity.Client/Core/RequestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,15 @@ namespace Microsoft.Identity.Client.Core
{
internal class RequestContext
{
public RequestContext(string clientId, ICoreLogger logger, Guid telemetryCorrelationId)
{
ClientId = string.IsNullOrWhiteSpace(clientId) ? "unset_client_id" : clientId;
Logger = logger;
TelemetryCorrelationId = telemetryCorrelationId.AsMatsCorrelationId();
}

public string TelemetryCorrelationId { get; }
public string ClientId { get; set; }
public ICoreLogger Logger { get; }
public IServiceBundle ServiceBundle { get; }

public ICoreLogger Logger { get; set; }

public static RequestContext CreateForTest(IServiceBundle serviceBundle = null)
public RequestContext(IServiceBundle serviceBundle, Guid telemetryCorrelationId)
{
var telemetryCorrelationId = Guid.NewGuid();

var logger = serviceBundle?.DefaultLogger ?? MsalLogger.Create(
telemetryCorrelationId,
null,
isDefaultPlatformLoggingEnabled: true);

return new RequestContext(null, logger, telemetryCorrelationId);
ServiceBundle = serviceBundle ?? throw new ArgumentNullException(nameof(serviceBundle));
Logger = MsalLogger.Create(telemetryCorrelationId, ServiceBundle.Config);
TelemetryCorrelationId = telemetryCorrelationId.AsMatsCorrelationId();
}
}
}
30 changes: 15 additions & 15 deletions src/Microsoft.Identity.Client/Http/HttpManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,41 @@ protected virtual HttpClient GetHttpClient()
Uri endpoint,
IDictionary<string, string> headers,
IDictionary<string, string> bodyParameters,
RequestContext requestContext)
ICoreLogger logger)
{
HttpContent body = bodyParameters == null ? null : new FormUrlEncodedContent(bodyParameters);
return await SendPostAsync(endpoint, headers, body, requestContext).ConfigureAwait(false);
return await SendPostAsync(endpoint, headers, body, logger).ConfigureAwait(false);
}

public async Task<HttpResponse> SendPostAsync(
Uri endpoint,
IDictionary<string, string> headers,
HttpContent body,
RequestContext requestContext)
ICoreLogger logger)
{
return await ExecuteWithRetryAsync(endpoint, headers, body, HttpMethod.Post, requestContext).ConfigureAwait(false);
return await ExecuteWithRetryAsync(endpoint, headers, body, HttpMethod.Post, logger).ConfigureAwait(false);
}

public async Task<HttpResponse> SendGetAsync(
Uri endpoint,
IDictionary<string, string> headers,
RequestContext requestContext)
ICoreLogger logger)
{
return await ExecuteWithRetryAsync(endpoint, headers, null, HttpMethod.Get, requestContext).ConfigureAwait(false);
return await ExecuteWithRetryAsync(endpoint, headers, null, HttpMethod.Get, logger).ConfigureAwait(false);
}

/// <summary>
/// Performs the POST request just like <see cref="SendPostAsync(Uri, IDictionary{string, string}, HttpContent, RequestContext)"/>
/// Performs the POST request just like <see cref="SendPostAsync(Uri, IDictionary{string, string}, HttpContent, ICoreLogger)"/>
/// but does not throw a ServiceUnavailable service exception. Instead, it returns the <see cref="HttpResponse"/> associated
/// with the request.
/// </summary>
public async Task<HttpResponse> SendPostForceResponseAsync(
Uri uri,
Dictionary<string, string> headers,
StringContent body,
RequestContext requestContext)
ICoreLogger logger)
{
return await ExecuteWithRetryAsync(uri, headers, body, HttpMethod.Post, requestContext, doNotThrow: true).ConfigureAwait(false);
return await ExecuteWithRetryAsync(uri, headers, body, HttpMethod.Post, logger, doNotThrow: true).ConfigureAwait(false);
}

private HttpRequestMessage CreateRequestMessage(Uri endpoint, IDictionary<string, string> headers)
Expand All @@ -95,7 +95,7 @@ private HttpRequestMessage CreateRequestMessage(Uri endpoint, IDictionary<string
IDictionary<string, string> headers,
HttpContent body,
HttpMethod method,
RequestContext requestContext,
ICoreLogger logger,
bool doNotThrow = false,
bool retry = true)
{
Expand All @@ -120,7 +120,7 @@ private HttpRequestMessage CreateRequestMessage(Uri endpoint, IDictionary<string
return response;
}

requestContext.Logger.Info(string.Format(CultureInfo.InvariantCulture,
logger.Info(string.Format(CultureInfo.InvariantCulture,
MsalErrorMessage.HttpRequestUnsuccessful,
(int)response.StatusCode, response.StatusCode));

Expand All @@ -131,7 +131,7 @@ private HttpRequestMessage CreateRequestMessage(Uri endpoint, IDictionary<string
}
catch (TaskCanceledException exception)
{
requestContext.Logger.Error("The HTTP request failed or it was canceled. " + exception.Message);
logger.Error("The HTTP request failed or it was canceled. " + exception.Message);
isRetryable = true;
timeoutException = exception;
}
Expand All @@ -140,19 +140,19 @@ private HttpRequestMessage CreateRequestMessage(Uri endpoint, IDictionary<string
{
if (retry)
{
requestContext.Logger.Info("Retrying one more time..");
logger.Info("Retrying one more time..");
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
return await ExecuteWithRetryAsync(
endpoint,
headers,
body,
method,
requestContext,
logger,
doNotThrow,
retry: false).ConfigureAwait(false);
}

requestContext.Logger.Error("Request retry failed.");
logger.Error("Request retry failed.");
if (timeoutException != null)
{
throw new MsalServiceException(
Expand Down
8 changes: 4 additions & 4 deletions src/Microsoft.Identity.Client/Http/IHttpManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ internal interface IHttpManager
Uri endpoint,
IDictionary<string, string> headers,
IDictionary<string, string> bodyParameters,
RequestContext requestContext);
ICoreLogger logger);

Task<HttpResponse> SendPostAsync(
Uri endpoint,
IDictionary<string, string> headers,
HttpContent body,
RequestContext requestContext);
ICoreLogger logger);

Task<HttpResponse> SendGetAsync(
Uri endpoint,
IDictionary<string, string> headers,
RequestContext requestContext);
ICoreLogger logger);

Task<HttpResponse> SendPostForceResponseAsync(
Uri uri,
Dictionary<string, string> headers,
StringContent body,
RequestContext requestContext);
ICoreLogger logger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public AdfsOpenIdConfigurationEndpointManager(IServiceBundle serviceBundle)
drsResponse.IdentityProviderService.PassiveAuthEndpoint.Host,
resource);

var httpResponse = await _serviceBundle.HttpManager.SendGetAsync(new Uri(webFingerUrl), null, requestContext)
var httpResponse = await _serviceBundle.HttpManager.SendGetAsync(new Uri(webFingerUrl), null, requestContext.Logger)
.ConfigureAwait(false);

if (httpResponse.StatusCode != HttpStatusCode.OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,9 @@ private void VerifyAuthorizationResult()
MsalErrorMessage.NoPromptFailedErrorMessage);
}

if (_authorizationResult.Status == AuthorizationStatus.UserCancel)
{
throw new MsalClientException(_authorizationResult.Error, _authorizationResult.ErrorDescription);
}

if (_authorizationResult.Status != AuthorizationStatus.Success)
{
throw new MsalServiceException(_authorizationResult.Error, _authorizationResult.ErrorDescription, null);
throw new MsalClientException(_authorizationResult.Error, _authorizationResult.ErrorDescription ?? "Unkown error.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private async Task<IAccount> GetSingleAccountForLoginHintAsync(string loginHint)
return accounts.First();
}

private async Task<IAccount> GetAccountFromParamsOrLoginHintAsync(AcquireTokenSilentParameters silentParameters)
private async Task<IAccount> GetAccountFromParamsOrLoginHintAsync(AcquireTokenSilentParameters silentParameters)
{
if (silentParameters.Account != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == '$(TargetFrameworkNetStandard)'">
<DefineConstants>$(DefineConstants);NETSTANDARD_RUNTIME</DefineConstants>
</PropertyGroup>
</PropertyGroup>
<ItemGroup>
<ReferenceAssemblyProjectReference Include="..\Microsoft.Identity.Client.Ref\Microsoft.Identity.Client.Ref.csproj" />
</ItemGroup>
</ItemGroup>
</Project>
22 changes: 22 additions & 0 deletions src/Microsoft.Identity.Client/MsalError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,28 @@ public static class MsalError
/// </summary>
public const string PlatformNotSupported = "platform_not_supported";

/// <summary>
/// An authorization Uri has been intercepted, but it cannot be parsed. See the log for more details.
/// </summary>
public const string InvalidAuthorizationUri = "invalid_authorization_uri";

/// <summary>
/// To use the OS browser, a loopback url must be configured. See https://aka.ms/msal-net-os-browser for details.
/// </summary>
public const string LoopbackRedirectUri = "loopback_redirect_uri";

/// <summary>
/// Error code used when the CustomWebUI has returned an uri, but it does not match the Authroity and AbsolutePath of
/// the configured redirect uri.
/// </summary>
public const string LoopbackResponseUriMisatch = "loopback_response_uri_mismatch";

/// <summary>
/// To use the default OS browser on Linux, make sure you can open a page using xdg-open tool. See https://aka.ms/msal-net-os-browser for details.
/// </summary>
public const string LinuxXdgOpen = "linux_xdg_open_failed";


#if iOS
/// <summary>
/// Xamarin.iOS specific. This error indicates that keychain access has not be enabled for the application.
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Identity.Client/MsalErrorMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public static string InvalidRedirectUriReceived(string invalidRedirectUri)

public const string CustomWebUiReturnedInvalidUri = "ICustomWebUi returned an invalid uri - it is empty or has no query.";

public static string CustomWebUiRedirectUriMismatch(string expectedUri, string actualUri)
public static string RedirectUriMismatch(string expectedUri, string actualUri)
{
return string.Format(CultureInfo.InvariantCulture, "Redirect Uri mismatch. Expected ({0}) Actual ({1})", expectedUri, actualUri);
}
Expand Down
9 changes: 6 additions & 3 deletions src/Microsoft.Identity.Client/OAuth2/OAuth2Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ internal async Task<T> ExecuteRequestAsync<T>(Uri endPoint, HttpMethod method, R
{
if (method == HttpMethod.Post)
{
response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext)
response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext.Logger)
.ConfigureAwait(false);
}
else
{
response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext).ConfigureAwait(false);
response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext.Logger).ConfigureAwait(false);
}

httpEvent.HttpResponseStatus = (int)response.StatusCode;
Expand All @@ -109,7 +109,10 @@ internal async Task<T> ExecuteRequestAsync<T>(Uri endPoint, HttpMethod method, R
if (headersAsDictionary.ContainsKey("x-ms-clitelem") &&
headersAsDictionary["x-ms-clitelem"] != null)
{
XmsCliTelemInfo xmsCliTeleminfo = new XmsCliTelemInfoParser().ParseXMsTelemHeader(headersAsDictionary["x-ms-clitelem"], requestContext);
XmsCliTelemInfo xmsCliTeleminfo = new XmsCliTelemInfoParser().ParseXMsTelemHeader(
headersAsDictionary["x-ms-clitelem"],
requestContext.Logger);

if (xmsCliTeleminfo != null)
{
httpEvent.TokenAge = xmsCliTeleminfo.TokenAge;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,25 @@
using Microsoft.Identity.Client.Core;
using Microsoft.Identity.Client.Platforms.Android.EmbeddedWebview;
using Microsoft.Identity.Client.Platforms.Android.SystemWebview;
using Microsoft.Identity.Client.PlatformsCommon.Interfaces;
using Microsoft.Identity.Client.UI;

namespace Microsoft.Identity.Client.Platforms.Android
{
[global::Android.Runtime.Preserve(AllMembers = true)]
internal class AndroidWebUIFactory : IWebUIFactory
{
public IWebUI CreateAuthenticationDialog(CoreUIParent coreUIParent, RequestContext requestContext)
public IWebUI CreateAuthenticationDialog(CoreUIParent parent, RequestContext requestContext)
{
if (coreUIParent.UseEmbeddedWebview)
if (parent.UseEmbeddedWebview)
{
return new EmbeddedWebUI(coreUIParent)
return new EmbeddedWebUI(parent)
{
RequestContext = requestContext
};
}

return new SystemWebUI(coreUIParent)
return new SystemWebUI(parent)
{
RequestContext = requestContext
};
Expand Down
Loading