'Xamarin login authentication using JWT
I'm developing my first Xamarin cross-platform application for Android and iOS (using Xamarin Forms). The application will require the user to login using a REST API and stay authenticated.
I want to use the token from my API, which is JWT, on my Xamarin application for the user to login
I don't know how to do this and all I have seen is with OAuth authentication.
Here is how I generate the token on my API project
private string GenerateToken(CrUserInfo user)
{
//Header
var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]));
var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
var header = new JwtHeader(signingCredentials);
//Claims
var claims = new[]
{
new Claim(ClaimTypes.Name, user.Username),
new Claim("User", user.Displayname),
new Claim(ClaimTypes.Role, user.Role.ToString()),
};
//Payload
var payload = new JwtPayload
(
_configuration["Authentication:Issuer"],
_configuration["Authentication:Audience"],
claims,
DateTime.Now,
DateTime.Now.AddMinutes(300)
);
var token = new JwtSecurityToken(header, payload);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Here is my post method which returns the Token
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public async Task<IActionResult> Authentication(UserLogin login)
{
//if it is a valid user
var validation = await IsValidUser(login);
if (validation.Item1)
{
if(validation.Item2 != null)
{
var token = GenerateToken(validation.Item2);
return Ok(new { token });
}
}
return NotFound("Unvalid User");
}
And I'm now trying to login a user on my Xamarin project but, as I said, all I see is OAuth authentication. The closest question I've seen was this one Xamarin.Forms how to access the current logged in user's Id and other information? - Stack Overflow but I don't know how to implement it.
Solution 1:[1]
First of all I used a different Library to Create the Jwt-Token. The implementation seems correct. In my Example e return a DTO from a Shared Project, because i also want to transmit the UserId and the exipredate But for example here is my code:
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new(ClaimTypes.NameIdentifier, user.Id),
};
var userRoles = await _userManager.GetRolesAsync(user);
claims.AddRange(userRoles.Select(x => new Claim(ClaimTypes.Role, x)));
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var jwtSecurityToken = new JwtSecurityToken(
_configuration["JWT:ValidIssuer"],
claims: claims,
expires: DateTime.Now.AddDays(1),
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
);
return new AuthDto
{
Id = user.Id,
Token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken),
ExpiryDate = jwtSecurityToken.ValidTo
};
In the shared App Project we used the ViewModel approach. There I store the token in the local app database. To check if the token is present I created a baseViewmodel which checks if the logintoken is active on each request.
To validate the token in the app I have implemented following class:
public class ValidatorImpl<T> : IValidator<T> where T : class
{
public bool IsValid(T validateObject) => !ValidateObject(validateObject).Any();
public IReadOnlyList<string> ValidateObject(T validateObject)
{
var context = new ValidationContext(validateObject);
var results = new List<ValidationResult>();
Validator.TryValidateObject(validateObject, context, results, true);
return results.Select(vr => vr.Errormessage).ToList();
}
}
before I save the token to the database i validate it like that:
if (!new ValidatorImpl<LoginToken>().IsValid(loginToken))
return false;
To deserialize the token do this:
private static JwtSecurityToken GetJwtSecurityToken(string token) => new JwtSecurityToken(token);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
