OWIN/Identity Framework - c#

I have a class library with a SignIn method with a lot of logic in order for a member to sign in. The problem that I am facing is that I add a claim of "Fullname" to the identity and it works fine, but as soon as the user log's off and logs in again the claim is gone.
If I inspect the users identity the claim is available on the second log in until the RedirectToAction method is hit, then all the custom claims are no longer in the users identity. This includes the Fullname and Role claims.
var roles = _dbsme.sp_GetAllRoles(user.Id);
ClaimsIdentity identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationProperties authenticationProperties1 = new AuthenticationProperties();
authenticationProperties1.IsPersistent = false;
AuthenticationProperties authenticationProperties2 = authenticationProperties1;
identity.AddClaim(new Claim("FullName", user.Firstname + " " + user.Surname));
foreach (string role in roles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role));
}
AuthenticationManager.SignIn(authenticationProperties2, identity);
signInStatus = SignInStatus.Success;

You should be adding claims via the UserManager in order to have them persisted (if you use ASP.NET Identity 2 with EF).
userManager.AddClaim(userId, new Claim(claimType,claimValue));
Please note that if you add the claims on a user that is currently logged-in you need to sign that user in again (to put the new information in the cookie).

Related

Asp.Net Core role system without Identity

How can i add role system without identity? I need to member and admin roles.
Login code:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, loginDTO.StrUserID)
};
var userIdentity = new ClaimsIdentity(claims, "login");
ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
await HttpContext.SignInAsync(principal);
Startup.cs
services.AddAuthorization(opt =>
{
opt.AddPolicy("Admin", policy => policy.RequireClaim(ClaimTypes.Name));
});
How can i add role system without identity? I need to member and admin roles.
As far as I know, if you used asp.net core cookie authentication , there is no need to build a role system.
We could write the codes in your login logic to check the user role from database.
Then we could add role by adding the ClaimTypes.Role Claim. Then we could use [Authorize(Roles ="Admin")] attribute to let only admin role user access.
More details, you could refer to below codes:
//Here build the logic to get the user role from database, then create a new role claim to add the user role.
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "TestA"),
new Claim(ClaimTypes.Role, "Admin"),
};
var userIdentity = new ClaimsIdentity(claims, "login");
ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
HttpContext.SignInAsync(principal);
On the controller:
[Authorize(Roles ="Admin")]
public class AdminController : Controller

Updated value of Claim is not reflecting in the subsequent requests

In my project, I am using token-based authentication and after a successful login, I store some user-specific values in user's token and to do this I have used Claims.
Below is the code I am using to store claims after login:
User user = new UserManager().GetUser(UserName, Password);
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, user.FullName),
new Claim(ClaimTypes.Email, user.Email),
new Claim("IsLocked", Convert.ToString(user.IsLocked))
};
AuthenticationProperties properties = CreateProperties(context.UserName);
ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims, Startup.OAuthOptions.AuthenticationType);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
As you can see in the above code that I have a claim to store IsLocked value of the user. As per the requirement, I need to prevent access of each API action from users whose account is locked. To do so, I have created a custom action filter and inside that, I use the value of IsLocked claim and thus prevent actions from being executed if user's claim value says that the user account is locked.
Below is the code of my custom action filter:
public class AllowActiveUsersAttribute : ActionFilterAttribute
{
public AllowActiveUsersAttribute()
{
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
if (Convert.ToBoolean(identity.Claims.Where(c => c.Type == "IsLocked").Select(c => c.Value).SingleOrDefault()))
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
}
}
}
And then I use this custom Attribute on all Web API actions, like:
[AllowActiveUsers]
public async Task<IHttpActionResult> GetAccountDetails()
This code works perfectly and I get Unauthorized error when I log in with a locked account and then try to use any API endpoint.
In our system, we have some rules and breaking those rules can lock the users' account. When the account gets locked then the user shouldn't be able to access any API endpoint. So after the successful login (with an account that is not locked), if a user breaks any rule then his/her account should get locked immediately and after that he/she must not be able to use any API endpoints.
To do this, I added code to update the value of IsLocked claim and it successfully updates the claim value. But when I try to get the value of IsLocked claim in the custom action then I get the same old value instead of the new return value. Below is the code that I am using to update the claim value.
// check for the existing claim and remove it
var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
var claim = (from c in user.Claims where c.Type == "IsLocked" select c).FirstOrDefault();
if (claim != null)
identity.RemoveClaim(claim);
// add new claim
identity.AddClaim(new Claim("IsLocked", Convert.ToString(true)));
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
Can you please suggest how I can get the new value in the custom attribute so that if a user's account gets locked then from next requests, none of the API requests should be entertained?
That's cause you are still using the old/existing token which still don't have the updated value of IsLocked and thus the scenario. To resolve this, either the user has to start afresh by means of generating a new token which would have the updated value. Essentially a new access token has to be generated.
See this issue link for more understanding https://github.com/IdentityServer/IdentityServer3/issues/2783

