Get Current User ASP.NET Visual Studio 2013 Preview ClaimsPrinciple - asp.net

I'm trying to get the current user in a web forms project using the new Visual Studio 2013 Preview for Web. I'm able to get the username using Page.User, but trying to get the user id is where I'm stuck. It's using this new Identity Model thing they've come out with.
This is what I've got:
//Gets the correct username
string uname = User.Identity.Name;
//Returns a null object
Microsoft.AspNet.Identity.IUser user = IdentityConfig.Users.Find(uname);
//What I hope to call to add a user to a role
IdentityConfig.Roles.AddUserToRole("NPO", user.Id);

If you are using the Default Membership that come's with the ASP.NET WebForms Template you should do something like this to retrieve the user:
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
}
The new model you are talking about is ClaimsPrincipal. The unique difference is this Claims Based Secury, that is completly compatible with the older versions but more powerfull.
EDIT:
To add an user to some Role programaticaly you should do this, passing the user name and the role name:
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
System.Web.Security.Roles.AddUserToRole(userName, "Role Name");
}
Using the new Claim Based Security
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
ClaimsPrincipal cp = (ClaimsPrincipal)HttpContext.Current.User;
GenericIdentity genericIdentity;
ClaimsIdentity claimsIdentity;
Claim claim;
genericIdentity = new GenericIdentity(userName, "Custom Claims Principal");
claimsIdentity = new ClaimsIdentity(genericIdentity);
claim = new Claim(ClaimTypes.Role, "Role Name");
claimsIdentity.AddClaim(claim);
cp.AddIdentity(claimsIdentity);
}

The user id is stored in the ClaimTypes.NameIdentifier claim by default. We provided an extension method as well that lives in Microsoft.AspNet.Identity so you can simply call Page.User.Identity.GetUserId(), instead of fetching the user just to get out the id.

Just a post for people who find this today this is now very easy to accomplish
ApplicationUserManager manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
ApplicationSignInManager signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
ApplicationUser user = signinManager.UserManager.FindByNameAsync("username").Result;
At this point you have access to everything Id, Email, Phone number, Even the Hashed version of the user password.

Related

Getting the full user name from User.Identity in Razor.Pages project when authenticating using Azure AD

I am developing my Razor.Pages web application in .Net Core 3.1 and I configured the authentication using my company AD. I can use without any problem the User.Identity.Name to get the user#domain value but I need to get the full name of the person that is logged in so that I can filter some results of a query to an SQL DB based on the user's full name.
I tried googling around but didn't find anything a solution to my problem. Thanks!
After doing some digging around I finally managed to create a method that receives the User.Identity.Name of the logged in user and returns the full name.
Bellow is a snippet of the method!
public static string GetFullName(string domainName)
{
string fullName = "";
UserPrincipal principal;
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
principal = UserPrincipal.FindByIdentity(ctx, domainName);
}
if (principal != null)
fullName = $"{principal.GivenName} {principal.Surname}";
else
fullName = domainName;
return fullName;
}

Implementing role based authorization in MVC and Web API with custom table

