How to get Email address from the principal in ASP.net? - asp.net

I am trying to get the Email associated with the current user.
The following shows few lines that I add Claims in authentication.
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
try
{
CreateDataConnection();
R_AuthenticateUser oAuthUser = oDataConnection.Authenticate(context.UserName,context.Password);
string DB_User_roles = oAuthUser.UserLoginRoles;
if (oAuthUser.Authenticated)
{
string[] aray = DB_User_roles.Split(',');
identity.AddClaim(new Claim(ClaimTypes.Name, oAuthUser.UserID.ToString())); // keeps the login_ID
identity.AddClaim(new Claim(ClaimTypes.Email, context.UserName));
foreach (var item in aray)
{
// identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, item));
identity.AddClaim(new Claim(ClaimTypes.Role, item));
}
context.Validated(identity);
}
else //if (context.UserName == "user" && context.Password == "user")
{
context.SetError("Incorrect credntials", "Provided Username and Password is incorrect");
return;
}
}
catch (Exception ex)
{
int y = 0;
}
}
In my controllers currently, I read UserID associated with the user as follows?
[HttpGet]
[PGAuthorization(Roles = "USER")]
[Route("api/Address/GetAllAddresses")]
public string GetAllAddressesByUser()
{
CreateDataConnection();
Int64 UserID = Convert.ToInt64((User as ClaimsPrincipal).Identity.Name);
List<R_CustomerAddress> oUser = oDataConnection.GetAllAddressesByUser(UserID);
string output = JsonConvert.SerializeObject(oUser);
return output;
}
But now I need to get the UserID using Email which I have added in authentication. I tried using
Int64 UserID = Convert.ToInt64((User as ClaimsPrincipal).Identity.Email);
but it does not work. Could someone help me with that ?

If you add Email in the claims during authentication, you can get it with :
string email = System.Security.Claims.ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value

Shorter is better:
string email = this.user.FindFirstValue(ClaimTypes.Email);

Related

In Blazor client app after login top of home page says Hello + a very long hash code instead of user name

After every login in a Blazor client app I see below picture and I have to refresh the page so It replaces the hash code with user name or email
loginDisplay.razor is where it supposed to show the name/email of the user:
<AuthorizeView>
<Authorized>
Hello, #context.User.Identity.Name!
Log out
</Authorized>
<NotAuthorized>
Register
Log in
</NotAuthorized>
I used the custom state provider found from this article by Chris Sainty.
GetAuthentication searches in localStorage if there exists a saved token return a new state based on that otherwise creates a new.
MarkAsAuthenticated lets the state provider know that a user logged in with provided email
MarkAsLogedOut is the opposite of the above one.
ParseClaimsFromJwt is reading the claims from the token
:
public class ApiAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly HttpClient _httpClient;
private readonly ILocalStorageService _localStorage;
public ApiAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorage)
{
_httpClient = httpClient;
_localStorage = localStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var savedToken = await _localStorage.GetItemAsync<string>("authToken");
if (string.IsNullOrWhiteSpace(savedToken))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", savedToken);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt")));
}
public void MarkUserAsAuthenticated(string email)
{
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, email) }, "apiauth"));
var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
NotifyAuthenticationStateChanged(authState);
}
public void MarkUserAsLoggedOut()
{
var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
var authState = Task.FromResult(new AuthenticationState(anonymousUser));
NotifyAuthenticationStateChanged(authState);
}
private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
var claims = new List<Claim>();
var payload = jwt.Split('.')[1];
var jsonBytes = ParseBase64WithoutPadding(payload);
var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);
if (roles != null)
{
if (roles.ToString().Trim().StartsWith("["))
{
var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());
foreach (var parsedRole in parsedRoles)
{
claims.Add(new Claim(ClaimTypes.Role, parsedRole));
}
}
else
{
claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
}
keyValuePairs.Remove(ClaimTypes.Role);
}
claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
return claims;
}
private byte[] ParseBase64WithoutPadding(string base64)
{
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
return Convert.FromBase64String(base64);
}
}
There is a small problem in the code of that article, just pass Email instead of token. Note the name of the parameter in void MarkUserAsAuthenticated(string email).
In AuthService.cs
((ApiA uthenticationStateProvider)_authenticationStateProvider)
//.MarkUserAsAuthenticated(loginResult.Token);
.MarkUserAsAuthenticated(loginModel.Email);

How can I get the claimsidentity of a token or from an token oauth2

I need one of my drivers to access certain information stored in the ClaimsIdentity.
Below my method GrantResourceOwnerCredentials().
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
string rol = null;
if (context.Request.Headers.ContainsKey("X-Role"))
{
rol = context.Request.Headers.Get("X-Role");
switch (rol)
{
case "user":
bool isValidCredentials = await //Logica que verifica credenciales.
if (isValidCredentials)
{
//Crea y prepara el objeto ClaimsIdentity
var identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
var data = new Dictionary<string, string>
{
{"email", context.UserName}
};
var properties = new AuthenticationProperties(data);
var ticket = new AuthenticationTicket(identity, properties);
context.Validated(ticket);
return;
}
else
{
context.SetError("Invalid user or password.");
return;
}
case "things":
//Logica para autenticar things.
return;
default:
context.SetError("The role is not valid.");
return;
}
}
else
{
context.SetError("The role header is required.");
return;
}
}
Part of the code of the controller dodne I need to have access to the claims is below
[Route("{email}")]
[Authorize(Roles="user")]
public async Task<Customer> Get([FromUri] string email)
{
//here I need to obtain the value of the claim that refers to userName associated with this identity.
}
How could this behavior be achieved? I know that at least the value of Role is being obtained since this makes [Authorize (Roles = "user")] work.
I expect that your controller class inherits from System.Web.Http.ApiController.
In this case you can access user claims in the following way.
At first get a ClaimsIdentity:
ClaimsIdentity claimsIdentity = (this.User as ClaimsPrincipal)?.Identities.FirstOrDefault();
or
var claimsIdentity = this.User?.Identity as ClaimsIdentity;
Then access claims:
if (claimsIdentity != null)
{
string userName = claimsIdentity.Name;
//or
userName = claimsIdentity.FindFirst(ClaimTypes.Name).Value;
}

