ASP.NET Identity Check email existence in custom UserValidator implementation - c#

In my application I created a custom version of the UserValidator so that I can configure the error messages myself.
Currently it's basically the implementation as found here, but with other resourcefile references.
The part I get stuck on is within the ValidateEmailAsync method.
It contains the line:
var email = await Manager.GetEmailStore().GetEmailAsync(user).WithCurrentCulture();
This gives the error that it cannot access GetEmailStore() method, since it's an internal method of the UserManager object.
Searching for a fix for that lead me to this question, and there it's advised to use this line instead:
var email = await Manager.GetEmailAsync(user.Id).ConfigureAwait(false);
But executing on that gives the exception that it couldn't find any user with the given Id.
Is there any other way to retrieve the email property for IUser object?
If needed, here's my current code.

Get the user like this, then grab the email;
var user = await Manager.GetUserAsync(User);
var email = user.Email;

Related

Getting more out of Request.HttpContext.User.Identity

When using MVC Core Identity, I am wondering if it is possible to get more information out of Request.HttpContext.User.Identity?
Currently, when I look at available, all it gives me back is Name, AuthenticationType, and IsAuthenticated.
What I would like to do for example is also get the Email address as well.
//Get User Manager From Owin Context
var userManager = HttpContext.GetOwinContext().GetUserManager<UserManager>();
var user = userManager.FindById(Convert.ToInt32(User.Identity.GetUserId()));
Using the above codes, it will return the full user object. I believe that solves your problem?

IdentityServer3 change subjectid/username during partial login

We're implementing our own SSO provider using IdentityServer3. We're almost done except that we have the requirement where when the user logs in for the first time they will have to change their username, password and supply other information. The problem lies with the change of the username: it needs to also change the subject id so when the partial login finishes the client also receives the new username, not the old one.
So what we need is a way, in the partial login, to change the sub claim. Searching the internet for this problem didn't give my any useful results. I've tried to change the claim but I'm unable to make it persist beyond the post request. I've done the following:
var ctx = Request.GetOwinContext();
var authentication = await ctx.Authentication.AuthenticateAsync(Constants.PartialSignInAuthenticationType);
authentication.Identity.RemoveClaim(identityResult.Identity.FindFirst("sub"));
authentication.Identity.AddClaim(new Claim("sub", model.NewUsername));
This, unfortunately, doesn't work because the claims I here have are just copies. What is the correct way to change the subject?
I've just discovered while looking in the IdentityServer3.Core.Extensions.OwinEnvironmentExtensions class, the same extensions class that hosts the GetIdentityServerPartialLoginAsync() method that there is a method named UpdatePartialLoginClaimsAsync(). This method accepts an enumerable of claims so I gave it my new sub claim, but this caused some unknown error (I'm not sure why), but when I gave it all the previous claims with the sub claim replaced everything worked as I wanted too.
var partialLogin = await OwinContext.Environment.GetIdentityServerPartialLoginAsync();
partialLogin.RemoveClaim(identityResult.Identity.FindFirst("sub"));
partialLogin.AddClaim(new Claim("sub", model.NewUsername));
await OwinContext.Environment.UpdatePartialLoginClaimsAsync(partialLogin.Claims);
The code above proved to be my solution.

Azure Active Directory Graph Client 2.0 - Context is not currently tracking the entity

I have recently installed the Azure Active Directory Graph Client Library 2.0.2 Nuget package and am unable to add Members to Groups both adding a group to a group or adding a user to a group I am getting the following error when the AddLink function is called:
“[System.InvalidOperationException] = {"The context is not currently tracking the entity."}
My code:
IGroup group = azureClient.Groups.GetByObjectId("Guid here").ExecuteAsync().Result;
IGroup groupToAdd = azureClient.Groups.GetByObjectId("Guid here").ExecuteAsync().Result;
azureClient.Context.AddLink(group, "Members", groupToAdd);
azureClient.Context.SaveChanges();
I have been unable to find any mention of this error in relation to the Azure Active Directory Graph Client Library from doing Google searches so any help on this would be much appreciated.
We’ve just released an update to the Graph client library, that fixes this problem.
You should now be able to add members to groups. The mechanism is a little different from using AddLinks (and hopefully simpler).
We also have a new blog describing the client library which talks about this and many other things: http://blogs.msdn.com/b/aadgraphteam/archive/2014/12/12/announcing-azure-ad-graph-api-client-library-2-0.aspx
For reference, to add a member to a group:
{groupObject}.Members.Add({entityObject} as DirectoryObject);
So for example, to update a group with a new user member:
myGroup.Members.Add(userToBeAdded as DirectoryObject);
await myGroup.UpdateAsync();
NOTE: The same construct can be used to add users to a DirectoryRole object. Groups and users may be added to a group, however, for now, only users can be added to a DirectoryRole.
Hope this helps,
I had the same issue, and the documentation wasn't very clear, so maybe this will help others. You cannot add users as members of an IGroup, but only to a Group. You also cannot add IDirectoryObjects to the Members collection, but only DirectoryObjects. You must first cast your IUser and IGroup objects. The following code is what I have working at the moment:
var graphClient = new ActiveDirectoryClient(new Uri(ConfigHelper.GraphServiceRoot), async () => await GetUserTokenAsync(cache));
var actualUser = await graphClient.Users.GetByObjectId(matchedUser.ObjectId).ExecuteAsync();
var actualGroup = (Group) await graphClient.Groups.GetByObjectId(matchedGroup.ObjectId).ExecuteAsync();
actualGroup.Members.Add(actualUser as DirectoryObject);
await graphClient.Context.SaveChangesAsync();
I tried this new syntax but still does not work.
public async Task<Result<dynamic>> addUserToAzureGroup(Group AzGroup, User AzUser)
{
// link the found user with the found group
try
{
AzGroup.Members.Add(AzUser as DirectoryObject);
await AzGroup.UpdateAsync();
}
catch (Exception ex)
{
Exception myEx = new Exception(ex.Message);
retResult.Exception = myEx;
return retResult;
}
return retResult;
}
I have almost the same error text in the execption message: The context is already tracking the relationship
Any news on that issue? Could anyone guess why that happens?
I also tried from the manage.windowsAzure.com UI and still cannot add the user! I get this error: Could not add members to group 'myAzAD_group'.