I have inherited an application with database. The database has following tables related to authentication and authorization.
User Table
UserName
Password
UserTypeId
UserType Table
UserTypeId
UserTypeDesc
The User Type table stores the roles for the user e.g. Admin, Editor, etc.
If I want to implement authorization like below
[Authorize(Roles="Admin, Editor")]
public IHttpActionResult GetOrders()
{
//Code here
}
Where and what should I code so that the roles are available to the authorize attribute ?
Edit
I already have a database. So I cannot use the AspNetUserRoles or AspNetRoles tables. I need to set the roles using my custom tables.
Edit2
As asked by #Nkosi, here is code snippet of how authentication is implemented. The actual implementation calls the business layer service and performs encryption and other stuff but I have simplified the snippet
public HttpResponseMessage Authenticate(User user)
{
var isValid = myRepository.Exists(a => a.UserName == user.UserName && a.Password == user.Password);
if(isValid)
{
FormsAuthentication.SetAuthCookie(user.UserName,false);
}
}
This method is called from the login page where user enters the UserName and Password
Using these Answers for reference
Having Trouble with Forms Authentication Roles
FormsAuthentication Roles without Membership
After having set the auth cookie on login like you did originally,
you do the following in your Global.asax.cs
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
FormsIdentity formsIdentity = new FormsIdentity(ticket);
ClaimsIdentity claimsIdentity = new ClaimsIdentity(formsIdentity);
//get the user from your custom tables/repository
var user = myUserRepository.GetUserByEmail(ticket.Name);
if(user!=null){
var userTypeId = user.UserTypeId;
var role = myUserTypeRepository.GetUserTypeById(userTypeId);
if(role != null) {
//Assuming the roles for the user e.g. Admin, Editor, etc.
// is in the UserTypeDesc property
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role.UserTypeDesc));
}
}
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
System.Threading.Thread.CurrentPrincipal = claimsPrincipal ;
if (System.Web.HttpContext.Current != null) {
System.Web.HttpContext.Current.User = claimsPrincipal ;
}
}
}
The nice thing about how they implemented it is that it handles Claims based roles using the ClaimsIdentity and ClaimsPrincipal objects, without putting the roles in the user's cookie. It also handles authentication in the Global.asax.cs file without having to resort to putting in custom authorize attributes.
Your question was very easy. You just need to sync these 2 tables with AspNetUserRoles and AspNetRoles tables respectively. Actually, Authorize attribute by default checks these two tables. So your roles need to reflect in them. These tables are made by default by EF if you select MVC template project.

ASP.NET MVC 5 Default WebApp Forgot Password module missing?

In MVC 4 with SimpleMembership all these functions come with the default webbapp that you create in Visual Studio.
I was wondering where I can find the same for MVC 5 using the new ASP.NET Identity membership system? Is there some official blog or something that is beeing hidden from me in google search results?
UPDATE1: http://blogs.msdn.com/b/webdev/archive/2013/12/20/announcing-preview-of-microsoft-aspnet-identity-2-0-0-alpha1.aspx
UPDATE2: ASP.NET Identity 2.0 RTM has been released. Forgot Password is included in the samples/templates. http://blogs.msdn.com/b/webdev/archive/2014/03/20/test-announcing-rtm-of-asp-net-identity-2-0-0.aspx
We are working on adding these features to the ASP.NET Identity system and the MVC 5 templates.
I ran into this as well. To fix it, I created some controller actions in AccountController.cs (and corresponding views) to handle it.
Here are the actual lines that reset the user's password:
[AllowAnonymous]
[HttpPost]
public ActionResult ResetForgottenPassword(string key, ManageUserViewModel model)
{
var user = db.Users.SingleOrDefault(u => u.ForgotPasswordCode != null && u.ForgotPasswordCode == key);
if (user == null || !user.ForgotPasswordDate.HasValue || user.ForgotPasswordDate.Value.AddDays(1) < DateTime.UtcNow)
return new HttpUnauthorizedResult();
ModelState state = ModelState["OldPassword"];
if (state != null)
{
state.Errors.Clear();
}
if (ModelState.IsValid)
{
if (UserManager.HasPassword(user.Id))
UserManager.RemovePassword(user.Id);
IdentityResult result = UserManager.AddPassword(user.Id, model.NewPassword);
if (result.Succeeded)
{
//Clear forgot password temp key
user.ForgotPasswordCode = null;
user.ForgotPasswordDate = null;
db.SaveChanges();
//Sign them in
var identity = UserManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, identity);
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
}
else
{
AddErrors(result);
}
}
ViewBag.ForgotPasswordCode = key;
return View(model);
}
Some custom items are the new fields on the user object:
ForgotPasswordCode and ForgotPasswordDate to keep track of the user throughout the "reset password email" process.
I pass the key around in in the ViewBag once the user arrives from the email link.
The db variable is a property of my database context class inherited from a base controller.
I use UTC DateTimes in my database. Change DateTime.UtcNow to DateTime.Now if you do not.
Probably not the best solution, but it's a fairly quick and simple patch.
You can build a reset password by yourself (not sure that is the better choice, but is better than nothing)
Generate the hash with:
var newPwdHash = new PasswordHasher().HashPassword(newPasswordPlain)
And replace to the user's passwordhash property
If you cannot wait for the ASP.NET Identity Team to add this feature you can get an implementation of password reset from the open source project SimpleSecurity. Just take a look at the ResetPassword action on the AccountController. You can read about how the password reset was implemented here. Although the article references SimpleMembership, SimpleSecurity uses the same API to support either SimpleMembership or ASP.NET Identity in your MVC application.

