Proactive messaging throwing Operation returned an invalid status code 'Unauthorized' - .net-core

I'm trying to store the conversation reference for chats between user and our bot, and use that chat reference to send other messages later.
I'm saving the following entities in our DB:
string UserAadObjectId { get; set; }
string UserId { get; set; }
string UserName { get; set; }
string ConversationId { get; set; }
string ConversationType { get; set; }
string ConversationTenantId { get; set; }
string ChannelId { get; set; }
string ActivityId { get; set; }
string BotId { get; set; }
string BotName { get; set; }
string ConversationReference { get; set; }
string ServiceUrl { get; set; }
After getting these entities for a specific user, I'm creating a conversation reference as following:(Where chatReference is the sql database for the entities above)
var user = new ChannelAccount(chatReference.UserId, chatReference.UserName, null, chatReference.UserAadObjectId);
var bot = new ChannelAccount(chatReference.BotId, chatReference.BotName);
var conversationAccount = new ConversationAccount(conversationType: chatReference.ConversationType, id: chatReference.ConversationId, tenantId: chatReference.ConversationTenantId);
var convReference = new ConversationReference(activityId: chatReference.ActivityId, user: user, bot: bot, conversation: conversationAccount, channelId: chatReference.ChannelId, serviceUrl: chatReference.ServiceUrl);
When running:
await turnContext.SendActivityAsync(messageActivity);
I'm getting the following error from Bot Connector I think:
Operation returned an invalid status code 'Unauthorized'
{"message":"Authorization has been denied for this request."}
Why this is happening? Knowing that AppId and AppPwd are correct.

There are series of steps to be followed to avoid the error occurred.
1. Disable security and test on localhost
Check the App ID and password in configuration file and delete those for testing
"MicrosoftAppId": "",
"MicrosoftAppPassword": ""
As you are using the core .Net framework. add or edit settings in appsettings.json
2. Check the App ID and password of bot
Now need to check whether the App ID and password are matching or not.
These instructions and procedure include CURL usage
To verify that your bot's app ID and password are valid, issue the following request using cURL, replacing APP_ID and APP_PASSWORD with your bot's app ID and password.
curl -k -X POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token -d "grant_type=client_credentials&client_id=APP_ID&client_secret=APP_PASSWORD&scope=https%3A%2F%2Fapi.botframework.com%2F.default"
This request attempts to exchange your bot's app ID and password for an access token. If the request is successful, you will receive a JSON payload that contains an access_token property, amongst others.
{"token_type":"Bearer","expires_in":3599,"ext_expires_in":0,"access_token":"eyJ0eXAJKV1Q..."}
3. Enable security and test on localhost
<appSettings>
<add key="MicrosoftAppId" value="APP_ID" />
<add key="MicrosoftAppPassword" value="PASSWORD" />
</appSettings>
if you are using bot framework SDK for .NET use the above code block
For complete reference of the procedure. Check

Related

How does authentication work or how to make protection from the mega-hacker Mr. Bob?

