public static StringBuilder BuildMessage(string appliesTo, WsTrustAddress wsTrustAddress, UserCredential credential) { // securityHeader will be empty string for Kerberos. StringBuilder securityHeaderBuilder = BuildSecurityHeader(wsTrustAddress, credential); string guid = Guid.NewGuid().ToString(); StringBuilder messageBuilder = new StringBuilder(MaxExpectedMessageSize); String schemaLocation = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; String soapAction = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"; String rstTrustNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512"; String keyType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer"; String requestType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue"; if (wsTrustAddress.Version == WsTrustVersion.WsTrust2005) { soapAction = "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue"; rstTrustNamespace = "http://schemas.xmlsoap.org/ws/2005/02/trust"; keyType = "http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey"; requestType = "http://schemas.xmlsoap.org/ws/2005/02/trust/Issue"; } messageBuilder.AppendFormat(CultureInfo.CurrentCulture, WsTrustEnvelopeTemplate, schemaLocation, soapAction, guid, wsTrustAddress.Uri, securityHeaderBuilder, rstTrustNamespace, appliesTo, keyType, requestType); securityHeaderBuilder.SecureClear(); return(messageBuilder); }
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); }
private static StringBuilder BuildSecurityHeader(WsTrustAddress address, UserCredential credential) { StringBuilder securityHeaderBuilder = new StringBuilder(MaxExpectedMessageSize); // Not add <Security> element if the credential type is kerberos if (credential.UserAuthType == UserAuthType.UsernamePassword) { StringBuilder messageCredentialsBuilder = new StringBuilder(MaxExpectedMessageSize); string guid = Guid.NewGuid().ToString(); messageCredentialsBuilder.AppendFormat(CultureInfo.CurrentCulture, "<o:UsernameToken u:Id='uuid-{0}'><o:Username>{1}</o:Username><o:Password>", guid, credential.UserName); char[] passwordChars = null; try { passwordChars = credential.PasswordToCharArray(); string escapeStr = XmlEscape(new string(passwordChars)); messageCredentialsBuilder.Append(escapeStr); escapeStr = ""; } finally { passwordChars.SecureClear(); } messageCredentialsBuilder.AppendFormat(CultureInfo.CurrentCulture, "</o:Password></o:UsernameToken>"); // // Timestamp the message // DateTime currentTime = DateTime.UtcNow; string currentTimeString = BuildTimeString(currentTime); // Expiry is 10 minutes after creation DateTime expiryTime = currentTime.AddMinutes(10); string expiryTimeString = BuildTimeString(expiryTime); securityHeaderBuilder.AppendFormat(CultureInfo.CurrentCulture, "<o:Security s:mustUnderstand='1' xmlns:o='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'><u:Timestamp u:Id='_0'><u:Created>{0}</u:Created><u:Expires>{1}</u:Expires></u:Timestamp>{2}</o:Security>", currentTimeString, expiryTimeString, messageCredentialsBuilder); messageCredentialsBuilder.SecureClear(); } return(securityHeaderBuilder); }
protected override async Task PreTokenRequest() { await base.PreTokenRequest(); if (this.PerformUserRealmDiscovery()) { UserRealmDiscoveryResponse userRealmResponse = await UserRealmDiscoveryResponse.CreateByDiscoveryAsync(this.Authenticator.UserRealmUri, this.userCredential.UserName, this.CallState); PlatformPlugin.Logger.Information(this.CallState, string.Format(CultureInfo.CurrentCulture, " User with hash '{0}' detected as '{1}'", PlatformPlugin.CryptographyHelper.CreateSha256Hash(this.userCredential.UserName), userRealmResponse.AccountType)); if (string.Compare(userRealmResponse.AccountType, "federated", StringComparison.OrdinalIgnoreCase) == 0) { if (string.IsNullOrWhiteSpace(userRealmResponse.FederationMetadataUrl)) { throw new AdalException(AdalError.MissingFederationMetadataUrl); } WsTrustAddress wsTrustAddress = await MexParser.FetchWsTrustAddressFromMexAsync(userRealmResponse.FederationMetadataUrl, this.userCredential.UserAuthType, this.CallState); PlatformPlugin.Logger.Information(this.CallState, string.Format(CultureInfo.CurrentCulture, " WS-Trust endpoint '{0}' fetched from MEX at '{1}'", wsTrustAddress.Uri, userRealmResponse.FederationMetadataUrl)); WsTrustResponse wsTrustResponse = await WsTrustRequest.SendRequestAsync(wsTrustAddress, this.userCredential, this.CallState); PlatformPlugin.Logger.Information(this.CallState, string.Format(CultureInfo.CurrentCulture, " Token of type '{0}' acquired from WS-Trust endpoint", wsTrustResponse.TokenType)); // We assume that if the response token type is not SAML 1.1, it is SAML 2 this.userAssertion = new UserAssertion(wsTrustResponse.Token, (wsTrustResponse.TokenType == WsTrustResponse.Saml1Assertion) ? OAuthGrantType.Saml11Bearer : OAuthGrantType.Saml20Bearer); } else if (string.Compare(userRealmResponse.AccountType, "managed", StringComparison.OrdinalIgnoreCase) == 0) { // handle password grant flow for the managed user if (this.userCredential.PasswordToCharArray() == null) { throw new AdalException(AdalError.PasswordRequiredForManagedUserError); } } else { throw new AdalException(AdalError.UnknownUserType); } } }
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); }