The procedure does not work properly Entity Framework ASP.NET MVC 5 C#5

I have been facing this problem with assigning users to a proper role. The code looks just fine, but in reality half of the users gets a proper role, the other half stays without a role at all. Here is the method which does it:
public IdentityResult RefreshUserGroupRoles(long? userId)
{
if (userId == null) throw new ArgumentNullException(nameof(userId));
var user = _userManager.FindById(userId.Value);
if(user == null)
{
throw new ArgumentNullException(nameof(userId));
}
// Remove user from previous roles:
var oldUserRoles = _userManager.GetRoles(userId.Value);
if (oldUserRoles.Count > 0)
{
_userManager.RemoveFromRoles(userId.Value, oldUserRoles.ToArray());
}
// Find the roles this user is entitled to from group membership:
var newGroupRoles = this.GetUserGroupRoles(userId.Value);
// Get the damn role names:
var allRoles = _roleManager.Roles.ToList();
var addTheseRoles = allRoles.Where(r => newGroupRoles.Any(gr => gr.AppRoleId == r.Id));
var roleNames = addTheseRoles.Select(n => n.Name).ToArray();
//_db.Database.CurrentTransaction.Commit();
// Add the user to the proper roles
var transaction = _db.Database.BeginTransaction();
IdentityResult result;
try
{
result = _userManager.AddToRoles(userId.Value, roleNames);
transaction.Commit();
_db.DbContextTransactionAu.Commit(); //This is for Audit
}
catch (Exception)
{
transaction.Rollback();
throw;
}
_db.DbContextTransactionAuDispose?.Dispose();
return result;
}
public IEnumerable<AppGroupRole> GetUserGroupRoles(long userId)
{
var userGroups = this.GetUserGroups(userId).ToList();
if (userGroups.Count == 0) return new Collection<AppGroupRole>().AsEnumerable();
var userGroupRoles = new List<AppGroupRole>();
foreach(var group in userGroups)
{
userGroupRoles.AddRange(group.AppRoles.ToArray());
}
return userGroupRoles;
}
Any idea what could be wrong?

Pass a variable from a Custom Filter to controller action method

I have a Web Api project.
I have implemented a custom Authentication Attribute like so:
public class TokenAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
// In auth web method you should implement functionality of authentication
// so that client app could be able to get token
if (actionContext.Request.RequestUri.AbsolutePath.Contains("api/auth/login"))
{
return;
}
// Receive token from the client. Here is the example when token is in header:
var token = HttpContext.Current.Request.Headers["Token"];
// Put your secret key into the configuration
var secretKey = ConfigurationManager.AppSettings["JWTSecurityKey"];
try
{
string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey);
int separatorIndex = jsonPayload.IndexOf(';');
string userId = "";
DateTime timeIssued = DateTime.MinValue;
if (separatorIndex >= 0)
{
//userId = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(jsonPayload.Substring(0, separatorIndex)));
userId = jsonPayload.Substring(0, separatorIndex);
timeIssued = DateTime.Parse(jsonPayload.Substring(separatorIndex + 1));
}
short TokenTTL = 10;
//try{
//Int16.TryParse(ConfigurationManager.AppSettings["TokenTTL"],TokenTTL);
//}catch(Exception e){ //}
if ((DateTime.Now.Subtract(timeIssued).TotalMinutes >= TokenTTL))
{
throw new HttpResponseException(HttpStatusCode.Forbidden);
}
//Save user in context
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, userId)
};
var id = new ClaimsIdentity(claims, "Basic");
var principal = new ClaimsPrincipal(new[] { id });
actionContext.Request.GetRequestContext().Principal = principal;
}
catch (JWT.SignatureVerificationException)
{
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}
}
}
Now how do I get hold of that user in my actionmethod?
[BasicHttpAuthorizeAttribute]
[httpGet]
public void Login()
{
// how do i get user here
}
/////// Save the string username to the context so that I can acess
it in the controler.
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, "john")
};
var id = new ClaimsIdentity(claims, "Basic");
var principal = new ClaimsPrincipal(new[] { id });
actionContext.Request.GetRequestContext().Principal = principal;
// how do i get user here
var name = User.Identity.Name;
BTW, use an authentication filter instead of an authorization filter to perform authentication. See my blog post - http://lbadri.wordpress.com/2014/02/13/basic-authentication-with-asp-net-web-api-using-authentication-filter/.

Enforcing a ClaimType on ClaimsIdentity

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");
}
}
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:
an exception is throw if the claim isn't found since .Single is used
Claim's value can never be null since it's constructor prevents it
It 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/

Resources