private async Task <MsalTokenResponse> AcquireBasicTokenSilentAsync( WebAccount webAccount, string clientId) { // we checked that it exists previously _wamProxy.TryGetAccountProperty(webAccount, "Authority", out string accountAuthority); var provider = await _webAccountProviderFactory.GetAccountProviderAsync(accountAuthority).ConfigureAwait(false); // We are not requesting any additional scopes beyond "profile" and "openid" (which are added by default) // since we do not want to require any additional claims (and thus be unable to renew the refresh token). var request = await CreateWebTokenRequestAsync(provider, clientId, "profile openid").ConfigureAwait(false); // Note that this is never a guest flow, we are always acquiring a token for the home realm, // since we only need the client info. var wamResult = await _wamProxy.GetTokenSilentlyAsync(webAccount, request).ConfigureAwait(false); if (!wamResult.ResponseStatus.IsSuccessStatus()) { _logger.Warning($"[WAM AAD Provider] GetIdFromWebResponseAsync failed {wamResult.ResponseStatus} - {wamResult.ResponseError}"); return(null); } return(ParseSuccessfullWamResponse(wamResult.ResponseData[0], out _)); }
private async Task <string> FetchMsaPassthroughTransferTokenAsync( AuthenticationRequestParameters authenticationRequestParameters, WebAccountProvider accountProvider) { try { // step 1 - get a response from the MSA provider, just to have a WebAccount _logger.Info("WAM MSA-PT: Making initial call to MSA provider"); WebAccount msaPtWebAccount = await TryFetchWebAccountFromMsaAsync( authenticationRequestParameters, accountProvider).ConfigureAwait(false); if (msaPtWebAccount != null) { // step 2 - get a trasnfer token _logger.Info("WAM MSA-PT: Getting transfer token"); string transferToken = await FetchTransferTokenAsync( accountProvider, msaPtWebAccount, authenticationRequestParameters.AppConfig.ClientId).ConfigureAwait(true); return(transferToken); } return(null); } catch (Exception ex) { _logger.Warning("WAM MSA-PT: Getting a transfer token failed " + ex); return(null); } }
public async Task <IEnumerable <IAccount> > GetAccountsAsync(string clientID, string redirectUri) { using (_logger.LogMethodDuration()) { if (!IsBrokerInstalledAndInvokable()) { _logger.Warning("Android broker is either not installed or is not reachable so no accounts will be returned. "); return(new List <IAccount>()); } BrokerRequest brokerRequest = new BrokerRequest() { ClientId = clientID, RedirectUri = new Uri(redirectUri) }; try { await _brokerHelper.InitiateBrokerHandshakeAsync(_parentActivity).ConfigureAwait(false); return(_brokerHelper.GetBrokerAccountsInAccountManager(brokerRequest)); } catch (Exception ex) { _logger.Error("Failed to get Android broker accounts from the broker. "); HandleBrokerOperationError(ex); throw; } } }
public async Task <WebTokenRequest> CreateWebTokenRequestAsync( WebAccountProvider provider, AuthenticationRequestParameters authenticationRequestParameters, bool isForceLoginPrompt, bool isInteractive, bool isAccountInWam) { bool setLoginHint = false; bool addNewAccount = false; string loginHint = authenticationRequestParameters.LoginHint ?? authenticationRequestParameters.Account?.Username; if (isInteractive && !isAccountInWam) { if (!string.IsNullOrEmpty(loginHint)) { setLoginHint = true; } else { addNewAccount = !(await _webAccountProviderFactory.IsDefaultAccountMsaAsync().ConfigureAwait(false)); } } var promptType = (setLoginHint || addNewAccount || (isForceLoginPrompt && isInteractive)) ? WebTokenRequestPromptType.ForceAuthentication : WebTokenRequestPromptType.Default; string scopes = ScopeHelper.GetMsalScopes(authenticationRequestParameters.Scope).AsSingleString(); WebTokenRequest request = new WebTokenRequest( provider, scopes, authenticationRequestParameters.ClientId, promptType); if (addNewAccount || setLoginHint) { request.Properties.Add("Client_uiflow", "new_account"); // launch add account flow if (setLoginHint) { request.Properties.Add("LoginHint", loginHint); // prefill username } } request.Properties.Add("api-version", "2.0"); // request V2 tokens over V1 request.Properties.Add("oauth2_batch", "1"); // request tokens as OAuth style name/value pairs request.Properties.Add("x-client-info", "1"); // request client_info if (ApiInformation.IsPropertyPresent("Windows.Security.Authentication.Web.Core.WebTokenRequest", "CorrelationId")) { request.CorrelationId = authenticationRequestParameters.CorrelationId.ToString(); } else { _logger.Warning("[WAM MSA Plugin] Could not add the correlation ID to the request."); } return(request); }
public async Task <Uri> ListenToSingleRequestAndRespondAsync( int port, Func <Uri, MessageAndHttpCode> responseProducer, CancellationToken cancellationToken) { TestBeforeTopLevelCall?.Invoke(); cancellationToken.ThrowIfCancellationRequested(); HttpListener httpListener = null; try { string urlToListenTo = "http://localhost:" + port + "/"; httpListener = new HttpListener(); httpListener.Prefixes.Add(urlToListenTo); TestBeforeStart?.Invoke(); httpListener.Start(); _logger.Info("Listening for authorization code on " + urlToListenTo); using (cancellationToken.Register(() => { _logger.Warning("HttpListener stopped because cancellation was requested."); TryStopListening(httpListener); })) { TestBeforeGetContext?.Invoke(); HttpListenerContext context = await httpListener.GetContextAsync() .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); Respond(responseProducer, context); _logger.Verbose("HttpListner received a message on " + urlToListenTo); // the request URL should now contain the auth code and pkce return(context.Request.Url); } } catch (ObjectDisposedException) { // If cancellation is requested before GetContextAsync is called // then an ObjectDisposedException is fired by GetContextAsync. // This is still just cancellation _logger.Warning("ObjectDisposedException - cancellation requested? " + cancellationToken.IsCancellationRequested); cancellationToken.ThrowIfCancellationRequested(); throw; } finally { TryStopListening(httpListener); } }
public async Task <string> GetBrokerAuthTokenSilentlyAsync(BrokerRequest brokerRequest, Activity callerActivity) { CheckForBrokerAccountInfoInAccountManager(brokerRequest, callerActivity); Bundle silentOperationBundle = CreateSilentBrokerBundle(brokerRequest); silentOperationBundle.PutString(BrokerConstants.BrokerAccountManagerOperationKey, BrokerConstants.AcquireTokenSilent); IAccountManagerFuture result = _androidAccountManager.AddAccount(BrokerConstants.BrokerAccountType, BrokerConstants.AuthtokenType, null, silentOperationBundle, null, null, GetPreferredLooper(callerActivity)); if (result != null) { Bundle bundleResult = null; try { bundleResult = (Bundle)await result.GetResultAsync( AccountManagerTimeoutSeconds, TimeUnit.Seconds) .ConfigureAwait(false); } catch (OperationCanceledException ex) { _logger.Error("An error occurred when trying to communicate with the account manager: " + ex.Message); } catch (Exception ex) { throw new MsalClientException(MsalError.BrokerApplicationRequired, MsalErrorMessage.AndroidBrokerCannotBeInvoked, ex); } string responseJson = bundleResult.GetString(BrokerConstants.BrokerResultV2); bool success = bundleResult.GetBoolean(BrokerConstants.BrokerRequestV2Success); _logger.Info($"Android Broker Silent call result - success? {success}. "); if (!success) { _logger.Warning($"Android Broker Silent call failed. " + $"This usually means that the RT cannot be refreshed and interaction is required. " + $"BundleResult: {bundleResult} Result string: {responseJson}"); } // upstream logic knows how to extract potential errors from this result return(responseJson); } _logger.Info("Android Broker didn't return any results. "); return(null); }
private async Task <RegionInfo> DiscoverAsync(ICoreLogger logger, CancellationToken requestCancellationToken) { string region = Environment.GetEnvironmentVariable("REGION_NAME"); if (ValidateRegion(region, "REGION_NAME env variable", logger)) // this is just to validate the region string { logger.Info($"[Region discovery] Region found in environment variable: {region}."); return(new RegionInfo(region, RegionAutodetectionSource.EnvVariable)); } try { var headers = new Dictionary <string, string> { { "Metadata", "true" } }; Uri imdsUri = BuildImdsUri(DefaultApiVersion); HttpResponse response = await _httpManager.SendGetAsync(imdsUri, headers, logger, retry : false, GetCancellationToken(requestCancellationToken)) .ConfigureAwait(false); // A bad request occurs when the version in the IMDS call is no longer supported. if (response.StatusCode == HttpStatusCode.BadRequest) { string apiVersion = await GetImdsUriApiVersionAsync(logger, headers, requestCancellationToken).ConfigureAwait(false); // Get the latest version imdsUri = BuildImdsUri(apiVersion); response = await _httpManager.SendGetAsync(BuildImdsUri(apiVersion), headers, logger, retry : false, GetCancellationToken(requestCancellationToken)) .ConfigureAwait(false); // Call again with updated version } if (response.StatusCode == HttpStatusCode.OK && !response.Body.IsNullOrEmpty()) { region = response.Body; if (ValidateRegion(region, $"IMDS call to {imdsUri.AbsoluteUri}", logger)) { logger.Info($"[Region discovery] Call to local IMDS succeeded. Region: {region}."); return(new RegionInfo(region, RegionAutodetectionSource.Imds)); } } else { logger.Warning($"[Region discovery] Call to local IMDS failed with status code {response.StatusCode} or an empty response."); } } catch (Exception e) { if (e is MsalServiceException msalEx && MsalError.RequestTimeout.Equals(msalEx?.ErrorCode)) { logger.Warning($"[Region discovery] Call to local IMDS timed out after {_imdsCallTimeoutMs}."); }
public async Task <IReadOnlyList <IAccount> > GetAccountsAsync( string clientId, string redirectUri, AuthorityInfo authorityInfo, ICacheSessionManager cacheSessionManager, IInstanceDiscoveryManager instanceDiscoveryManager) { using (_logger.LogMethodDuration()) { if (!IsBrokerInstalledAndInvokable()) { _logger.Warning("[Android broker] Broker is either not installed or is not reachable so no accounts will be returned. "); return(null); } return(await GetAccountsInternalAsync(clientId, redirectUri).ConfigureAwait(false)); } }
public bool IsBrokerInstalledAndInvokable(AuthorityType authorityType) { if (!DesktopOsHelper.IsWin10OrServerEquivalent()) { _logger.Warning("[WAM Broker] Not a supported operating system. WAM broker is not available. "); return(false); } // WAM does not work on pure ADFS environments if (authorityType == AuthorityType.Adfs) { _logger.Warning("[WAM Broker] WAM does not work in pure ADFS environments. Falling back to browser for an ADFS authority. "); return(false); } _logger.Verbose("[WAM Broker] IsBrokerInstalledAndInvokable true"); return(true); }
public string GetSilentResultFromBundle(Bundle bundleResult) { string responseJson = bundleResult.GetString(BrokerConstants.BrokerResultV2); bool success = bundleResult.GetBoolean(BrokerConstants.BrokerRequestV2Success); _logger.Info($"[Android broker] Silent call result - success? {success}. "); if (!success) { _logger.Warning($"[Android broker] Silent call failed. " + $"This usually means that the RT cannot be refreshed and interaction is required. " + $"BundleResult: {bundleResult} Result string: {responseJson}"); } // upstream logic knows how to extract potential errors from this result return(responseJson); }
public void WriteValueToTag(string tagname, object value) { var currentTag = Collection.GetReadTagWithName(tagname); if (currentTag == null) { logger.Warning(null, $"{Name}({Ip}) device write error. Tag not found : {tagname}"); return; } logger.Trace($"{Name}({Ip}) device write. Tag name : {currentTag?.Name} Tag Value : {value}"); if (isdeviceConnected) { WriteTagHelper(currentTag, value); } else { logger.Warning(null, $"{Name}({Ip}) device not connected. Tag not written : {tagname} "); } }
internal XmsCliTelemInfo ParseXMsTelemHeader(string headerValue, ICoreLogger logger) { if (string.IsNullOrEmpty(headerValue)) { return(null); } string[] headerSegments = headerValue.Split(','); if (headerSegments.Length == 0) { logger.Warning( FormatLogMessage(TelemetryError.XmsCliTelemMalformed, headerValue)); return(null); } string headerVersion = headerSegments[0]; XmsCliTelemInfo xMsTelemetryInfo = new XmsCliTelemInfo { Version = headerVersion }; if (!string.Equals(headerVersion, ExpectedCliTelemHeaderVersion)) { logger.Warning( FormatLogMessage(TelemetryError.XmsUnrecognizedHeaderVersion, headerVersion)); return(xMsTelemetryInfo); } MatchCollection formatMatcher = MatchHeaderToExpectedFormat(headerValue); if (formatMatcher.Count < 1) { logger.Warning( FormatLogMessage(TelemetryError.XmsCliTelemMalformed, headerValue)); return(xMsTelemetryInfo); } xMsTelemetryInfo.ServerErrorCode = headerSegments[ErrorCodeIndex]; xMsTelemetryInfo.ServerSubErrorCode = headerSegments[SubErrorCodeIndex]; xMsTelemetryInfo.TokenAge = headerSegments[TokenAgeIndex]; xMsTelemetryInfo.SpeInfo = headerSegments[SpeInfoIndex]; return(xMsTelemetryInfo); }
private bool Connect() { if (master != null) { master.Dispose(); } if (tcpClient != null) { tcpClient.Close(); } if (CheckInternet()) { try { tcpClient = new TcpClient(); IAsyncResult asyncResult = tcpClient.BeginConnect(IpAddress, ModbusPort, null, null); asyncResult.AsyncWaitHandle.WaitOne(3000, true); //wait for 3 sec if (!asyncResult.IsCompleted) { tcpClient.Close(); logger.Warning(null, $"Not connecting to server - {IpAddress}"); return(false); } // create Modbus TCP Master by the tcpclient master = ModbusIpMaster.CreateIp(tcpClient); master.Transport.Retries = 0; //don't have to do retries //master.Transport.ReadTimeout = 1500; logger.Info($"Connected to server - {IpAddress}"); isreading = false; return(tcpClient.Connected); } catch (Exception ex) { logger.Warning(ex, "Connection error"); return(false); } } return(false); }
new internal void Add(string devicename, Device device) { if (ContainsKey(devicename)) { logger.Warning(null, $"Device already added - {devicename}"); return; } base.Add(devicename, device); device.ConnectionStatusChanged += Device_ConnectionStatusChanged; device.Collection.TagStatusChanged += delegate(Tag sender, object value, bool quality) { TagStatusChanged?.Invoke(sender, value, quality); }; }
private async Task <WebAccount> FindWamAccountForMsalAccountAsync( WebAccountProvider provider, IWamPlugin wamPlugin, IAccount msalAccount, string loginHint, string clientId) { if (msalAccount == null && string.IsNullOrEmpty(loginHint)) { return(null); } Account accountInternal = (msalAccount as Account); if (accountInternal?.WamAccountIds != null && accountInternal.WamAccountIds.TryGetValue(clientId, out string wamAccountId)) { _logger.Info("WAM will try to find an account based on the WAM account id from the cache"); WebAccount result = await _wamProxy.FindAccountAsync(provider, wamAccountId).ConfigureAwait(false); if (result != null) { return(result); } _logger.Warning("WAM account was not found for given WAM account id."); } var wamAccounts = await _wamProxy.FindAllWebAccountsAsync(provider, clientId).ConfigureAwait(false); return(MatchWamAccountToMsalAccount( wamPlugin, msalAccount, loginHint, wamAccounts)); }
public async Task <IReadOnlyList <IAccount> > GetAccountsAsync( string clientId, string redirectUri, AuthorityInfo authorityInfo, ICacheSessionManager cacheSessionManager, IInstanceDiscoveryManager instanceDiscoveryManager) { using (_logger.LogMethodDuration()) { if (!IsBrokerInstalledAndInvokable()) { _logger.Warning("[Android broker] Broker is either not installed or is not reachable so no accounts will be returned. "); return(new List <IAccount>()); } BrokerRequest brokerRequest = new BrokerRequest() { ClientId = clientId, RedirectUri = new Uri(redirectUri) }; try { await InitiateBrokerHandshakeAsync().ConfigureAwait(false); var accounts = GetBrokerAccounts(brokerRequest); return(_brokerHelper.ExtractBrokerAccountsFromAccountData(accounts)); } catch (Exception ex) { _logger.Error("[Android broker] Failed to get Android broker accounts from the broker. "); _brokerHelper.HandleBrokerOperationError(ex); throw; } } }
public static IDictionary <AdalTokenCacheKey, AdalResultWrapper> Deserialize(ICoreLogger logger, byte[] state) { IDictionary <AdalTokenCacheKey, AdalResultWrapper> dictionary = new Dictionary <AdalTokenCacheKey, AdalResultWrapper>(); if (state == null || state.Length == 0) { return(dictionary); } using (Stream stream = new MemoryStream()) { BinaryWriter writer = new BinaryWriter(stream); writer.Write(state); writer.Flush(); stream.Position = 0; BinaryReader reader = new BinaryReader(stream); int blobSchemaVersion = reader.ReadInt32(); if (blobSchemaVersion != SchemaVersion) { logger.Warning("The version of the persistent state of the cache does not match the current schema, so skipping deserialization."); return(dictionary); } int count = reader.ReadInt32(); for (int n = 0; n < count; n++) { string keyString = reader.ReadString(); string[] kvpElements = keyString.Split(new[] { Delimiter }, StringSplitOptions.None); AdalResultWrapper resultEx = AdalResultWrapper.Deserialize(reader.ReadString()); AdalTokenCacheKey key = new AdalTokenCacheKey(kvpElements[0], kvpElements[1], kvpElements[2], (TokenSubjectType)int.Parse(kvpElements[3], CultureInfo.CurrentCulture), resultEx.Result.UserInfo); dictionary.Add(key, resultEx); } logger.Info(string.Format(CultureInfo.CurrentCulture, "Deserialized {0} items to token cache.", count)); } return(dictionary); }
new internal void Add(string devicename, Device device) { if (ContainsKey(devicename)) { logger.Warning(null, $"Device already added - {devicename}"); return; } base.Add(devicename, device); device.ConnectionStatusChanged += Device_ConnectionStatusChanged; device.Collection.TagStatusChanged += (sender, e) => { if (sender is Tag tag) { TagStatusChanged?.Invoke(this, new TagChangedEventArgs { Name = tag.Name, Value = tag.Value, Quality = tag.Quality }); } }; }
public static long GetDurationFromWindowsTimestamp(string windowsTimestampInFuture, ICoreLogger logger) { if (string.IsNullOrEmpty(windowsTimestampInFuture)) { return(0); } if (!ulong.TryParse(windowsTimestampInFuture, out ulong winTimestamp) || winTimestamp <= 11644473600 || winTimestamp == ulong.MaxValue) { logger.Warning("Invalid Universal time " + windowsTimestampInFuture); return(0); } ulong unixTimestamp = winTimestamp - 11644473600; return((long)unixTimestamp - CurrDateTimeInUnixTimestamp()); }
public async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken) { if (!Broker.IsBrokerInstalledAndInvokable(_authenticationRequestParameters.AuthorityInfo.AuthorityType)) { _logger.Warning("Broker is not installed. Cannot respond to silent request."); return(null); } MsalTokenResponse response = await SendTokenRequestToBrokerAsync().ConfigureAwait(false); if (response != null) { ValidateResponseFromBroker(response); Metrics.IncrementTotalAccessTokensFromBroker(); return(await _silentRequest.CacheTokenResponseAndCreateAuthenticationResultAsync(response).ConfigureAwait(false)); } return(null); }
/// <summary> /// Parse Native Interop AuthResult Response to MSAL Token Response /// </summary> /// <param name="authResult"></param> /// <param name="authenticationRequestParameters"></param> /// <param name="logger"></param> /// <exception cref="MsalServiceException"></exception> public static MsalTokenResponse ParseRuntimeResponse( NativeInterop.AuthResult authResult, AuthenticationRequestParameters authenticationRequestParameters, ICoreLogger logger) { try { string expiresOn = authResult.ExpiresOn.ToString(); string correlationId = authenticationRequestParameters.CorrelationId.ToString("D"); if (string.IsNullOrWhiteSpace(correlationId)) { logger.Warning("No correlation ID in response"); correlationId = null; } //parsing Pop token from auth header if pop was performed. Otherwise use access token field. var token = authResult.IsPopAuthorization ? authResult.AuthorizationHeader.Split(' ')[1] : authResult.AccessToken; MsalTokenResponse msalTokenResponse = new MsalTokenResponse() { AccessToken = token, IdToken = authResult.RawIdToken, CorrelationId = correlationId, Scope = authResult.GrantedScopes, ExpiresIn = DateTimeHelpers.GetDurationFromWindowsTimestamp(expiresOn, logger), ClientInfo = authResult.Account.ClientInfo.ToString(), TokenType = authResult.IsPopAuthorization ? Constants.PoPAuthHeaderPrefix : BrokerResponseConst.Bearer, WamAccountId = authResult.Account.Id, TokenSource = TokenSource.Broker }; logger.Info("WAM response status success"); return(msalTokenResponse); } catch (NativeInterop.MsalRuntimeException ex) { throw new MsalServiceException("wam_failed", $"Could not acquire token using WAM. {ex.Message}"); } }
private bool VerifyAuthenticator() { // there may be multiple authenticators from same package // , but there is only one entry for an authenticator type in // AccountManager. // If another app tries to install same authenticator type, it will // queue up and will be active after first one is uninstalled. AuthenticatorDescription[] authenticators = _androidAccountManager.GetAuthenticatorTypes(); foreach (AuthenticatorDescription authenticator in authenticators) { if (authenticator.Type.Equals(BrokerConstants.BrokerAccountType, StringComparison.OrdinalIgnoreCase) && VerifySignature(authenticator.PackageName)) { _logger.Verbose("Found the Authenticator on the device"); return(true); } } _logger.Warning("No Authenticator found on the device."); return(false); }
public static long GetDurationFromWindowsTimestamp(string windowsTimestampInFuture, ICoreLogger logger) { if (string.IsNullOrEmpty(windowsTimestampInFuture)) { return(0); } // Windows uses in most functions the FILETIME structure, which represents the actual time as the number of 100-nanosecond intervals since January 1, 1601 (UTC). // To convert to unix timestamp (Jan 1, 1970), you have to substract 11644473600 seconds. if (!ulong.TryParse(windowsTimestampInFuture, out ulong winTimestamp) || winTimestamp <= 11644473600 || winTimestamp == ulong.MaxValue) { logger.Warning("Invalid Universal time " + windowsTimestampInFuture); return(0); } ulong unixTimestamp = winTimestamp - 11644473600; return((long)unixTimestamp - CurrDateTimeInUnixTimestamp()); }
internal /* internal for testing only */ MessageAndHttpCode GetResponseMessage(Uri authCodeUri) { // Parse the uri to understand if an error was returned. This is done just to show the user a nice error message in the browser. var authorizationResult = AuthorizationResult.FromUri(authCodeUri.OriginalString); if (!string.IsNullOrEmpty(authorizationResult.Error)) { _logger.Warning($"Default OS Browser intercepted an Uri with an error: " + $"{authorizationResult.Error} {authorizationResult.ErrorDescription}"); string errorMessage = string.Format( CultureInfo.InvariantCulture, _webViewOptions?.HtmlMessageError ?? DefaultFailureHtml, authorizationResult.Error, authorizationResult.ErrorDescription); return(GetMessage(_webViewOptions?.BrowserRedirectError, errorMessage)); } return(GetMessage( _webViewOptions?.BrowserRedirectSuccess, _webViewOptions?.HtmlMessageSuccess ?? DefaultSuccessHtml)); }
private string ExtractTransferToken( string clientId, IWebTokenRequestResultWrapper transferResponse, bool isInteractive) { if (!transferResponse.ResponseStatus.IsSuccessStatus()) { try { _ = WamAdapters.CreateMsalResponseFromWamResponse( transferResponse, _msaPlugin, clientId, _logger, isInteractive: isInteractive); } catch (MsalServiceException exception) { _logger.Warning( "WAM MSA-PT: could not get a transfer token, ussually this is because the " + "1st party app is configured for MSA-PT but not configured to login MSA users (signinaudience =2). " + "Error was: " + exception.ErrorCode + " " + exception.Message); } return(null); } _ = _msaPlugin.ParseSuccessfullWamResponse(transferResponse.ResponseData[0], out var properties); properties.TryGetValue("code", out string code); // Important: cannot use this WebAccount with the AAD provider WebAccount msaPtWebAccount = transferResponse.ResponseData[0].WebAccount; _logger.InfoPii($"Obtained a transfer token for {msaPtWebAccount.UserName} ? {code != null}", $"Obtained a transfer token? {code != null}"); return(code); }
public MsalTokenResponse ParseSuccesfullWamResponse(WebTokenResponse webTokenResponse) { if (!webTokenResponse.Properties.TryGetValue("TokenExpiresOn", out string expiresOn)) { _logger.Warning("Result from WAM does not have expiration. Marking access token as expired."); expiresOn = null; } if (!webTokenResponse.Properties.TryGetValue("ExtendedLifetimeToken", out string extendedExpiresOn)) { extendedExpiresOn = null; } if (!webTokenResponse.Properties.TryGetValue("Authority", out string authority)) { _logger.Error("Result from WAM does not have authority."); return(new MsalTokenResponse() { Error = "no_authority_in_wam_response", ErrorDescription = "No authority in WAM response" }); } if (!webTokenResponse.Properties.TryGetValue("correlationId", out string correlationId)) { _logger.Warning("No correlation ID in response"); correlationId = null; } bool hasIdToken = webTokenResponse.Properties.TryGetValue("wamcompat_id_token", out string idToken); _logger.Info("Result from WAM has id token? " + hasIdToken); bool hasClientInfo = webTokenResponse.Properties.TryGetValue("wamcompat_client_info", out string clientInfo); _logger.Info("Result from WAM has client info? " + hasClientInfo); bool hasScopes = webTokenResponse.Properties.TryGetValue("wamcompat_scopes", out string scopes); _logger.InfoPii("Result from WAM scopes: " + scopes, "Result from WAM has scopes? " + hasScopes); //foreach (var kvp in webTokenResponse.Properties) //{ // Debug.WriteLine($"Other params {kvp.Key}: {kvp.Value}"); //} MsalTokenResponse msalTokenResponse = new MsalTokenResponse() { AccessToken = webTokenResponse.Token, IdToken = idToken, CorrelationId = correlationId, Scope = scopes, ExpiresIn = CoreHelpers.GetDurationFromWindowsTimestamp(expiresOn, _logger), ExtendedExpiresIn = CoreHelpers.GetDurationFromWindowsTimestamp(extendedExpiresOn, _logger), ClientInfo = clientInfo, TokenType = "Bearer", WamAccountId = webTokenResponse.WebAccount.Id, TokenSource = TokenSource.Broker }; return(msalTokenResponse); }
public async Task<Uri> ListenToSingleRequestAndRespondAsync( int port, string path, Func<Uri, MessageAndHttpCode> responseProducer, CancellationToken cancellationToken) { TestBeforeTopLevelCall?.Invoke(); cancellationToken.ThrowIfCancellationRequested(); HttpListener httpListener = null; try { if(string.IsNullOrEmpty(path)) { path = "/"; } else { path = (path.StartsWith("/") ? path : "/" + path); } string urlToListenTo = "http://localhost:" + port + path; if (!urlToListenTo.EndsWith("/")) { urlToListenTo += "/"; } httpListener = new HttpListener(); httpListener.Prefixes.Add(urlToListenTo); TestBeforeStart?.Invoke(urlToListenTo); httpListener.Start(); _logger.Info("Listening for authorization code on " + urlToListenTo); using (cancellationToken.Register(() => { _logger.Warning("HttpListener stopped because cancellation was requested."); TryStopListening(httpListener); })) { TestBeforeGetContext?.Invoke(); HttpListenerContext context = await httpListener.GetContextAsync() .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); Respond(responseProducer, context); _logger.Verbose("HttpListner received a message on " + urlToListenTo); // the request URL should now contain the auth code and pkce return context.Request.Url; } } // If cancellation is requested before GetContextAsync is called, then either // an ObjectDisposedException or an HttpListenerException is thrown. // But this is just cancellation... catch (Exception ex) when (ex is HttpListenerException || ex is ObjectDisposedException) { _logger.Info("HttpListenerException - cancellation requested? " + cancellationToken.IsCancellationRequested); cancellationToken.ThrowIfCancellationRequested(); // if cancellation was not requested, propagate original ex throw; } finally { TryStopListening(httpListener); } }
private async Task <HttpResponse> ExecuteWithRetryAsync( Uri endpoint, IDictionary <string, string> headers, HttpContent body, HttpMethod method, ICoreLogger logger, bool doNotThrow = false, bool retry = true, CancellationToken cancellationToken = default) { Exception timeoutException = null; bool isRetryable = false; bool is5xxError = false; HttpResponse response = null; try { HttpContent clonedBody = body; if (body != null) { // Since HttpContent would be disposed by underlying client.SendAsync(), // we duplicate it so that we will have a copy in case we would need to retry clonedBody = await CloneHttpContentAsync(body).ConfigureAwait(false); } response = await ExecuteAsync(endpoint, headers, clonedBody, method, cancellationToken).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.OK) { return(response); } logger.Info(string.Format(CultureInfo.InvariantCulture, MsalErrorMessage.HttpRequestUnsuccessful, (int)response.StatusCode, response.StatusCode)); is5xxError = (int)response.StatusCode >= 500 && (int)response.StatusCode < 600; isRetryable = is5xxError && !HasRetryAfterHeader(response); } catch (TaskCanceledException exception) { logger.Error("The HTTP request failed or it was canceled. " + exception.Message); isRetryable = true; if (cancellationToken.IsCancellationRequested) { isRetryable = false; } timeoutException = exception; } if (isRetryable && retry) { logger.Info("Retrying one more time.."); await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); return(await ExecuteWithRetryAsync( endpoint, headers, body, method, logger, doNotThrow, retry : false).ConfigureAwait(false)); } logger.Warning("Request retry failed."); if (timeoutException != null) { throw new MsalServiceException( MsalError.RequestTimeout, "Request to the endpoint timed out.", timeoutException); } if (doNotThrow) { return(response); } if (is5xxError) { throw MsalServiceExceptionFactory.FromHttpResponse( MsalError.ServiceNotAvailable, "Service is unavailable to process the request", response); } return(response); }
public async Task <Uri> ListenToSingleRequestAndRespondAsync( int port, string path, Func <Uri, MessageAndHttpCode> responseProducer, CancellationToken cancellationToken) { TestBeforeTopLevelCall?.Invoke(); cancellationToken.ThrowIfCancellationRequested(); HttpListener httpListener = null; string urlToListenTo = string.Empty; try { if (string.IsNullOrEmpty(path)) { path = "/"; } else { path = (path.StartsWith("/") ? path : "/" + path); } urlToListenTo = "http://localhost:" + port + path; if (!urlToListenTo.EndsWith("/")) { urlToListenTo += "/"; } httpListener = new HttpListener(); httpListener.Prefixes.Add(urlToListenTo); TestBeforeStart?.Invoke(urlToListenTo); httpListener.Start(); _logger.Info("Listening for authorization code on " + urlToListenTo); using (cancellationToken.Register(() => { _logger.Warning("HttpListener stopped because cancellation was requested."); TryStopListening(httpListener); })) { TestBeforeGetContext?.Invoke(); HttpListenerContext context = await httpListener.GetContextAsync() .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); Respond(responseProducer, context); _logger.Verbose("HttpListner received a message on " + urlToListenTo); // the request URL should now contain the auth code and pkce return(context.Request.Url); } } // If cancellation is requested before GetContextAsync is called, then either // an ObjectDisposedException or an HttpListenerException is thrown. // But this is just cancellation... catch (Exception ex) when(ex is HttpListenerException || ex is ObjectDisposedException) { _logger.Info("HttpListenerException - cancellation requested? " + cancellationToken.IsCancellationRequested); cancellationToken.ThrowIfCancellationRequested(); if (ex is HttpListenerException) { throw new MsalClientException(MsalError.HttpListenerError, $"An HttpListenerException occurred while listening on {urlToListenTo} for the system browser to complete the login. " + "Possible cause and mitigation: the app is unable to listen on the specified URL; " + "run 'netsh http add iplisten 127.0.0.1' from the Admin command prompt.", ex); } // if cancellation was not requested, propagate original ex throw; } finally { TryStopListening(httpListener); } }
public static MsalRefreshTokenCacheItem GetRefreshToken( ICoreLogger logger, ILegacyCachePersistence legacyCachePersistence, IEnumerable <string> environmentAliases, string clientId, IAccount account) { try { IDictionary <AdalTokenCacheKey, AdalResultWrapper> dictionary = AdalCacheOperations.Deserialize(logger, legacyCachePersistence.LoadCache()); IEnumerable <KeyValuePair <AdalTokenCacheKey, AdalResultWrapper> > listToProcess = dictionary.Where(p => p.Key.ClientId.Equals(clientId, StringComparison.OrdinalIgnoreCase) && environmentAliases.Contains(new Uri(p.Key.Authority).Host)); bool filtered = false; if (!string.IsNullOrEmpty(account?.Username)) { listToProcess = listToProcess.Where(p => account.Username.Equals( p.Key.DisplayableId, StringComparison.OrdinalIgnoreCase)); filtered = true; } if (!string.IsNullOrEmpty(account?.HomeAccountId?.ObjectId)) { listToProcess = listToProcess.Where(p => account.HomeAccountId.ObjectId.Equals( p.Key.UniqueId, StringComparison.OrdinalIgnoreCase)).ToList(); filtered = true; } // We should filter at leasts by one criteria to ensure we retrun adequate RT if (!filtered) { logger.Warning("Could not filter ADAL entries by either UPN or unique ID, skipping."); return(null); } return(listToProcess.Select(adalEntry => new MsalRefreshTokenCacheItem( new Uri(adalEntry.Key.Authority).Host, adalEntry.Key.ClientId, adalEntry.Value.RefreshToken, adalEntry.Value.RawClientInfo, familyId: null, homeAccountId: GetHomeAccountId(adalEntry.Value))) .FirstOrDefault()); } catch (Exception ex) { logger.WarningPiiWithPrefix(ex, "An error occurred while searching for refresh tokens in ADAL format in the cache for MSAL. " + "For details please see https://aka.ms/net-cache-persistence-errors. "); return(null); } }