SSPI negotiation failed with WtrustChannelFactory - windows

This one has me for a while now, I am trying to build a console app that can call a .net web/wcf service SP, the first leg is to get a token from the idP (ADFS4.0) the pasted code was working fine for a whole day, at some point it stopped working with the following error:
SOAP security negotiation with 'https://adfs.domain.in/adfs/services/trust/13/windowsmixed' for target 'https://adfs.domain.in/adfs/services/trust/13/windowsmixed' failed. See inner exception for more details.
The inner error is:
The Security Support Provider Interface (SSPI) negotiation failed.
NativeErrorCode: 0x80090350 -> SEC_E_DOWNGRADE_DETECTED
I have tried /13/windows and /windowstransport as well as the endpoint.
private static GenericXmlSecurityToken RequestSecurityToken()
{
// set up the ws-trust channel factory
var factory = new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(new WindowsWSTrustBinding(
SecurityMode.TransportWithMessageCredential), new EndpointAddress(new Uri("https://adfs.domain.in/adfs/services/trust/13/windowsmixed"), EndpointIdentity.CreateSpnIdentity("adfs#domain.in")));
factory.TrustVersion = TrustVersion.WSTrust13;
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new System.ServiceModel.EndpointAddress(endpoint_address)
};
// request token and return
return factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;
}

Related

An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail

When I try to execute a CRM CRUD operation using a Console App, I'm getting the following error:
System.ServiceModel.Security.MessageSecurityException
  HResult=0x80131501
  Message=An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
  Source=mscorlib
class Program
{
static void Main(string[] args)
{
IOrganizationService _serviceProxy = crmConnection();
Entity con = new Entity("contact");
con["lastname"] = "test";
_serviceProxy.Create(con);
}
private static IOrganizationService crmConnection()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Uri oUri = new Uri("https://XXXXXXXX.api.crm.dynamics.com/XRMServices/2011/Organization.svc");
ClientCredentials clientCredentials = new ClientCredentials();
clientCredentials.UserName.UserName = "XXXXXXXXXXXX";
clientCredentials.UserName.Password = "XXXXXXXXXXXXXXXXXX";
OrganizationServiceProxy _serviceProxy = new OrganizationServiceProxy(oUri, null,clientCredentials,null);
_serviceProxy.Timeout = new TimeSpan(0, 10, 0);
return _serviceProxy;
}
}
Thanks in advance.
An unsecured or incorrectly secured fault was received from the other party
Try using Connection String with XrmTooling this way you can avoid call directly to the Organization.svc and handle the redirection to the SDK
var conn = new CrmServiceClient("AuthType=Office365;Username=xxx#xxx.com; Password=yyyyyy;Url=https://xxxx.crm.dynamics.com;RequireNewInstance=True");
IOrganizationService _orgService = conn.OrganizationWebProxyClient ?? (IOrganizationService)conn.OrganizationServiceProxy;
return _orgService;
If the error continues could be related to differences between your PC time and the Dynamics Server ajusted +-4 minutes and try again.
Hope it helps

Proactive Bot Messaging - CreateDirectConversation - unauthorized exception

