İlginizi Çekebilir
  1. Ana Sayfa
  2. C#
  3. ASP.NET Core 3.0 ile JWT Uygulaması
kz_g_n

ASP.NET Core 3.0 ile JWT Uygulaması

Bu makalede basit bir ASP.NET Core 3.0 API  uygulamasına JWT (Json Web Token) ile authentication yapısını nasıl kuracağımızı anlatacağım.


Bu makalede basit bir ASP.NET Core 3.0 API  uygulamasına JWT (Json Web Token) ile authentication yapısını nasıl kuracağımızı anlatacağım.

İlk olarak JWT nedir?

Bir JWT, teknik olarak bazı JSON verilerinin sahibini doğrulayan bir mekanizmadır. Çerezlerin aksine çok miktarda veri içerebilmektedir. Buna rağmen boyutu çok büyük değildir ve URL üzerinden de gönderilebilme özelliği olan kompakt yapıya sahiptir.

dot net core 3 jwt s
ASP.NET Core 3.0 API  uygulaması JWT(Json Web Token) ile authentication

Bir sunucu bir JWT aldığında, kaynak tarafından imzalandığından içerdiği verilere güvenilebileceğini garanti edebilir. Hiçbir aracı, bir JWT’yi gönderildikten sonra değiştiremez. Bir JWT’nin veri sahipliğini garanti ettiğini, ancak şifrelemeyi garanti etmediğini bilmek önemlidir; Bir JWT’ye kaydettiğiniz JSON verileri, yalnızca seri hale getirildiğinden ve şifrelenmemiş olduğundan tokene müdahale eden herkes tarafından görülebilir. Bu nedenle HTTPS’i JWT’lerle (ve genel olarak HTTPS’i) kullanmanızı tavsiye ederim. Json Web Tokenile ilgili dökümanlara resmi sitesi https://jwt.io/ üzerinden ulaşabilirsiniz.

Şimdi gelelim JWT’nin ASP.NET Core 3.0 Api uygulamasındaki kullanımına;

 

ASP.NET Core JWT UsersController

Basit bir read işlemi için GeltAll() methodunu, sisteme giriş yetkisi alabilmek için gerekli olan Json Web Token ve kullanıcı bilgilerini dönen “authenticate” methodunu oluşturuyoruz. UsersController’a eklenen [Authorize] attribute’ı token gönderilmeden istek yapılmasını engeller. Token alabilmek için ulaşmaya çalışacağımız Authenticate methodu ise [AllowAnonymous] attribute’ına sahip olmalıdır.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using WebApi.Services;
using WebApi.Models;

namespace WebApi.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class UsersController : ControllerBase
    {
        private IUserService _userService;

        public UsersController(IUserService userService)
        {
            _userService = userService;
        }

        [AllowAnonymous]
        [HttpPost("authenticate")]
        public IActionResult Authenticate([FromBody]AuthenticateModel model)
        {
            var user = _userService.Authenticate(model.Username, model.Password);

            if (user == null)
                return BadRequest(new { message = "You shall not pass! -Gandalf the Grey"
                });

            return Ok(user);
        }

        [HttpGet]
        public IActionResult GetAll()
        {
            var users = _userService.GetAll();
            return Ok(users);
        }
    }
}

 

ASP.NET Core User Entity

User entity sınıfı, uygulamadaki bir kullanıcının verilerini gösterir. Uygulamanın farklı bölümleri arasında veri taşıma ve controller action methodlarından http response döndürmek için kullanılabilir.

namespace WebApi.Entities
{
    public class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string Token { get; set; }
    }
}

 

ASP.NET Core JWT AppSettings.json

