Bu yazımızda asp.net core uygulamalarında token based authentication nedir, nasıl sağlanır bir örnek üzerinden inceleyeceğiz.
ProductApi adında bir service projenizin olduğunu düşünün ve bu service üzerinde product tablonuz için CRUD işlemlerini yapan belli endpoint'ler sağladığınızı varsayalım. Herhangi bir güvenlik kontrolü bulunmayan ProductApi'nize call yapmak isteyen bir kişi geliştirme yaparken doğrudan erişebiliyor. Peki ama çok basit bir şekilde düşünecek olursak service url'lerini bulan herhangi bir kişi servisinizi manipüle etmek adına CRUD metotlarınıza doğrudan call yapabilir yada bazı metotları call edebilir bazılarını edemez vs. gibi riskler barındırmaktadır.
Bu gibi durumlara çözüm olarak token-based authentication yöntemleri geliştirilmiştir.
Token based authentication'ın genel konsepti oldukça basit; kullanıcıdan bir username ve password vs. gibi bir bilgi alıp bu bilgiyi server'a göndermek ve eğer valid bir username ve password ise karşılığında bir token dönüp o kullanıcının artık token expire oluncaya dek bütün api işlemlerini o token üzerinden yapması beklenir.
JSON Web Token Nedir Nasıl Kullanılır;
Base64 olarak oluşturulmuş 3 ayrı bölümden oluşur;
HEADER.PAYLOAD.SIGNATURE
Header bölümünde; hangi token türünün ve şifreleme algoritmasının kullanıldığı bilgisi yer alır.
Payload; uygulama bazlı bilgilerin yer aldığı(claim,userId vs.) yani uygulamaya özel bölümdür.
Signature ise adından da anlaşıldığı gibi server tarafından üretilen signature'ın bulunduğu bölümdür.
Şimdi ise bir asp.net core projesinde JWT nasıl entegre edilir ve kullanılır bunu inceleyelim.
İlk olarak aşağıdaki gibi Startup.cs bulunan ConfigureServices metodu içerisinde uygulama boyunca geçerli olan JWT Authentication middleware konfigurasyonlarını yapalım.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
{
ValidateActor = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Issuer"],
ValidAudience = Configuration["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SigningKey"]))
};
});
services.AddMvc();
}
Middleware tanımlamasını yukarıdaki gibi yaptıktan sonra bunu builder'a eklememiz gerekmekte. Bunun içinde yine Startup.cs de Configure metodu içerisinde aşağıdaki tanımlamayı yapalım.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
Sırada JWT generate edecek olan endpoint'i oluşturma var. Bunun için TokenController adında bir controller oluşturalım ve içerisine kullanıcıyı validate ederken kullanılacak olan bilgilerin bulunduğu request modeli alıp geriye tokenResponse dönen bir endpoint oluşturalım.
[AllowAnonymous]
[HttpPost]
[Route("token")]
public IActionResult Post([FromBody]LoginRequest request)
{
if (ModelState.IsValid)
{
var user = _userService.Get(request.UserName, request.Password);
if (user == null)
{
return Unauthorized();
}
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, request.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken
(
issuer: _configuration["Issuer"], //appsettings.json içerisinde bulunan issuer değeri
audience: _configuration["Audience"],//appsettings.json içerisinde bulunan audince değeri
claims: claims,
expires: DateTime.UtcNow.AddDays(30), // 30 gün geçerli olacak
notBefore: DateTime.UtcNow,
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SigningKey"])),//appsettings.json içerisinde bulunan signingkey değeri
SecurityAlgorithms.HmacSha256)
);
return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
return BadRequest();
}
public class LoginRequest
{
public string UserName {get;set;}
public string Password {get;set;}
}
JWT based authentication yapısı projemiz için hazır. Sırada bunu test etmek var. Bunun için asp.net core projesi oluşturulurken default gelen ValuesController.cs içerisindeki Get metodunu kullanarak testimizi yapalım. Controller seviyesinde [Authorize] atrtribute'ü kullanarak authentication zorunlu olduğunu belirtebiliriz.
[Authorize]
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Postman kullanarak projemizi test edelim.
İlk olarak token almadan ValuesController'a HttpGet request'inde bulunalım ancak token bilgisi set etmediğimizden bize geriye successful bir response (http200) dönmemesi gerekir. Aşağıda görüldüğü üzre response olarak 401 yani Unauthorized cevabı aldık.
Şimdi ise TokenController da bulunan metoda request atarak token response'unu aşağıdaki gibi alalım.
Almış olduğumuz tokenResponse'u göndereceğimiz request'in Authorization header'ına set ederek tekrardan ValuesController'a istekte bulunduğumuzda bu sefer http200 ile geriye value array'ini dönen cevabı almış olacağız.
JWT'nin kullanımı özetle bu şekilde. Sizlerde geliştirdiğiniz bir api projenizi dış dünyaya açarken token-based authentication yapmak istediğinizde implementasyonu oldukça basit olan basit jwt den faydalanabilirsiniz.