I am creating a bot to proactively start a conversation with an account I have never had a previous conversation with. I have created another controller that I am posting to and doing the following steps:
public class OutboundController : ApiController {
public HttpResponseMessage Post([FromUri] int id, [FromBody] OutboundData outboundData) {
MicrosoftAppCredentials.TrustServiceUrl(outboundData.ServiceUrl);
//create conversation
var connector = new ConnectorClient(new Uri(outboundData.ServiceUrl));
var botAccount = new ChannelAccount { Id = outboundData.FromAccountId, Name = outboundData.FromAccountName };
var toAccount = new ChannelAccount { Id = outboundData.ToAccountId, Name = outboundData.ToAccountName };
if(!MicrosoftAppCredentials.IsTrustedServiceUrl(outboundData.ServiceUrl)) {
throw new Exception("service URL is not trusted!");
}
var conversationResponse = connector.Conversations.CreateDirectConversation(botAccount, toAccount);
var client = new BuslogicClient();
var confirmData = client.GetOutboundData(id);
var greetingMessage = CreateGreetingMessage(confirmData);
var convoMessage = Activity.CreateMessageActivity();
convoMessage.Text = greetingMessage;
convoMessage.From = botAccount;
convoMessage.Recipient = toAccount;
convoMessage.Conversation = new ConversationAccount(id: conversationResponse.Id);
convoMessage.Locale = "en-Us";
connector.Conversations.SendToConversationAsync((Activity)convoMessage);
string message = string.Format("I received correlationid:{0} and started conversationId:{1}", id, conversationResponse.Id);
var response = Request.CreateResponse(HttpStatusCode.OK, message);
return response;
}
When I call connector.Conversations.CreateDirectConversation I am getting the following exception: Additional information: Authorization for Microsoft App ID [ID] failed with status code Unauthorized and reason phrase 'Unauthorized'. If I do this with appId and password blank everything works fine in the channel emulator. I've tried providing the MicrosoftAppCredentials to the constructor of the ConnectorClient, but that has no affect. I've read on other threads that the service URL must be trusted so I used MicrosoftAppCredentials.TrustServiceUrl.
versions I am using:
BotBuilder 3.5.3
Channel Emulator 3.0.0.59
The use-case for my bot is to post to the outbound controller with some user info to create a proactive message to be sent out (specifically SMS). If the user responds to my message it will be intercepted by the messages controller and passed to my dialogs for further processing and conversation responses on that same channel.
I've also taken a look at: https://github.com/Microsoft/BotBuilder/issues/2155 but don't quite understand solution described in the comments or if it even pertains to the issue I'm trying to solve.
Any suggestions or help would be appreciated!
You need to pass credentials explicitly to connector:
var credentials = new MicrosoftAppCredentials("YoursMicrosoftAppId", "YoursMicrosoftAppPassword");
var connector = new ConnectorClient(serviceUrl, credentials);

NativeMessageHandler Giving "Unauthorized" result on PostAsync

I am using ModernHTTPClient in my application to access a Secure ReST Service.
Server is configured with TLS1.2.
Whenever i try to hit the service with valid user credential, i gets the below error.
"Unauthorized"
"System.TypeInitializationException: The type initializer for
'System.Net.HttpVersion' threw an exception."
Below is the code which i used
NativeMessageHandler handler = new NativeMessageHandler(false, false);
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.EnableUntrustedCertificates();
handler.Credentials = oNwCred;
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
using (var oClient = new HttpClient(handler))
{
//Set Timeout
oClient.Timeout = new TimeSpan(0, C_TIME_OUT, 0);
oClient.DefaultRequestHeaders.Accept.Clear();
var oContent = new StringContent(szRequestJson, Encoding.UTF8, C_CONTENT_TYPE);
return await oClient.PostAsync(szUrl, oContent);
}
Server is configured with self signed certificate.
I have tried the code from Both PCL and from Droid project as well.
Thank you in advance for your help.
Regards
Vips

MS crm Account Creation: System.Net.WebException: The request failed with HTTP status 401: Unauthorized

I am using
I am logged into a remote server for accessing Visual studio as well as MS CRM. I have taken sample code from SDK and trying to run the code:
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";
CrmService service = new CrmService();
service.Url= "http://10.16.16.205:5555/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = new System.Net.NetworkCredential"username", "password", "domain");
// Create the account object.
account account = new account();
// Set the properties of the account object.
account.name = "Fourth Coffee123";
account.address1_line1 = "29 Market St.";
account.address1_city = "Sam";
account.address1_stateorprovince = "MT1";
account.address1_postalcode = "9999";
account.donotbulkemail = new CrmBoolean();
account.donotbulkemail.Value = true;
// Create the target object for the request.
TargetCreateAccount target = new TargetCreateAccount();
// Set the properties of the target object.
target.Account = account;
// Create the request object.
CreateRequest create = new CreateRequest();
// Set the properties of the request object.
create.Target = target;
// Execute the request.
CreateResponse created = (CreateResponse)service.Execute(create);
I am using Crm Web Service for this, but Its throwing exception:
Exception Details:
System.Net.WebException: The request
failed with HTTP status 401:
Unauthorized.
Source Error:
Line 114: [return: System.Xml.Serialization.XmlElementAttribute("Response")]
Line 115: public Response Execute(Request Request) {
Line 116: ***object[] results = this.Invoke("Execute", new object[]* {**
Line 117: Request});
Line 118: return ((Response)(results[0]));
One thing you are missing is a real username and password. I am assuming that you have omitted this for the purposes of this question.
Have you checked the security role on the user that you are using for the web service call? Add this user to the System Administrator role if you haven't already.
With CRM often times, this error has nothing to do with security but something else altogether.
First turn on CRM tracing and look there. This will give you more error detail. Here's how:
http://support.microsoft.com/kb/907490
Also you can try to use my exception formatter to get more detail on the error. This is an extension class that will allow you to format the exception and print it to stdout or to the http response. Find it here:
http://paste.ly/5Y66
Use it this way:
try {
// do all your stuff
} catch (Exception ex) {
ex.Print();
}
Notice that in the formatted exception output, you can see the "Details" property deserialized such that you can see the text version. This is where CRM hides the real exception most of the time.

Windows Service Hosting WCF Objects over SSL (https) - Custom JSON Error Handling Doesn't Work

I will first show the code that works in a non-ssl (http) environment. This code uses a custom json error handler, and all errors thrown, do get bubbled up to the client javascript (ajax).
// Create webservice endpoint
WebHttpBinding binding = new WebHttpBinding();
ServiceEndpoint serviceEndPoint = new ServiceEndpoint(ContractDescription.GetContract(Type.GetType(svcHost.serviceContract + ", " + svcHost.assemblyName)), binding, new EndpointAddress(svcHost.hostUrl));
// Add exception handler
serviceEndPoint.Behaviors.Add(new FaultingWebHttpBehavior());
// Create host and add webservice endpoint
WebServiceHost webServiceHost = new WebServiceHost(svcHost.obj, new Uri(svcHost.hostUrl));
webServiceHost.Description.Endpoints.Add(serviceEndPoint);
webServiceHost.Open();
I'll also show you what the FaultingWebHttpBehavior class looks like:
public class FaultingWebHttpBehavior : WebHttpBehavior
{
public FaultingWebHttpBehavior()
{
}
protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ErrorHandler());
}
public class ErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
// Build an object to return a json serialized exception
GeneralFault generalFault = new GeneralFault();
generalFault.BaseType = "Exception";
generalFault.Type = error.GetType().ToString();
generalFault.Message = error.Message;
// Create the fault object to return to the client
fault = Message.CreateMessage(version, "", generalFault, new DataContractJsonSerializer(typeof(GeneralFault)));
WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
}
}
}
[DataContract]
public class GeneralFault
{
[DataMember]
public string BaseType;
[DataMember]
public string Type;
[DataMember]
public string Message;
}
The AddServerErrorHandlers() method gets called automatically, once webServiceHost.Open() gets called. This sets up the custom json error handler, and life is good :-)
The problem comes, when we switch to and SSL (https) environment. I'll now show you endpoint creation code for SSL:
// Create webservice endpoint
WebHttpBinding binding = new WebHttpBinding();
ServiceEndpoint serviceEndPoint = new ServiceEndpoint(ContractDescription.GetContract(Type.GetType(svcHost.serviceContract + ", " + svcHost.assemblyName)), binding, new EndpointAddress(svcHost.hostUrl));
// This exception handler code below (FaultingWebHttpBehavior) doesn't work with SSL communication for some reason, need to resarch...
// Add exception handler
serviceEndPoint.Behaviors.Add(new FaultingWebHttpBehavior());
//Add Https Endpoint
WebServiceHost webServiceHost = new WebServiceHost(svcHost.obj, new Uri(svcHost.hostUrl));
binding.Security.Mode = WebHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
webServiceHost.AddServiceEndpoint(svcHost.serviceContract, binding, string.Empty);
Now, with this SSL endpoint code, the service starts up correctly, and wcf hosted objects can be communicated with just fine via client javascript. However, the custom error handler doesn't work. The reason is, the AddServerErrorHandlers() method never gets called when webServiceHost.Open() is run.
So, can anyone tell me what is wrong with this picture? And why, is AddServerErrorHandlers() not getting called automatically, like it does when I'm using non-ssl endpoints?
Thanks!
I will refer you to MSDN docs
If the Transport value is specified by
the
WebHttpBinding(WebHttpSecurityMode),
then the settings provided by the
Transport property become effective
for the service endpoint. The value of
WebHttpSecurityMode can only be set in
the WebHttpBinding constructor that
takes it as an explicit parameter and
its value cannot be set again after
the binding instance is created.
see : http://msdn.microsoft.com/en-us/library/bb348328.aspx
So you need to pass this value
binding.Security.Mode = WebHttpSecurityMode.Transport;
into your .ctor() like that
WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
I have never used this before as I always declare my bindings into web.config file but according to MSDN, this is what you should do.

Resources