Roles added to the user does give false in IsInRole - asp.net-core-mvc

I am trying to use [Authorize(Roles = "Administrator")]
But I always get "Access denied".
To test if i added the roles correct i added the following code in my controller:
var test=User.IsInRole("Administrator");
var user = await userManager.GetUserAsync(User);
var roles =await userManager.GetRolesAsync(user);
rolesOfUser = roles.ToList();
Have I added the role wrong?
Why does IsInRole always return false? is suggesting that the user is not signin or completed all authentication process. If the is the case how do i do that?
Seeding data:
public async Task SeedAsync()
{
context.Database.EnsureCreated();
if (await roleManager.RoleExistsAsync("Administrator") == false)
{
await roleManager.CreateAsync(new IdentityRole("Administrator"));
}
var user = await userManager.FindByEmailAsync("Jakob.Madsen#********.com");
if (user == null)
{
user = new IdentityUser()
{
UserName = "Jakob.Madsen#*********.com",
PhoneNumber = "*********",
Email = "Jakob.Madsen#*********.com",
};
var result = await userManager.CreateAsync(user, "*********");
if (result == IdentityResult.Success)
{
userManager.AddToRoleAsync(user, "Administrator").Wait();
}
else
{
throw new InvalidOperationException("Could not create Administrator");
}
}
var resultRoles = await userManager.GetRolesAsync(user);
if (resultRoles.Contains("Administrator") == false)
{
userManager.AddToRoleAsync(user, "Administrator").Wait();
}
}
Update:
I follow this ASP .Net Core Identity Role Claims not adding to User as suggested.
And it now works.

