Reputation: 374
I am working on a new app and am using ASP.NET Identity and was wondering if there was a way to enforce a specific claim type be present on the ClaimsIdentity. Here is what I have so far.. It works but it seems there this is something that would / should be built in and maybe I am just not finding it.
public void SignIn(IUserIdentity user, string authenticationType, bool isPersistent)
{
if (user == null)
{
string msg = "UserIdentity or UserIdentity is null";
_logger.Error(msg);
throw new NullReferenceException(msg);
}
List<Claim> claims = _claimService.GetClaims(user.UserId);
var identity = new ClaimsIdentity(claims, authenticationType, ClaimTypes.Name, ClaimTypes.Role);
if (claims.Any() && claims.Single(c => c.Type == ClaimTypes.Name).Value != null)
{
_owinContext.Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = isPersistent
}, identity);
}
else
{
throw new SecurityException("Invalid or null Name Claim");
}
}
Upvotes: 3
Views: 1373
Reputation: 15420
I am not aware of any built-in way to assert that a claim exist.
Edit:
You are right. My original solution is over-engineered. I think your solution is the only way to go.
The validation is incorrect though for two reasons:
.Single
is usedClaim
's value can never be null since it's constructor prevents itIt should be:
List<Claim> claims = _claimService.GetClaims(user.UserId);
if (claims.Any(i => i.Type == ClaimTypes.Name)
{
var identity = new ClaimsIdentity(claims, authenticationType, ClaimTypes.Name, ClaimTypes.Role);
Or
var claims = _claimService.GetClaims(user.UserId);
var identity = new ClaimsIdentity(claims, authenticationType, ClaimTypes.Name, ClaimTypes.Role);
if (identity.Name != null)
{
Original:
How I would do it is to separate authentication and authorization.
Authentication - verifies the user
Authorization - verifies what the user is authorized to do.
public class ClaimsAuthorizeAttribute : AuthorizeAttribute
{
public string[] ClaimTypes { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) { throw new ArgumentNullException("httpContext"); }
var principal = httpContext.User as ClaimsPrincipal;
return principal != null && HasAllClaimTypes(principal) && base.AuthorizeCore(httpContext);
}
private bool HasAllClaimTypes(ClaimsPrincipal principal)
{
return ClaimTypes == null || ClaimTypes.All(claimType => principal.HasClaim(claim => claim.Type == claimType));
}
}
Enforce claim types that all controllers require in global filters like so:
filters.Add(new ClaimsAuthorizeAttribute { ClaimTypes = new[]{ ClaimTypes.Name } });
When a claim type is not present, the user is redirected to the log in page. (you may want to change this behavior though)
See this article too http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/
Upvotes: 3