ASP.NET Added Claims are Missing

I have an asp.net application that authenticates against a third party via ADFS. Once authentication is successful, the user is redirected to a landing page where claims for the user are pulled from a database. I populate the user's claims using the following code:
IClaimsPrincipal principal = Thread.CurrentPrincipal as IClaimsPrincipal;
IClaimsIdentity claimsIdentity = (IClaimsIdentity)principal.Identity;
foreach (string claim in customClaims)
{
Claim newClaim = new Claim(ClaimTypes.Role, claim);
claimsIdentity.Claims.Add(newClaim);
}
Once I have populated the claims, I save the IClaimsPrincipal to session. Here is where things get odd. After the user is redirected from the landing page to their desired page, the claims are missing. If I query the the claims using the following code...
IClaimsPrincipal principal= Thread.CurrentPrincipal as IClaimsPrincipal;
IClaimsIdentity claimsIdentity = (IClaimsIdentity)principal.Identity;
foreach (Claim claim in claimsIdentity.Claims)
{
Response.Write(claim.ClaimType + ": " + claim.Value + "<br/>");
}
...I don't get back any of the added claims. Instead I only have the original claim given me from ADFS (the username). The odd thing is that if I pull the IClaimsPrincipal out of Session, and query it's collection of claims, I get back all of the claims I added. What is going on here?
You should use the ClaimsAuthenticationManager extensibility point to pull more claims - everything you add there will automatically (and probably correctly) saved to the authentication session.
Try updating the session cookie after adding the claims, example:
var user = HttpContext.User as ClaimsPrincipal;
var claims = new List<Claim>();
claims.Add(new Claim("MyClaimType", "MyClaimValue"));
user.AddIdentity(new ClaimsIdentity(claims));
// Update cookie
var sam = FederatedAuthentication.SessionAuthenticationModule;
if (sam != null)
{
var token = new SessionSecurityToken(user);
sam.WriteSessionTokenToCookie(token);
}
I believe if you manipulate claims outside the "WIF controlled" methods like ClaimsAuthorizationManager then you have to manually update the authentication session cookie or else you lose all the changes.

I implemented custom authentication but how to get UserID through application

I implemented custom authentication/authorization based on this tutorial http://www.mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx
It works fine. I implemented it because I don't want to have stored procedures in my database and possibility to use different RDBMS.
But I have one issue here. I authenticate user but I don't know how to store UserId somewhere so when I need to get something from database based on UserID to get it. Something like:
List<Product> products = productsRepository.GetProductsByUserId(User.UserID);
How to make this?
BTW Is there any better way to make custom authentication/authorization than this from this tutorial?
Thanks
If you've actually implemented all the methods, and you're populating the built-in MembershipUser, then simply Membership.GetUser().ProviderUserKey will return ther UserId.
in my solution I use
Docent docent = DocentRepo.GetByID(User.Identity.Name);
maybe this can be of use to you
If you're using FormsAuthentification you can encode some custom user data in your cookie / ticket besides UserName. But you have to manually create a FormsAuthenticationTicket and set UserData property to the user's id during login. This way you can have both UserName & UserId.
// during login
var authCookie = FormsAuthentication.GetAuthCookie(userName, createPersistentCookie);
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
// preserve data in your configuration
var ticketWithId = new FormsAuthenticationTicket(
version: ticket.Version,
name: ticket.Name,
issueDate: ticket.IssueDate,
expiration: ticket.Expiration,
isPersistent: ticket.IsPersistent,
userData: userId);
authCookie.Value = FormsAuthentication.Encrypt(ticketWithId);
_context.Response.Cookies.Add(authCookie);
Then you can have an extension method for Controller or HttpContext classes:
public int? GetUserId(this Controller controller) {
var identity = (FormsIdentity)controller.User.Identity;
int id;
if (int.TryParse(identity.Ticket.UserData, out id))
return id;
return null;
}
But if you don't need both UserId & UserName data for your user, than HttpContext.User.Identity.Name or Controller.User.Identity.Name will have the username for your current user

Resources