C# MVC4 windows username and cookie issues

First, I'm sad to say I'm not sure whether this code should be in the _Layout.cshtml or somewhere in the controller. It needs to run on all pages, so I've put it in the _Layout.cshtml page.
This is for an intranet web app. What I'm attempting to do is this: if a cookie (holding the user's userid) is not found, get the windows username, run it through a class that will go into the database and get the corresponding user's username, and - if we get a user id back - make a cookie containing it. Doesn't sound too hard, but one line in particular, and various incarnations of it, is refusing to be supportive. Here's the code as a whole.
if(!Context.Response.Cookies.AllKeys.Contains("userid")){
var winuser = System.Web.HttpContext.Current.User.Identity.Name;
var winuserid = myprojectname.Models.MyIntranetDataContext.getUserId(winuser).UserID();
if (winuserid == null) {
Response.Redirect("/someotherpage");
} else {
HttpCookie cookieuser = new HttpCookie("userid");
DateTime now = DateTime.Now;
cookieuser.Value = winuserid;
cookieuser.Expires = now.AddMonths(1);
Response.Cookies.Add(cookieuser);
}
}
Line 2 - var winuser... - appears to be the problem. In this current incarnation, I'm getting a build error: An object reference is required for the non-static field, method, or property 'myprojectname.Models.MyIntranetDataContext.getUserId(string)'
It doesn't like it when I add a .ToString to it either.
I've tried making winuser this as well:
Page.User.Identity.Name;
That gave no build errors. When I attempt to Start Debugging, she blows up with this beauty of an error: 'Cannot perform runtime binding on a null reference'
Once I get the windows username, all will be well.
Really, this isn't about cookies, or even mvc to much of an extent (except maybe guidance on where to put this code - the _Layout.cshtml?). Really it's about getting the windows username, which I seem unable to do. Thanks in advance for any assistance you are able to provide.
Note, the above names aren't actual - just for example only.
If they are on the domain, couldn't you use something like the following to retrieve that information?
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal principal = (WindowsPrincipal)Thread.CurrentPrincipal;
WindowsIdentity identity = (WindowsIdentity)principal.Identity;
String userName= principal.Identity.Name;

Session not getting retrieved in Facebook C# SDK example

I am a newbie at ASP.net programming. This is in reference to the Facebook C# SDK, I have managed to set up all the steps required for authentication on this SDK. However, I keep getting a null from the following code:
(reference: http://csharpsdk.org/docs/web/getting-started#5)
var accessToken = Session["AccessToken"].ToString(); //This line returns null and crashes
var client = new FacebookClient(accessToken);
dynamic result = client.Get("me", new { fields = "name,id" });
string name = result.name;
string id = result.id;
Just like in the example, I had set up a generic handler to set up the session variable to be stored in the HttpContext.Session object.
I even tried to modify the offending line to directly access the HttpContext and retrieve the access token:
var accessToken = HttpContext.Current.Session["AccessToken"].ToString();
but this yielded the same result.
Have I missed out something in the webconfig or is there some other way I can store the access token when shifting from the handler to the log in page?
Make sure in your Facebook developer settings that you do not have query string selected for your app as auth token paramenter!!!
This is the default mode and this wont work unless you do the following:
http://developer.facebook.com
Open your app page.
Then go Settings --> Auth Dialog --> Auth Token Parameter and select URI Fragment.
100% sure this is your problem. It's not included in any literature I found, and it's a damn shame.
If it is returning null then I would assume that the Session value is not being set - have you debugged to make sure the code which sets the session is being hit?
Looking at the linked article - it uses a HttpHandler to do this bit but does not mention anything about registering it in the Web.Config - have you done this? If not see here http://msdn.microsoft.com/en-us/library/46c5ddfy.aspx

Categories