I am doing authentication using azure mobile apps in my xamarin forms app and once I retrieve unique User Authentication Id, I am storing this with bunch of other user information into a sync table called Users as shown below.
So basically I am also using Azure Mobile Sync in my app. Id column below is predefined Azure Mobile Id. Everything works fine as long as I have same user with Id stored in Local sync db.
Once, if I lose this local Db information (It can be caused by reinstalling app or deleting app data). User will prompt to re-login and although I get the same Azure Authentication Id, snyc will cause a new insert into Azure Users table. Because it doesnt know that it is an existing row.
Possible Solutions is to make userAuthId as PK (eventually it is unique). But if I do that I will lose azure mobile sync feature, wont I? Can somebody shade me lights how to make Custom Id column for azure mobile sync? or instead of auto generate, i can pass the value from client.
I encountered the similar issue before, I just set the value of Id column in my users table to UserAuthId. For adding the additional UserAuthId and use it as the foreign key in other tables, I assumed that after user logged, you need to check the online Users table and try to retrieve the existing user record based on the current UserAuthId, then you could insert/update your local data store or directly update your online Users table. Moreover, I would recommend you follow adrian hall's book here about developing Azure Mobile Apps with Xamarin.
I found a solution myself following suggestion from Bruce Chen. Basically just remove the Default Value or Binding as shown in the image and on your backend Api change the Post function as below and also your controller should retrieve UserId from the authentication by calling ClaimsPrincipal as below. Using this method, you get the authenticated UserId within your Api. You can see the full implementation on this github link. So you can pass this as Id of the table. I also added extra check before I insert that if Id is already exist or not since I am not auto generating the Id.
I hope this helps to anybody else having same problem.
public string UserId => ((ClaimsPrincipal)User).FindFirst(ClaimTypes.NameIdentifier).Value;
public async Task<IHttpActionResult> PostUser(User item)
{
try
{
User current;
item.Id = UserId;
myAppsAPIContext db = new myAppsAPIContext();
User User = db.Users.Where(u => u.Id == UserId).SingleOrDefault();
if (User == null)
{
current = await InsertAsync(item);
}
else
current = User;
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
catch (Exception ex)
{
TelemetryClient.TrackException(ex);
return null;
}
}
Related
My User Class uses a Trait which creates tables on behalf of a new user registered.
I want to access the new user id number to use it in the table naming like below (which does not work).
static::creating(function($obj)
{
if (empty($obj->db_name)) {
$obj->attributes['table_id'] = 'user_' . $obj->id;
}
});
How can I access the id of this new user during the creating process so I can create and save the record without going back using created method to update the column.
creating occurs before the record is saved - it has no ID yet. You may want to hook into the created event instead, which occurs after the record has been saved and has an ID.
I have two entities BlogPost and user im not sure how the follow mechanism works I have searched on S.O but could not get an idea
What I think
I think follow is some sort of Get posts where userID = ?
but also it should be a continues process ie when user posts again it should automatically get the new post, until user unfollows.
I would like some suggestions on how to go about implementing and what i will need.
What i am trying to create
I want to create a service that subcribes to a user (like in the social networks such linkedIn, so a user can follow another user there by getting all the users new activities such as new posts (new uploads)
public void subscribeToUser(String id){
//follow a user by id
//im not sure the relationship i should create between the entities
// user and posts so that when one user creates a post
// another user can subscribe to the first user and can see all the posts and future posts of the user
}
}
I am calling this method from within a Controller method while logged in as a user, with the standard DefaultMembershipProvider code in MVC5 that comes completely out of the box. Like this:
string LoggedInUsersId = User.Identity.GetUserId();
When debugging, this method call returns a GUID that is completely different to the "Id" field GUID stored in the AspNetUsers table. As I only have one user in this table, I have no idea where this other GUID is coming from?
I thought that the Id field value from the AspNetUsers table would be returned for the currently logged in user when you call User.Identity.GetUserId()?
I am definitely checking the same database/environment and looking at the right place.
Solved!
Thanks to this blog post (see point #2):
https://digitaltoolfactory.net/blog/2013/10/five-things-should-should-know-about-the-new-asp-net-identity-membership-system/
The new MVC5 membership stuff had automatically created a new local database on my laptop called "DefaultConnection" where it had generated and placed all the membership tables and data. So GetUserId() was returning a GUID that lived locally in the AspNetUsers table from that local database which did not exist in my other main database that the application was using! Gah.
So the fix was changing this line inside of IdentityModels.cs:
public ApplicationDbContext() : base("DefaultConnection") { }
to:
public ApplicationDbContext() : base("MyConnectionString") { }
Now it works and everything is saved centrally into my application's main database.
Scenario: my app runs queries where the user id is used in many cases to filter what data the user can see. The user id is an integer. I don't want the user to be able to simply alter the query string and change the user ID parm to another # (and essentially assume another user's identity). Through our authentication process, each request to the server includes a security token in the header, which was returned to the client when they logged in. During the auth process, this token is stored on the server and is mapped to the user's user id.
What I would like to do is pull the token out of the header, do a lookup and get the user ID that is mapped to the token value (got that working), and then alter the query string to add the user ID.
So a request may come in as
http://localhost/api/app/customerlist
And after I get the user id, it may look like this
http://localhost/api/app/customerlist?$filter=userid%20eq%1234
And then continue on.
This is a simple scenario but illustrates my goal. I am not able to add surrogate keys to the database and use a GUID or some other value as my filter column. Pretty much stuck with the structure.
Thanks
On the server side you can add any filters directly to whatever IQueryable is returned. If you use the Authorize attribute you can also access the user data via the "User" variable.
[BreezeController]
[Authorize]
public class NorthwindIBModelController : ApiController {
[HttpGet]
public IQueryable<Customer> CustomerList() {
var userName = User.Identity.Name;
var filter = filter on customers;
var custs = ContextProvider.Context.Customers.Where({ some filter using userName});
}
}
Also see:
Passing username to Web Api methods in ASP.NET MVC 4
Take a look at the EntityQuery.withParameters method. With it from the client you can take any query and add your user id filter to it. Something like
myQuery = myQuery.withParameters( { userId: 1234});
myEntityManager.executeQuery(myQuery).then(...);
Or am I missing something.
For integration purposes our users in Dynamics CRM need to have the same GUIDs as in the rest of our environment (several custom web apps built on ASP.NET and SQL Server 2005). But when we try to create a new Dynamics user with a certain GUID, Dynamics just ignores it and creates its own (the pattern of which leads me to believe that it’s using NEWSEQUENTIALID() internally, just as if the user was created through the UI). But for other types (contact for example) Dynamics takes the GUID with no issue.
Am I doing something wrong, or does Dynamics always ignore GUIDs on new user creation?
CrmService service = GetService();
systemuser newUser = new systemuser();
Key newUserId = new Key();
newUserId.Value = new Guid("D630FA8D-A32F-4a37-BFEF-CE36CBA29009");
// The GUID I would like Dynamics to use
newUser.systemuserid = newUserId;
Lookup bu = new Lookup();
bu.Value = new Guid("16B10365-0E18-DF11-B839-005056B60DD4");
// The correct business unit ID. Nothing to see here.
newUser.businessunitid = bu;
newUser.firstname = "John";
newUser.lastname = "Doe";
newUser.domainname = "DOMAIN\\jdoe";
// Valid AD credentials too. Names changed to protect the innocent.
Guid userId = service.Create(newUser);
Console.WriteLine("User created with GUID " + userId.ToString());
// Dynamics creates the user with a completely different GUID. :-(
Edit:
I've now asked this question on Microsoft's CRM forum as well.
I know it is not ideal, but as a workaround you could add a custom attribute to the systemuser entity and store your integration id there.
Without knowing more about your solution I can tell you that you don't need hardcoded quids everywhere like you are trying to do. When I arrived at my current client they were trying to do the same things and it was a serious PITA.
It took me about a day to replace all the code that was using the hardcoded quids for various entities with a simple lookup procedure that gets the entity by whatever key (user name in your case) you want and then get the entity's id from that. No more trying to do something you should be trying to do in the first place.
It took me about a day to replace all the code that was using the hardcoded quids for various entities with a simple lookup procedure that gets the entity by whatever key (user name in your case)
How interesting. You're searchnig John Doe user by 'John','Doe' strings. And what should I do if I got TWO "John Doe" in my company ?