The IsInRole method and [Authorize(Roles="Administrator")] attribute check whether an identity that this claims principal possesses contains a claim of type ClaimsIdentity.RoleClaimType(http://schemas.microsoft.com/ws/2008/06/identity/claims/role) where the value of the claim is equal to the value specified by the role parameter.
So to summarize, if you call IsInRole, by default the assumption is that your claims representing roles have the type mentioned above – otherwise the role check will not succeed. You can confirm that by listing the claims :
var claims = User.Claims.ToList();
You haven't provide how you seed the roles , but you can find a lot of code samples :
ASP.NET Core 2.0: Getting Started With Identity And Role Management
.NET Core 2.1 Use Role Management
Also don't forget to logout and login again to see the desired behavior .

Related

Automatically map a Contact to an Account

I want to add a field to Accounts which shows the email domain for that account e.g. #BT.com. I then have a spreadsheet which lists all the Accounts and their email domains. What I want to do is when a new Contact is added to Dynamics that it checks the spreadsheet for the same email domain (obviously without the contacts name in the email) and then assigned the Contact to the Account linked to that domain. Any idea how I would do this. Thanks
Probably best chance would be to develop CRM plugin. Register your plugin to be invoked when on after contact is created or updated (so called post-event phase). And in your plugin update the parentaccountid property of the contact entity to point to account of your choice.
Code-wise it goes something like (disclaimer: not tested):
// IPluginExecutionContext context = null;
// IOrganizationService organizationService = null;
var contact = (Entity)context.InputParameters["Target"];
var email = organizationService.Retrieve("contact", contact.Id, new ColumnSet("emailaddress1")).GetAttributeValue<string>("emailaddress1");
string host;
try
{
var address = new MailAddress(email);
host = address.Host;
}
catch
{
return;
}
var query = new QueryExpression("account");
query.TopCount = 1;
// or whatever the name of email domain field on account is
query.Criteria.AddCondition("emailaddress1", ConditionOperator.Contains, "#" + host);
var entities = organizationService.RetrieveMultiple(query).Entities;
if (entities.Count != 0)
{
contact["parentaccountid"] = entities[0].ToEntityReference();
}
organizationService.Update(contact);
I took Ondrej's code and cleaned it up a bit, re-factored for pre-operation. I also updated the logic to only match active account records and moved the query inside the try/catch. I am unfamiliar with the MailAddress object, I personally would just use string mapping logic.
var target = (Entity)context.InputParameters["Target"];
try
{
string host = new MailAddress(target.emailaddress1).Host;
var query = new QueryExpression("account");
query.TopCount = 1;
// or whatever the name of email domain field on account is
query.Criteria.AddCondition("emailaddress1", ConditionOperator.Contains, "#" + host);
query.Criteria.AddCondition("statecode", ConditionOperator.Equals, 0); //Active records only
var entities = organizationService.RetrieveMultiple(query).Entities;
if (entities.Count != 0)
{
target["parentaccountid"] = entities[0].ToEntityReference();
}
}
catch
{
//Log error
}

hosted parse Cloud code find(...) does not retrieve sessionToken

I am migrating Parse.com cloud code to hosted parse-server. Mongodb is already migrated.
The code is supposed to retrieve a user's sessionToken according to its google plus id. The find operation succeeds and a user is returned but the user does not have any sessionToken.
EDIT regarding mongodb:
Checking mongo db directly - the _User table record holds a _session_token value. In the _Session table I could not find that _session_token. Also I could not find any entry for that _User (I concatenated _User$ when searching).
The code is (more or less) so:
Parse.Cloud.define("getParseUserSessionToken", function(request, response) {
var googlePlusId = ...;
// here we're doing some code to get the google id
// assume it is set
var googleIdQuery = new Parse.Query(Parse.User);
googleIdQuery.equalTo(GOOGLE_PLUS_ID_FIELD_KEY, googlePlusId);
searchUserQuery.find({
useMasterKey: true
}).
then(function(users) {
if (users && users.length > 0) {
var user = users[0]; //user exist
var token = user.getSessionToken();
if (token) {
//user exist, return sessionToken
// ....
} else {
// CODE REACHES HERE AS THERE'S NO TOKEN
// return error: "no token"
}
}
}
As you can see I pass userMasterKey: true to find()
With a debugger I can see that I get a user with data, but without a token. I tried several things but nothing works.
Any idea what am I missing?

(Windows Phone 10) Is possible to edit, add new contact programmatically in windows phone 10?

I want to implement function edit and add contact programatically in windows phone 10.
Is it possible? Has any sample about it ?
Here is a code snippet for creating the contact:
public async Task AddContact(String FirstName, String LastName)
{
var contact = new Windows.ApplicationModel.Contacts.Contact();
contact.FirstName = FirstName;
contact.LastName = LastName;
//Here you can set other properties...
//Get he contact store for the app (so no lists from outlook and other stuff will be in the returned lists..)
var contactstore = await Windows.ApplicationModel.Contacts.ContactManager.RequestStoreAsync(Windows.ApplicationModel.Contacts.ContactStoreAccessType.AppContactsReadWrite);
try
{
var contactLists = await contactstore.FindContactListsAsync();
Windows.ApplicationModel.Contacts.ContactList contactList;
//if there is no contact list we create one
if (contactLists.Count == 0)
{
contactList = await contactstore.CreateContactListAsync("MyList");
}
//otherwise if there is one then we reuse it
else
{
contactList = contactLists.FirstOrDefault();
}
await contactList.SaveContactAsync(contact);
}
catch
{
//Handle it properly...
}
}
And here is a short sample for changing an existing contact:
//you can obviusly couple the changes better then this... this is just to show the basics
public async Task ChangeContact(Windows.ApplicationModel.Contacts.Contact ContactToChange, String NewFirstName, String NewLastName)
{
var contactStore = await Windows.ApplicationModel.Contacts.ContactManager.RequestStoreAsync(Windows.ApplicationModel.Contacts.ContactStoreAccessType.AppContactsReadWrite);
var contactList = await contactStore.GetContactListAsync(ContactToChange.ContactListId);
var contact = await contactList.GetContactAsync(ContactToChange.Id);
contact.FirstName = NewFirstName;
contact.LastName = NewLastName;
await contactList.SaveContactAsync(contact);
}
And very important:
In the appxmanifest you have to add the contacts capability. Right click to it in the solution explorer and "View Code" and then under Capabilities put
<uap:Capability Name="contacts" />
There is no UI for this. See this.
Both samples are meant to be for starting point... obviously it's not production ready and you have to adapt it to your scenario.
Update
Since this came up in the comments I extend my answer a little bit.
Based on this (plus my own experimentation) the ContactListId for aggregated contacts is null (which makes sense if you think about it). Here is how to get the raw contact with ContactlLstId (code is based on the comment from the link)
public async Task IterateThroughContactsForContactListId()
{
ContactStore allAccessStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
var contacts = await allAccessStore.FindContactsAsync();
foreach (var contact in contacts)
{
//process aggregated contacts
if (contact.IsAggregate)
{
//here contact.ContactListId is "" (null....)
//in this case if you need the the ContactListId then you need to iterate through the raw contacts
var rawContacts = await allAccessStore.AggregateContactManager.FindRawContactsAsync(contact);
foreach (var rawContact in rawContacts)
{
//Here you should have ContactListId
Debug.WriteLine($"aggregated, name: {rawContact.DisplayName }, ContactListId: {rawContact.ContactListId}");
}
}
else //not aggregated contacts should work
{
Debug.WriteLine($"not aggregated, name: {contact.DisplayName }, ContactListId: {contact.ContactListId}");
}
}
}
And another important thing:
According to the documentation you won’t be able to change all the contacts which are created by other apps.
AllContactsReadWrite:
Read and write access to all app and system contacts. This value is
not available to all apps. Your developer account must be specially
provisioned by Microsoft in order to request this level of access.
In some cases, I get a System.UnauthorizedAccessException when SaveContactAsync(contact) is called. One example for this was when the contact was in the Skype Contact List.

I can't login with WebSecurity.Login and I get WebSecurity.CurrentUserId as -1.

I am trying to register a user and place his order in same action for unregistered users. Please see problematic part of my code below. I get WebSecurity.CurrentUserId as -1 here. Therefore I cant find users and add user info to order. What is wrong here. It should be Id of newly registered user. Thanks for your helps.
WebSecurity.CreateUserAndAccount(UpperEmail, user.Password, new { user.Password, user.PasswordConfirm, user.Email, user.Name }, false);
int userId = db.Users.FirstOrDefault(u => u.Email == user.Email).Id;
if (!Roles.RoleExists("User"))
Roles.CreateRole("User");
Roles.AddUserToRole(UpperEmail, "User");
WebSecurity.Login(UpperEmail, user.Password);
neworder.user = db.Users.Find(WebSecurity.CurrentUserId);
neworder.UserId = WebSecurity.CurrentUserId;
neworder.PaymentStatus = PaymentStatus.Onaylandi;I

parse.com inherited ACL + roles - afterSave or beforeSave, tricky scenario

Here's what I am trying to achieve but somehow I am stuck and I am not sure what's the proper approach, I cannot find any good examples of such case so I am seeking your help.
Each registered user can add new object to class "List". Once the new item is created I call afterSave function and assign proper ACL creating new role ("membersOf_" + List.id). Next, user can add new object to class "Items", which will store List.id as a reference and ACL for item should be inherited from list. Lists and Items can be shared between multiple users of their choice. There are few problems in such case:
when creating new List, I need to create new role and assign creator to it and add such role to created List
when creating new Item, I need to pass List.id as a payload and validate with cloud code if current user can create such item (assigned to specified List) by checking first if he has proper permissions to List
if permission check is ok, I need give this item the same ACL as List has and proceed with saving
Here's my afterSave for List, creating role properly and assigning ACL to List object. (1) I am missing adding this role to user (creator)
Parse.Cloud.afterSave("List", function(request, response) {
var list = request.object;
var user = Parse.User.current();
if (list.existed()) {
// quit on update, proceed on create
return;
}
var roleName = "membersOf_" + list.id;
var listRole = new Parse.Role(roleName, new Parse.ACL(user));
return listRole.save().then(function(listRole) {
var acl = new Parse.ACL();
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
acl.setReadAccess(listRole, true);
acl.setWriteAccess(listRole, true);
var itemData = new Parse.Object("List", {
ACL: acl
});
return itemData.save('objectId', list.id);
});
// to do - add user to this role too
});
Here's my Item beforeSave to validate if user can actually create such object, I am checking if he can query the List table, if he get >0 results for such List that means he will be ok to adding an Item assigned to this List. (2) Missing ACL inheritance
Parse.Cloud.beforeSave("Item", function(request, response) {
var item = request.object;
var listId = request.object.get("list");
var user = Parse.User.current();
var List = Parse.Object.extend("List");
var query = new Parse.Query(List);
query.equalTo("objectId", listId);
query.first({
success: function(list) {
if (list.id) {
response.success();
}
else {
response.error('No such list or you don\'t have permission to perform this operation.');
}
},
error: function(error) {
response.error(error);
}
});
});
Can someone point me to the proper solution or help solve that puzzle? I am missing two things:
- (1) I need to add user (creator) to new role created in afterSave
- (2) I need to add the same ACL to Item, inherit it from List object
I have tried many things, passing ACL in afterSave for Item, modifying payload in beforeSave. Many different functions following documentation and different examples, but still no luck.
Any advice would be awesome!
Ok, I think I finally figured it out. Hopefully this will help someone in future.
Here are final beforeSave and afterSave functions adding user to specified role and assigning the same ACL to Item object
Parse.Cloud.afterSave("List", function(request, response) {
var list = request.object;
var user = Parse.User.current();
if (list.existed()) {
// quit on update, proceed on create
return;
}
var roleName = "membersOf_" + list.id;
var listRole = new Parse.Role(roleName, new Parse.ACL(user));
//+ adding user to role in this line:
listRole.relation("users").add(user);
return listRole.save().then(function(listRole) {
var acl = new Parse.ACL();
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
acl.setReadAccess(listRole, true);
acl.setWriteAccess(listRole, true);
var itemData = new Parse.Object("List", {
ACL: acl
});
return itemData.save('objectId', list.id);
});
// to do - add user to this role too
});
Parse.Cloud.beforeSave("Item", function(request, response) {
var item = request.object;
var listId = request.object.get("list");
var user = Parse.User.current();
// + modifying payload with the same ACL here
var acl = new Parse.ACL();
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
acl.setRoleWriteAccess("membersOf_" + listId, true);
acl.setRoleReadAccess("membersOf_" + listId, true);
item.set('ACL', acl);
var List = Parse.Object.extend("List");
var query = new Parse.Query(List);
query.equalTo("objectId", listId);
query.first({
success: function(list) {
if (list.id) {
response.success();
}
else {
response.error('No such list or you don\'t have permission to perform this operation.');
}
},
error: function(error) {
response.error(error);
}
});
});

Resources