Jwt Bearer

1. ASP.Net API C#

1.1. Install package

Cài đặt thư viện JwtBearer

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

1.2. Configuration

Khai báo thông tin Jwt trong appsettings.json

"Jwt": {
    "Issuer": "ceb.net.vn",
    "Audience": "ceb.net.vn",
    "SecretKey": "23748ijwefkassncmnzcmnjLAKDSJLkuqiowasfdweioruzcasfd01284zxasdfwer",
    "Expires": 30
}

Khai báo trong Program.cs

builder.Services.AddAuthentication(p => {
    p.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    p.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(p => {
    p.TokenValidationParameters = new TokenValidationParameters{
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        ValidAudience = builder.Configuration["Jwt:Audience"],
        ValidateLifetime = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"] ?? throw new KeyNotFoundException("Jwt:SecretKey")))
    };
});

1.3. Login

Tạo class LoginResult trả về kết quả đăng nhập

public class LoginResult{
    public bool Success { get; set; }
    public string? Token { get; set; }
    public string Message { get; set; } = null!;
}

Tạo hàm GenerateToken trong class Helper trong Services

public static class Helper{
    public static string? GenerateToken(Member obj, IConfiguration configuration){
        List<Claim> claims = new List<Claim>{
          new Claim(ClaimTypes.NameIdentifier, obj.MemberId!),  
          new Claim(ClaimTypes.Name, string.IsNullOrEmpty(obj.Surname) ? obj.GivenName : obj.Surname + " " + obj.GivenName),  
          new Claim(ClaimTypes.Email, obj.Email),  
          new Claim(ClaimTypes.GivenName, obj.GivenName),  
          new Claim(ClaimTypes.Role, obj.Role.ToString())
        };
        if(!string.IsNullOrEmpty(obj.Surname)) claims.Add(new Claim(ClaimTypes.Surname, obj.Surname));
        JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
        SymmetricSecurityKey key = new SymmetricSecurityKey(
            Encoding.ASCII.GetBytes(configuration["Jwt:SecretKey"]?? throw new KeyNotFoundException("Jwt:SecretKey"))
        );
        SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
        JwtSecurityToken token = new JwtSecurityToken(
            issuer: configuration["Jwt:Issuer"],
            audience: configuration["Jwt:Audience"],
            claims: claims,
            expires: DateTime.Now.AddDays(Convert.ToInt32(configuration["Jwt:Expires"])),
            signingCredentials: credentials            
        );
        return handler.WriteToken(token);
    }
}

Tạo class LoginModel lưu trữ thông tin người dùng nhập vào

public class LoginModel{
    public string Email { get; set; } = null!;
    public string Password { get; set; } = null!;
}

Kiểm tra đăng nhập

public Member? GetMemberById(string id){
    string sql = "SELECT MemberId, GivenName, Surname, Email, Role FROM Member WHERE MemberId = @Id";
    return connection.QuerySingleOrDefault<Member>(sql, new {id});
}
public LoginResult Login(LoginModel obj, IConfiguration configuration){
    Member? member = GetMemberByEmail(obj.Email);
    if(member != null){
        if(BCrypt.Net.BCrypt.Verify(obj.Password, member.Password)){
            return new LoginResult{
                Success = true,
                Message = "Login Success",
                Token = Helper.GenerateToken(member,  configuration)
            };
        }
        return new LoginResult{
            Success = false,
                Message = "Password invalid",
        };
    }
    return new LoginResult{
        Success = false,
            Message = "Email invalid"
    };
}

Xử lý đăng nhập trả về Jwt Bearer Token

[HttpPost("login")]
public LoginResult Login(LoginModel obj){
    return Provider.Member.Login(obj, HttpContext.RequestServices.GetRequiredService<IConfiguration>());
}

2. Flutter

2.1 Install package

Mở file pubspec.yaml khai báo thêm package flutter_secure_storage để lưu trữ thông tin Jwt Token

dependencies:
  flutter:
    sdk: flutter
  http: ^1.6.0
  flutter_dotenv: ^6.0.1
  flutter_secure_storage: ^11.2.0

2.2 Save Token


class SessionHelper {
  static final FlutterSecureStorage storage = FlutterSecureStorage();
  static Future<void> save(String token, String email) async {
    await storage.write(key: 'token', value: token);
    await storage.write(key: 'email', value: email);
  }
  static Future<String?> get token async {
    return await storage.read(key: 'token');
  }
  static Future<String?> get email async {
    return await storage.read(key: 'email');
  }
  static Future<void> logout() async {
    await storage.delete(key: 'token');
    await storage.delete(key: 'email');
  }
}

Get information with token


static Future<Member?> getProfile(String token) async {
    Uri uri = Uri.parse('${dotenv.env['API_URL']}/api/auth');
    var response = await http.get(
      uri,
      headers: {
        'content-type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );
    if (response.statusCode == 200) {
      return Member.fromMap(jsonDecode(response.body));
    }
    return null;
}