JWT token konfigurasyonu yaparken şifreleme işleminde kullanacağımız anahtar kelimeyi -tahmin edilmesi zor bir string ifade,  AppSettings.json dosyasından okuyoruz.

  "AppSettings": {
    "Secret": "ASIRI GIZLI JSON WEB TOKEN ANAHTARIM, BURAYA HERHANGI BIR STRING IFADE GELEBILIR"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

 

ASP.NET Core JWT AppSettings.cs

AppSettings class’ı appsettings.json dosyasında tanımlanan property’leri içerir. Dependency Injection (DI) sisteminde yerleşik olan ASP.NET Core yapısındaki sınıflara inject edilen nesneler üzerinden, uygulama ayarlarına erişmek için kullanacağız.

namespace WebApi.Helpers
{
    public class AppSettings
    {
        public string Secret { get; set; }
    }
}

 

ASP.NET Core JWT Helpers

Extension methodlar, C # ‘daki mevcut tiplere kolaylık yöntemleri ve ekstra işlevler eklemek için kullanılır. Extension methodlar hakkında detaylı bilgiye ve uygulama detaylarına buradan ulaşabilirsiniz.

using System.Collections.Generic;
using System.Linq;
using WebApi.Entities;

namespace WebApi.Helpers
{
    public static class ExtensionMethods
    {
        public static IEnumerable<User> WithoutPasswords(this IEnumerable<User> users) {
            return users.Select(x => x.WithoutPassword());
        }

        public static User WithoutPassword(this User user) {
            user.Password = null;
            return user;
        }
    }
}

 

ASP.NET Core JWT Authenticate Model

Authenticate model, “/users/authenticate” adresindeki method request’i için gerekli parametreleri içerir. Bu URL’e bir HTTP POST requesti geldiğinde, request body’sindeki veriler AuthenticateModel’in bir instance’ına bağlanır, doğrulanır ve methoda iletilir.

Otomatize edilmiş bir validasyon kuralı oluşturmak için ASP.NET Core Data Annotations kütüphanesinin [Required] attribute’ı, bağlı olduğu model property’si methoda gönderilmediğinde ap cevabı olarak “validation error message” cevabı döner.

using System.ComponentModel.DataAnnotations;

namespace WebApi.Models
{
    public class AuthenticateModel
    {
        [Required]
        public string Username { get; set; }

        [Required]
        public string Password { get; set; }
    }
}

 

ASP.NET Core JWT User Service

User servisi, kullanıcı kimlik bilgilerinin doğrulanması ve bir json web token dondüren bir methodla, uygulamadaki kullanıcıları listeleyen bir method içermektedir.

Ayrıca veritabanı bağlantısı ile ve orm aracı implementasyonu ile zaman kaybetmemek ve JWT authentication işlemine odaklanmak amacıyla kullanıcılar için mock data tanımlandı. Kullanıcı bilgilerini veritabanında ve şifreleri hash’lenmiş şekilde saklamanız önerilir.

Başarılı kimlik doğrulamasında Authenticate methodu, appsettings.json içinde tanımlanmış secret key yardımıyla dijitl olarak imzalanmış bir token üretmek için JwtSecurityTokenHandler sınıfını kullanır.

WebApi.Service namespace’inde üst bölümde bulunan interface nesnesi, UserService’in içerdiği merhodları tanımlar,  altındaki user sevice ise bu methodları miras alır.

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using WebApi.Entities;
using WebApi.Helpers;

namespace WebApi.Services
{
    public interface IUserService
    {
        User Authenticate(string username, string password);
        IEnumerable<User> GetAll();
    }

    public class UserService : IUserService
    {
        // users mock data
        private List<User> _users = new List<User>
        { 
            new User { Id = 1, FirstName = "john", LastName = "doe", Username = "jdoe", Password = "123" } 
        };

        private readonly AppSettings _appSettings;

        public UserService(IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }

        public User Authenticate(string username, string password)
        {
            var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);

            // user bulunamazsa null dönüyoruz
            if (user == null)
                return null;

            // authentication başarılı, jwt token oluşturuyoruz
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] 
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString())
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            user.Token = tokenHandler.WriteToken(token);

            return user.WithoutPassword();
        }

        public IEnumerable<User> GetAll()
        {
            return _users.WithoutPasswords();
        }
    }
}

 

ASP.NET Core JWT Program

Program class’ı, uygulamayı başlatmak için ana giriş noktası olan bir konsol uygulamasıdır, IHostBuilder instance’ı kullanarak web api host’unu ve web sunucusunu yapılandırır ve başlatır. ASP.NET Core uygulamaları yürütmek için bir host gerektirir.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>()
                        .UseUrls("http://localhost:4000");
                });
    }
}

 

ASP.NET Core JWT Startup

ASP.NET Core mimarisinde, Dependency Injection için kullanabileceğimiz hazır bir yapı bulunuyor. Inject etmek isteyeceğiniz nesne bir servis nesnesi veya log nesnesi olabilir. Ihtiyacınız olan şey, inject işlemini yaptıktan sonra Startup.cs sınıfındaki servis konfigurasyonlarını yaptığımız methodda, IServiceCollection interface ile servisimizi tanıtmak.

Authentication yöntemini ve temel konfigurasyonlarını uygulamaya tanıtmak için Microsoft.AspNetCore.Authentication.JwtBearer kütüphanesini kullanıyoruz.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebApi.Helpers;
using WebApi.Services;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;

namespace WebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddControllers();

            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });

            // configure DI for application services
            services.AddScoped<IUserService, UserService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();

            // global cors policy
            app.UseCors(x => x
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());

            app.UseAuthentication();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });
        }
    }
}

 

ASP.NET Core JWT Web Api csproj

Csproj (C# project) dosyası bir MSBuild tabanlı bir dosyadır ve target framework ve Nuget paketlerinin versiyonları ve bağımlılık bilgilerini içerir.

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" />
  </ItemGroup>
</Project>

 

ASP.NET Core JWT Authentication API’nin Postman ile Test Edilmesi

  • http://localhost:40000/users/authenticate adresinini POST yöntemiyle test etmeliyiz. User Controller’da tanımlı authenticate methodumuzu hatırlayalım. HttpPost attribute’a sahip, valid bir AuthenticateModel nesnesi istemektedir. Postman query editörümüz aşağıdaki gibi görünecektir.(200 OK response’u ile birlikte)

 

authentication_request_and_response_with_postman

 

ASP.NET Core JWT Authentication API’nin Authentcated Methodunun Test Edilmesi

  • Token bilgisini kullanıcı adı ve şifresiyle aldıktan sonra, Authorization sekmesinde, Bearer token sekmesindeki Token için ayrılmış olan alana yapıştırıyoruz. HttpGet attribute’ı ile işaretlenmiş olan GetAll methodu için Get yöntemini kullanarak istek yapmamız gerekiyor. Böylece request alanları aşağıdaki gibi görünüyor.

 

Token’ımız kabul ediliyor ve kullanıcı bilgilerine ulaşıyoruz.

Asp.net kategorisin diğer konulara buradan ulaşabilirsiniz.

Yorum Yap

Yorum Yap

Yorumlar (3)

  1. 3 ay önce

    Bu tarz yazıların devamını bekliyoruz. Güzel ve açıklayıcı olmuş.
    Eline sağlık.

  2. Hikmet Eryıldız
    3 ay önce

    Eline sağlık Raziye. Güzel bir anlatım olmuş. Sıradaki yazını merakla bekliyoruz.

  3. 3 ay önce

    Müthişsin