I`m developing angular + asp.net mvc app without Claim, JWT and other built-in tools.
My auth (authentication) system:
"Users" table:
namespace AwakenedTalents.Models
{
public class User
{
public string Id { get; set; } // I use guid here
public string Login { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public bool IsEmailConfirmed { get; set; }
}
}
When I login to the site, I send an encrypted (TrippleDES by key) Id from the ASPNET server and add it to the cookies on angular.
AuthenticationCheck (angular AuthService method):
IsAuth(): boolean {
if (this.cookies.get("authtoken")!="")
{
return true;
}
else
{
return false;
}
}
Thus, I check if the user is authenticated and call the command to get user data from the server:
UpdateUserData() {
$.get(env.environment.server_url+"/login/getuserdata?authtoken=" + this.cookies.get("authtoken")).done(response => {
if( response != "Not authenticate"){
userData.user = JSON.parse(response);
}
})
return userData.user;
}
Everything seems to be working fine until the mega-hacker Mr. Bob shows up. He steals other people's cookies in ANY way and replaces them with his own. Then he enters the site under the guise of another person, stealing his data. How to make protection from the mega-hacker Mr. Bob?
What did you try and what were you expecting? :
I watched youtube videos :)
You can protect your cookies by making them with the secure flag and the httponly flag. The secure flag will makes sure your cookie is only sent over an encrypted (https) connection. The httponly flag makes your cookie inaccessible to javascript. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
It's also a good idea to have verification information that you can validate in your cookie, such as including the sessionID as part of the encrypted content to validate it against the current user's session.

asp.net web api: only during sql connection - HTTP 500 Error occurs : Local host is currently unable to handle request

The Web Api throws HTTP 500 error when it has to reference values from sql database.
https://localhost:44304/api/values
This works fine.
But,
https://localhost:44304/api/User
throws HTTP 500 Error - Local host is currently unable to handle request
The API is a simple test one, which has to retrieve data from User table in SQL database.
private readonly string connectionString =
"Server=MyServerName\\SQLEXPRESS;Database=MyDatabase;Trusted_Connection=True;user
id=dbuser;password=dbuserpass;";
The data access file:
namespace UserLogin.Models
{
public partial class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
}
No changes being done to any portions of the default code after creating the Web API Component.
Note: using udl, the test connection to the database was successful.
Thanks for help.

Insert record with relationship using OData

This is what my models looks like
public User
{
public string Id { get; set; }
public string Username { get; set; }
public virtual Group Group { get; set; }
}
public Group
{
public string Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<User> Users { get; set; }
}
I using Azure Mobile TableController which using OData for CRUD.
Now I trying to insert new user by specifying the id of the group but instead it gives me an error which shows that instead of trying to associate it with my user model it trying to create new one:
{
"message": "The operation failed due to a conflict: 'Violation of PRIMARY KEY constraint 'PK_dbo.Groups'. Cannot insert duplicate key in object 'dbo.Groups'. The duplicate key value is (ad934511a82c4b42ae5427b5228737c6).\r\nThe statement has been terminated.'."
}
This is what my post looks like:
POST http://localhost/tables/user?ZUMO-API-VERSION=2.0.0 HTTP/1.1
{
email: 'test#test.com',
password: '#test',
group: {
id: 'ad934511a82c4b42ae5427b5228737c6'
}
}
Relationships are not directly supported in Azure Mobile Apps, but you can apply some workarounds to get it to work. Here's a blog post that walks through the scenario: 30 Days of Zumo.v2 (Azure Mobile Apps): Day 26: Relationship Advice.
The specific problem you're running into is the Entity Framework "detatched entities" problem. See e.g. Many to Many Relationships not saving. The problem is that Entity Framework has not loaded the child item into its context, so it thinks that it needs to insert the child item as well as the parent. (There have been long-standing feature requests in Entity Framework to solve this, but the feature has never been added.)
I just posted a similar answer here: How do I insert entities with a 1:n relationship in Azure App Service

ServiceStack JsonServiceClient: The requested resource does not support http method GET

So I recently remade my API and client in a new solution on a different version control scheme. Some of the code has change, but nothing related to the JsonServiceClient. Anyways, I'm getting this exception stating 405 Method Not Allowed Code: Method Not Allowed, Message: The requested resource does not support http method 'GET'.
The issue is that the request is not a GET but a POST, I'm not sure where its getting mixed up. The actual post is represented as such:
var result = (
await
webService.PostAsync(new Login
{
Token = token,
Provider = provider,
IsLinkedAccount = isLinkedAccount,
ResponseText = responseText,
Uuid = uuid,
Platform = platform
}))
The Login DTO is represented as this:
[Route("/login", "POST")]
public partial class Login
: IReturn<LoginDTO>
{
public virtual string Token { get; set; }
public virtual SocialNetworks Provider { get; set; }
public virtual string Email { get; set; }
public virtual bool IsLinkedAccount { get; set; }
public virtual string ResponseText { get; set; }
public virtual string Uuid { get; set; }
public virtual Platform Platform { get; set; }
}
And the actual API route is represented as this:
public class LoginController : ApiController
{
[AcceptVerbs("POST")]
public async Task<LoginDTO> Login(Login request)
{
...
}
}
And I've used swagger and postman to verify that the endpoint is indeed accurate and I can manually send an HTTP POST, so what messed up with the JsonServiceClient?
These is the service stack versions I'm using
<package id="ServiceStack.Client" version="4.0.52" targetFramework="net452"/>
<package id="ServiceStack.Common" version="4.0.52" targetFramework="net452"/>
<package id="ServiceStack.Interfaces" version="4.0.52" targetFramework="net452" />
<package id="ServiceStack.Text" version="4.0.52" targetFramework="net452" />

Unable to deserialize contract after changing route registration

I have an existing WCF Web API app that is registering routes using the following pattern:
RouteTable.Routes.Add(new ServiceRoute("MyService", new WebServiceHostFactory(), typeof(MyServiceImplementation)));
I recently updated to Preview 6. I also updated the registration pattern in Global.asax to use the enhancements extension:
routes.SetDefaultHttpConfiguration(new MyServiceConfiguration());
routes.MapServiceRoute<MyServiceImplementation>("MyService");
I also have a contract that I am posting to a method in a request.
[WebInvoke(UriTemplate = "/MyOperation", Method = "POST")]
Contact MyOperation(Contact contact);
...
[DataContract( Name = "Contact" )]
public class Contact : IExtensibleDataObject
{
[StringLength(50)]
[StringNotEmpty]
[DataMember(Name = "FirstName", Order = 1)]
public string FirstName { get; set; }
[DataMember(Name = "LastName", Order = 1)]
public string LastName { get; set; }
//[StringLength(50)]
//[DataMember(Name = "Location", Order = 1)]
//public String Location { get; set; }
public ExtensionDataObject ExtensionData { get; set; }
}
The issue I am getting is that when I post a previously acceptable contract, such as:
<Contact xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://myservice/schema">
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<Location i:nil="true" />
</Contact>
I get the following exception:
The server encountered an error processing the request. Please see the
service
help page for constructing valid requests to the service. The
exception message is 'The service operation 'MyOperation' expected a
value assignable to type 'Contact' for input parameter 'contact' but
received a value of type 'HttpRequestMessage`1'.'. See server logs for
more details.
I found that if I remove the xmlns="http://myservice/schema" from my request, the service accepts the request. I have existing api clients that will be making calls to the new service with this present, so I have to make sure these messages are accepted.
I understand that the WCF Web Api Enhancements (extension method) I am using uses different classes under the hood; but I am a little ignorant at the moment as to why one would be able to deserialize and the other would not.
Cheers.
The WCF Web API doesn use the DataContact serializer but the XmlSerializer so you will need to use those attributed to decorate your Contract class. Try adding the XmlRootAttribute with a Namespace to the Contract class.
[XmlRoot(Namespace = "http://myservice/schema")]
public class Contact
{
// ...
}

Resources