manually check if claims token is ok

I have a custom attribute where I manually wanna check if a claims token is valid. How do I do that?
public class AuthorizeClaimsAttribute : AuthorizeAttribute {
protected override bool UserAuthorized(IPrincipal user) {
var cookie = HttpContext.Current.Request.Cookies.Get("bearerToken");
if (cookie != null) {
//Check if token is valid, how?
}
return false;
}
}
The token is created as follow:
var identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim("Username", model.Username));
identity.AddClaim(new Claim("IsAdmin", isAdmin.ToString()));
var properties = new AuthenticationProperties() {
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.Add(Startup.OAuthOptions.AccessTokenExpireTimeSpan)
};
var ticket = new AuthenticationTicket(identity, properties);
var accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
Note: I cannot use the existing Authorize attribute. That´s why I need to check it manually.
One method is to store the token alongside its username somewhere in a persistant data structure
For example, when you create the Identity store the model.UserName & the accessToken in a a database of your choice.
Then, when you want to check your cookie you can re-open your database and query for it and take the appropriate action.
Also, adding that date in the database will also help you keep the size of it down resulting in faster searches, i.e. if your token only lasts for 3 months, delete the old ones as part of maintenance

Custom RoleProvider in ASP.NET Core with Identity?

In past MVC versions I was able to do
<roleManager enabled="true" defaultProvider="...." ...
in to the web.config to get a custom role provider, but that doesn't seem to be the case anymore.
Essentially what I want to do is:
The user logs in.
On success, get roles for user from external source.
Apply roles to user to be used in code.
Match user roles to roles in custom RoleProvider
How do I do this in ASP.NET Core?
If you're using simple cookie-based authentication instead of the Identity framework, you can add your roles as claims and they will be picked up by User.IsInRole(...), [Authorize(Roles = "...")], etc.
private async Task SignIn(string username)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, username)
};
// TODO: get roles from external source
claims.Add(new Claim(ClaimTypes.Role, "Admin"));
claims.Add(new Claim(ClaimTypes.Role, "Moderator"));
var identity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme,
ClaimTypes.Name,
ClaimTypes.Role
);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(identity),
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMonths(1)
}
);
}

How to add claims during user registration

I'm using ASP.NET MVC 5 project with identity 2.1.0 and VS2013 U4. I want to add claims to user during registration in order to be stored in db. These claims represent user custom properties.
As I created a web page for administrator to create/edit/delete users, I'm still using create method from AccountController to create a user, but I don't want to login that user. How can I add those claims to the user ?
You probably already have a UserManager class. You can use that one to create users and to add claims.
As an example in a controller:
// gather some context stuff
var context = this.Request.GetContext();
// gather the user manager
var usermanager = context.Get<ApplicationUserManager>();
// add a country claim (given you have the userId)
usermanager.AddClaim("userid", new Claim(ClaimTypes.Country, "Germany"));
In order for this to work you need to implement your own UserManager and link it with the OWIN context (in the example it's ApplicationUserManager which basically is class ApplicationUserManager : UserManager<ApplicationUser> { } with only a small amount of configuration added). A bit of reading is available here: https://msdn.microsoft.com/en-us/library/dn613290%28v=vs.108%29.aspx
you can use Like
private void SignInAsync(User User)
{
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, User.Employee.Name));
claims.Add(new Claim(ClaimTypes.Email, User.Employee.EmailId));
claims.Add(new Claim(ClaimTypes.Role, User.RoleId.ToString()));
var id = new ClaimsIdentity(claims,
DefaultAuthenticationTypes.ApplicationCookie);
var claimsPrincipal = new ClaimsPrincipal(id);
// Set current principal
Thread.CurrentPrincipal = claimsPrincipal;
var ctx = Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(id);
}
after login pass the User table value in this function
SignInAsync(result);
you can get clam value like
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
// Get the claims values
string UserRoleValue = identity.Claims.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value).SingleOrDefault();
You can, in fact, create claims at the same time you create the user account.
Just add the claims to the user object before you call CreateAsync on the user manager.
var identityUser = new IdentityUser
{
UserName = username,
Email = email,
// etc...
Claims = { new IdentityUserClaim { ClaimType = "SomeClaimType", ClaimValue = "SomeClaimValue"} }
};
var identityResult = await _userManager.CreateAsync(identityUser, password);
This will create the user and associate the claims with the user as one logical operation with persistence.

Categories