public Dictionary <string, string> GetPreviousRequestRecord(CallState callState) { Dictionary <string, string> parameters; if (callState != null && callState.AuthorityType == AuthorityType.AAD) { parameters = GetClientMetricsParameters(); } else { parameters = new Dictionary <string, string>(); } return(parameters); }
public void Authenticate(Uri authorizationUri, Uri redirectUri, CallState callState) { try { #if MAC var windowController = new AuthenticationAgentNSWindowController(authorizationUri.AbsoluteUri, redirectUri.OriginalString, CallbackMethod); windowController.Run(parameters.CallerWindow); #else this.parameters.CallerViewController.PresentViewController(new AuthenticationAgentUINavigationController(authorizationUri.AbsoluteUri, redirectUri.OriginalString, CallbackMethod), false, null); #endif } catch (Exception ex) { throw new AdalException(AdalError.AuthenticationUiFailed, ex); } }
public void EndClientMetricsRecord(string endpoint, CallState callState) { if (callState != null && callState.AuthorityType == AuthorityType.AAD && metricsTimer != null) { metricsTimer.Stop(); lastResponseTime = metricsTimer.ElapsedMilliseconds; lastCorrelationId = callState.CorrelationId; lastEndpoint = endpoint; lock (PendingClientMetricsLock) { if (pendingClientMetrics == null) { pendingClientMetrics = this; } } } }
public async Task UpdateFromTemplateAsync(CallState callState) { if (!this.updatedFromTemplate) { var authorityUri = new Uri(this.Authority); string host = authorityUri.Authority; string path = authorityUri.AbsolutePath.Substring(1); string tenant = path.Substring(0, path.IndexOf("/", StringComparison.Ordinal)); AuthenticatorTemplate matchingTemplate = await AuthenticatorTemplateList.FindMatchingItemAsync(this.ValidateAuthority, host, tenant, callState); this.AuthorizationUri = matchingTemplate.AuthorizeEndpoint.Replace("{tenant}", tenant); this.DeviceCodeUri = matchingTemplate.DeviceCodeEndpoint.Replace("{tenant}", tenant); this.TokenUri = matchingTemplate.TokenEndpoint.Replace("{tenant}", tenant); this.UserRealmUri = CanonicalizeUri(matchingTemplate.UserRealmEndpoint); this.IsTenantless = (string.Compare(tenant, TenantlessTenantName, StringComparison.OrdinalIgnoreCase) == 0); this.SelfSignedJwtAudience = matchingTemplate.Issuer.Replace("{tenant}", tenant); this.updatedFromTemplate = true; } }
public static Dictionary <string, string> ParseKeyValueList(string input, char delimiter, bool urlDecode, bool lowercaseKeys, CallState callState) { var response = new Dictionary <string, string>(); List <string> queryPairs = SplitWithQuotes(input, delimiter); foreach (string queryPair in queryPairs) { List <string> pair = SplitWithQuotes(queryPair, '='); if (pair.Count == 2 && !string.IsNullOrWhiteSpace(pair[0]) && !string.IsNullOrWhiteSpace(pair[1])) { string key = pair[0]; string value = pair[1]; // Url decoding is needed for parsing OAuth response, but not for parsing WWW-Authenticate header in 401 challenge if (urlDecode) { key = UrlDecode(key); value = UrlDecode(value); } if (lowercaseKeys) { key = key.Trim().ToLower(); } value = value.Trim().Trim(new[] { '\"' }).Trim(); if (response.ContainsKey(key) && callState != null) { PlatformPlugin.Logger.Warning(callState, string.Format(CultureInfo.CurrentCulture, "Key/value pair list contains redundant key '{0}'.", key)); } response[key] = value; } } return(response); }
public override async Task <bool> IsUserLocalAsync(CallState callState) { if (!UserInformation.NameAccessAllowed) { // The access is not allowed and we cannot determine whether this is a local user or not. So, we do NOT add form auth parameter. // This is the case where we can advise customers to add extra query parameter if they want. PlatformPlugin.Logger.Information(callState, "Cannot access user information to determine whether it is a local user or not due to machine's privacy setting."); return(false); } try { return(string.IsNullOrEmpty(await UserInformation.GetDomainNameAsync())); } catch (UnauthorizedAccessException) { PlatformPlugin.Logger.Information(callState, "Cannot try Windows Integrated Authentication due to lack of Enterprise capability."); // This mostly means Enterprise capability is missing, so WIA cannot be used and // we return true to add form auth parameter in the caller. return(true); } }
public static string ReadErrorResponse(XDocument responseDocument, CallState callState) { string errorMessage = null; try { XElement body = responseDocument.Descendants(XmlNamespace.SoapEnvelope + "Body").FirstOrDefault(); if (body != null) { XElement fault = body.Elements(XmlNamespace.SoapEnvelope + "Fault").FirstOrDefault(); if (fault != null) { XElement reason = fault.Elements(XmlNamespace.SoapEnvelope + "Reason").FirstOrDefault(); if (reason != null) { XElement text = reason.Elements(XmlNamespace.SoapEnvelope + "Text").FirstOrDefault(); if (text != null) { using (var reader = text.CreateReader()) { reader.MoveToContent(); errorMessage = reader.ReadInnerXml(); } } } } } } catch (XmlException ex) { throw new AdalException(AdalError.ParsingWsTrustResponseFailed, ex); } return(errorMessage); }
internal static WsTrustAddress ExtractWsTrustAddressFromMex(XDocument mexDocument, UserAuthType userAuthType, CallState callState) { WsTrustAddress address = null; MexPolicy policy = null; try { Dictionary <string, MexPolicy> policies = ReadPolicies(mexDocument); Dictionary <string, MexPolicy> bindings = ReadPolicyBindings(mexDocument, policies); SetPolicyEndpointAddresses(mexDocument, bindings); Random random = new Random(); //try ws-trust 1.3 first policy = policies.Values.Where(p => p.Url != null && p.AuthType == userAuthType && p.Version == WsTrustVersion.WsTrust13).OrderBy(p => random.Next()).FirstOrDefault() ?? policies.Values.Where(p => p.Url != null && p.AuthType == userAuthType).OrderBy(p => random.Next()).FirstOrDefault(); if (policy != null) { address = new WsTrustAddress(); address.Uri = policy.Url; address.Version = policy.Version; } else if (userAuthType == UserAuthType.IntegratedAuth) { throw new AdalException(AdalError.IntegratedAuthFailed, new AdalException(AdalError.WsTrustEndpointNotFoundInMetadataDocument)); } else { throw new AdalException(AdalError.WsTrustEndpointNotFoundInMetadataDocument); } } catch (XmlException ex) { throw new AdalException(AdalError.ParsingWsMetadataExchangeFailed, ex); } return(address); }
internal abstract void Error(CallState callState, Exception ex, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "");
public static async Task <WsTrustAddress> FetchWsTrustAddressFromMexAsync(string federationMetadataUrl, UserAuthType userAuthType, CallState callState) { XDocument mexDocument = await FetchMexAsync(federationMetadataUrl, callState); return(ExtractWsTrustAddressFromMex(mexDocument, userAuthType, callState)); }
public static Dictionary <string, string> ParseKeyValueList(string input, char delimiter, bool urlDecode, CallState callState) { return(ParseKeyValueList(input, delimiter, urlDecode, true, callState)); }
internal static async Task <XDocument> FetchMexAsync(string federationMetadataUrl, CallState callState) { XDocument mexDocument; try { IHttpClient request = PlatformPlugin.HttpClientFactory.Create(federationMetadataUrl, callState); using (var response = await request.GetResponseAsync()) { mexDocument = XDocument.Load(response.ResponseStream, LoadOptions.None); } } catch (WebException ex) { throw new AdalServiceException(AdalError.AccessingWsMetadataExchangeFailed, ex); } catch (XmlException ex) { throw new AdalException(AdalError.ParsingWsMetadataExchangeFailed, ex); } return(mexDocument); }
public HttpClientWrapper(string uri, CallState callState) { this.uri = uri; this.Headers = new Dictionary <string, string>(); this.CallState = callState; }
public IHttpClient Create(string uri, CallState callState) { return(new HttpClientWrapper(uri, callState)); }
public async Task <AuthorizationResult> AcquireAuthorizationAsync(Uri authorizationUri, Uri redirectUri, CallState callState) { bool ssoMode = ReferenceEquals(redirectUri, Constant.SsoPlaceHolderUri); if (this.promptBehavior == PromptBehavior.Never && !ssoMode && redirectUri.Scheme != Constant.MsAppScheme) { throw new ArgumentException(AdalErrorMessageEx.RedirectUriUnsupportedWithPromptBehaviorNever, "redirectUri"); } WebAuthenticationResult webAuthenticationResult; WebAuthenticationOptions options = (this.useCorporateNetwork && (ssoMode || redirectUri.Scheme == Constant.MsAppScheme)) ? WebAuthenticationOptions.UseCorporateNetwork : WebAuthenticationOptions.None; if (this.promptBehavior == PromptBehavior.Never) { options |= WebAuthenticationOptions.SilentMode; } try { if (ssoMode) { webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(options, authorizationUri); } else { webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(options, authorizationUri, redirectUri); } } catch (FileNotFoundException ex) { throw new AdalException(AdalError.AuthenticationUiFailed, ex); } catch (Exception ex) { if (this.promptBehavior == PromptBehavior.Never) { throw new AdalException(AdalError.UserInteractionRequired, ex); } throw new AdalException(AdalError.AuthenticationUiFailed, ex); } AuthorizationResult result = ProcessAuthorizationResult(webAuthenticationResult, callState); return(result); }
public async virtual Task <bool> IsUserLocalAsync(CallState callState) { return(await Task.Factory.StartNew(() => false)); }
internal abstract void Warning(CallState callState, string message, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "");
public virtual string GetRedirectUriAsString(Uri redirectUri, CallState callState) { return(redirectUri.OriginalString); }
public static async Task <WsTrustResponse> SendRequestAsync(WsTrustAddress wsTrustAddress, UserCredential credential, CallState callState) { IHttpClient request = PlatformPlugin.HttpClientFactory.Create(wsTrustAddress.Uri.AbsoluteUri, callState); request.ContentType = "application/soap+xml"; if (credential.UserAuthType == UserAuthType.IntegratedAuth) { SetKerberosOption(request); } StringBuilder messageBuilder = BuildMessage(DefaultAppliesTo, wsTrustAddress, credential); string soapAction = XmlNamespace.Issue.ToString(); if (wsTrustAddress.Version == WsTrustVersion.WsTrust2005) { soapAction = XmlNamespace.Issue2005.ToString(); } WsTrustResponse wstResponse; try { request.BodyParameters = new StringRequestParameters(messageBuilder); request.Headers["SOAPAction"] = soapAction; IHttpWebResponse response = await request.GetResponseAsync(); wstResponse = WsTrustResponse.CreateFromResponse(response.ResponseStream, wsTrustAddress.Version); } catch (WebException ex) { string errorMessage; try { XDocument responseDocument = WsTrustResponse.ReadDocumentFromResponse(ex.Response.GetResponseStream()); errorMessage = WsTrustResponse.ReadErrorResponse(responseDocument, callState); } catch (AdalException) { errorMessage = "See inner exception for detail."; } throw new AdalServiceException( AdalError.FederatedServiceReturnedError, string.Format(AdalErrorMessage.FederatedServiceReturnedErrorTemplate, wsTrustAddress.Uri, errorMessage), null, ex); } return(wstResponse); }
internal static string PrepareLogMessage(CallState callState, string classOrComponent, string message) { string correlationId = (callState != null) ? callState.CorrelationId.ToString() : string.Empty; return(string.Format(CultureInfo.CurrentCulture, "{0}: {1} - {2}: {3}", DateTime.UtcNow, correlationId, classOrComponent, message)); }
private static AuthorizationResult ProcessAuthorizationResult(WebAuthenticationResult webAuthenticationResult, CallState callState) { AuthorizationResult result; switch (webAuthenticationResult.ResponseStatus) { case WebAuthenticationStatus.Success: result = new AuthorizationResult(AuthorizationStatus.Success, webAuthenticationResult.ResponseData); break; case WebAuthenticationStatus.ErrorHttp: result = new AuthorizationResult(AuthorizationStatus.ErrorHttp, webAuthenticationResult.ResponseErrorDetail.ToString(CultureInfo.CurrentCulture)); break; case WebAuthenticationStatus.UserCancel: result = new AuthorizationResult(AuthorizationStatus.UserCancel, null); break; default: result = new AuthorizationResult(AuthorizationStatus.UnknownError, null); break; } return(result); }
public async Task <AuthenticatorTemplate> FindMatchingItemAsync(bool validateAuthority, string host, string tenant, CallState callState) { AuthenticatorTemplate matchingAuthenticatorTemplate = null; if (validateAuthority) { matchingAuthenticatorTemplate = this.FirstOrDefault(a => string.Compare(host, a.Host, StringComparison.OrdinalIgnoreCase) == 0); if (matchingAuthenticatorTemplate == null) { // We only check with the first trusted authority (login.windows.net) for instance discovery await this.First().VerifyAnotherHostByInstanceDiscoveryAsync(host, tenant, callState); } } return(matchingAuthenticatorTemplate ?? AuthenticatorTemplate.CreateFromHost(host)); }
public override string GetRedirectUriAsString(Uri redirectUri, CallState callState) { return(ReferenceEquals(redirectUri, Constant.SsoPlaceHolderUri) ? WebAuthenticationBroker.GetCurrentApplicationCallbackUri().OriginalString : redirectUri.OriginalString); }
internal static async Task <UserRealmDiscoveryResponse> CreateByDiscoveryAsync(string userRealmUri, string userName, CallState callState) { string userRealmEndpoint = userRealmUri; userRealmEndpoint += (userName + "?api-version=1.0"); PlatformPlugin.Logger.Information(callState, string.Format(CultureInfo.CurrentCulture, " Sending user realm discovery request to '{0}'", userRealmEndpoint)); var client = new AdalHttpClient(userRealmEndpoint, callState) { Client = { Accept = "application/json" } }; return(await client.GetResponseAsync <UserRealmDiscoveryResponse>(ClientMetricsEndpointType.UserRealmDiscovery)); }
public async Task VerifyAnotherHostByInstanceDiscoveryAsync(string host, string tenant, CallState callState) { string instanceDiscoveryEndpoint = this.InstanceDiscoveryEndpoint; instanceDiscoveryEndpoint += ("?api-version=1.0&authorization_endpoint=" + AuthorizeEndpointTemplate); instanceDiscoveryEndpoint = instanceDiscoveryEndpoint.Replace("{host}", host); instanceDiscoveryEndpoint = instanceDiscoveryEndpoint.Replace("{tenant}", tenant); try { var client = new AdalHttpClient(instanceDiscoveryEndpoint, callState); InstanceDiscoveryResponse discoveryResponse = await client.GetResponseAsync <InstanceDiscoveryResponse>(ClientMetricsEndpointType.InstanceDiscovery); if (discoveryResponse.TenantDiscoveryEndpoint == null) { throw new AdalException(AdalError.AuthorityNotInValidList); } } catch (AdalServiceException ex) { throw new AdalException((ex.ErrorCode == "invalid_instance") ? AdalError.AuthorityNotInValidList : AdalError.AuthorityValidationFailed, ex); } }
internal AuthenticationResultEx LoadFromCache(CacheQueryData cacheQueryData, CallState callState) { lock (cacheLock) { PlatformPlugin.Logger.Verbose(callState, "Looking up cache for a token..."); AuthenticationResultEx resultEx = null; KeyValuePair <TokenCacheKey, AuthenticationResultEx>?kvp = this.LoadSingleItemFromCache(cacheQueryData, callState); if (kvp.HasValue) { TokenCacheKey cacheKey = kvp.Value.Key; resultEx = kvp.Value.Value; bool tokenNearExpiry = (resultEx.Result.ExpiresOn <= DateTime.UtcNow + TimeSpan.FromMinutes(ExpirationMarginInMinutes)); if (tokenNearExpiry) { resultEx.Result.AccessToken = null; PlatformPlugin.Logger.Verbose(callState, "An expired or near expiry token was found in the cache"); } else if (!cacheKey.ResourceEquals(cacheQueryData.Resource)) { PlatformPlugin.Logger.Verbose(callState, string.Format(CultureInfo.CurrentCulture, "Multi resource refresh token for resource '{0}' will be used to acquire token for '{1}'", cacheKey.Resource, cacheQueryData.Resource)); var newResultEx = new AuthenticationResultEx { Result = new AuthenticationResult(null, null, DateTimeOffset.MinValue), RefreshToken = resultEx.RefreshToken, ResourceInResponse = resultEx.ResourceInResponse }; newResultEx.Result.UpdateTenantAndUserInfo(resultEx.Result.TenantId, resultEx.Result.IdToken, resultEx.Result.UserInfo); resultEx = newResultEx; } else { PlatformPlugin.Logger.Verbose(callState, string.Format(CultureInfo.CurrentCulture, "{0} minutes left until token in cache expires", (resultEx.Result.ExpiresOn - DateTime.UtcNow).TotalMinutes)); } if (resultEx.Result.AccessToken == null && resultEx.RefreshToken == null) { this.tokenCacheDictionary.Remove(cacheKey); PlatformPlugin.Logger.Information(callState, "An old item was removed from the cache"); this.HasStateChanged = true; resultEx = null; } if (resultEx != null) { PlatformPlugin.Logger.Information(callState, "A matching item (access token or refresh token or both) was found in the cache"); } } else { PlatformPlugin.Logger.Information(callState, "No matching token was found in the cache"); } return(resultEx); } }
public async Task <AuthorizationResult> AcquireAuthorizationAsync(Uri authorizationUri, Uri redirectUri, CallState callState) { returnedUriReady = new SemaphoreSlim(0); Authenticate(authorizationUri, redirectUri, callState); await returnedUriReady.WaitAsync(); return(authorizationResult); }
internal void StoreToCache(AuthenticationResultEx result, string authority, string resource, string clientId, TokenSubjectType subjectType, CallState callState) { lock (cacheLock) { PlatformPlugin.Logger.Verbose(callState, "Storing token in the cache..."); string uniqueId = (result.Result.UserInfo != null) ? result.Result.UserInfo.UniqueId : null; string displayableId = (result.Result.UserInfo != null) ? result.Result.UserInfo.DisplayableId : null; this.OnBeforeWrite(new TokenCacheNotificationArgs { Resource = resource, ClientId = clientId, UniqueId = uniqueId, DisplayableId = displayableId }); TokenCacheKey tokenCacheKey = new TokenCacheKey(authority, resource, clientId, subjectType, result.Result.UserInfo); this.tokenCacheDictionary[tokenCacheKey] = result; PlatformPlugin.Logger.Verbose(callState, "An item was stored in the cache"); this.UpdateCachedMrrtRefreshTokens(result, clientId, subjectType); this.HasStateChanged = true; } }
public async Task <AuthorizationResult> AcquireAuthorizationAsync(Uri authorizationUri, Uri redirectUri, CallState callState) { returnedUriReady = new SemaphoreSlim(0); try { var agentIntent = new Intent(this.parameters.CallerActivity, typeof(AuthenticationAgentActivity)); agentIntent.PutExtra("Url", authorizationUri.AbsoluteUri); agentIntent.PutExtra("Callback", redirectUri.AbsoluteUri); this.parameters.CallerActivity.StartActivityForResult(agentIntent, 0); } catch (Exception ex) { throw new AdalException(AdalError.AuthenticationUiFailed, ex); } await returnedUriReady.WaitAsync(); return(authorizationResult); }
private KeyValuePair <TokenCacheKey, AuthenticationResultEx>?LoadSingleItemFromCache(CacheQueryData cacheQueryData, CallState callState) { lock (cacheLock) { // First identify all potential tokens. List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > items = this.QueryCache(cacheQueryData.Authority, cacheQueryData.ClientId, cacheQueryData.SubjectType, cacheQueryData.UniqueId, cacheQueryData.DisplayableId); List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > resourceSpecificItems = items.Where(p => p.Key.ResourceEquals(cacheQueryData.Resource)).ToList(); int resourceValuesCount = resourceSpecificItems.Count(); //multiple tokens matched. scope down the results to the matching userAssertion Hash, if provided if (resourceValuesCount > 1 && cacheQueryData.AssertionHash != null) { resourceSpecificItems = resourceSpecificItems.Where(p => p.Value.UserAssertionHash.Equals(cacheQueryData.AssertionHash)) .ToList(); resourceValuesCount = resourceSpecificItems.Count(); } KeyValuePair <TokenCacheKey, AuthenticationResultEx>?returnValue = null; switch (resourceValuesCount) { case 1: PlatformPlugin.Logger.Information(callState, "An item matching the requested resource was found in the cache"); returnValue = resourceSpecificItems.First(); break; case 0: { // There are no resource specific tokens. Choose any of the MRRT tokens if there are any. List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > mrrtItems = items.Where(p => p.Value.IsMultipleResourceRefreshToken).ToList(); if (mrrtItems.Any()) { returnValue = mrrtItems.First(); PlatformPlugin.Logger.Information(callState, "A Multi Resource Refresh Token for a different resource was found which can be used"); } } break; default: throw new AdalException(AdalError.MultipleTokensMatched); } // check for tokens issued to same client_id/user_id combination, but any tenant. if (returnValue == null) { List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > itemsForAllTenants = this.QueryCache(null, cacheQueryData.ClientId, cacheQueryData.SubjectType, cacheQueryData.UniqueId, cacheQueryData.DisplayableId); if (itemsForAllTenants.Count != 0) { returnValue = itemsForAllTenants.First(); } // check if the token was issued by AAD if (returnValue != null && Authenticator.DetectAuthorityType(returnValue.Value.Key.Authority) != AuthorityType.ADFS) { //remove access token to redeem refresh token against a different tenant. returnValue.Value.Value.Result.AccessToken = null; } else { returnValue = null; } } return(returnValue); } }