Asp.NET Core 3.1 ile Token Bazlı Kimlik Doğrulaması ve Refresh Token Kullanımı(JWT)

Merhaba,

Günümüz web uygulamalarında veri güvenliğini sağlayabilmek için kullanıcı doğrulama yöntemleri arasından en etkili ve çağdaş olanlarından kabul edebileceğimiz Token Bazlı Kimlik Doğrulama yöntemi ile sistemsel ve kullanıcı açısından en az maliyette en yüksek verimi elde edebilmekte ve güvenli bir şekilde gerekli authorization işlemlerini gerçekleştirebilmekteyiz.

Bu makalemizde Asp.NET Core uygulamalarında Token Bazlı Kimlik Doğrulama yapılanmasını a’dan z’ye inceleyeceğiz. Esasında daha önceden bu konu üzerine kâh Asp.NET mimarisi için olsun kâh Node.JS için olsun birçok makale karalamış bulunmaktayım. İlgili makaleleri aşağıda listelersek eğer;

Görüldüğü üzere konuya dair bloğumuzda önceden birçok kaynak mevcuttur. Peki hoca, madem konuya dair önceden karaladıkların var. Ne diye tekrar aynı konuda içerik oluşturuyorsun? sorunuzu duyar gibiyim. Biliyorsunuz ki son zamanlarda Asp.NET Core Identity üzerine detaylı yazı dizisi kaleme almaktayım. İşte bu yazı dizisinde authentication yöntemlerinden biri olarak yer alacak ve konuyu sıfırdan ele alıp ve adım adım kodlama standartlarını belirleyecek bir içerik ortaya koyma niyetindeyim. Ayriyetten diğer makalelerde bulamayacağınız terminolojilerle birlikte farklı tanımlamalar ve yöntemlerde ele alınmış olacaktır.

İşte bu niyetle yeni bir minvalde yol alacağız… O halde haydi gelin başlayalım.

Başlarken

Makalemize başlarken bir adet Asp.NET Core Web API projesinin hali hazırda bulunmasıyla birlikte gerekli authentication kontrolünde bizlere eşlik edecek olan aşağıdaki “Users” tablosunu tasarlamamız gerekmektedir.

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public string RefreshToken { get; set; }
        public DateTime? RefreshTokenEndDate { get; set; }
    }

Users tablosunu Code First yahut Database First yaklaşımlarından herhangi biriyle tasarlayıp, oluşturabilirsiniz.

Oluşturulan “Users” tablosuna tekrar göz atarsak eğer standart kolonların dışında “RefreshToken” ve “RefreshTokenEndDate” kolonları mevcuttur. Bu kolonların ne amaçla oluşturulduğuna değinebilmek için öncelikle üretilecek token yapılanmasıyla ilintili “Access Token” ve “Refresh Token” terimlerini açıklamamız gerekmektedir.

  1. Access Token
    OAuth 2.0 protokolüne göre RFC 7519 standartında olan ve authorization neticesinde belirli bir expire süresine bağlı bir şekilde üretilip kullanıcıya sunulan güvenli bir anahtar değeridir. Anlayacağınız token’ın ta kendisidir 🙂
  2. Refresh Token
    Access token’ın expire süresi sona ermeye yaklaştığında veya sona erdiğinde yeni bir access token üretebilmek için kullanılan token değeridir. Kullanıcıya verilen access token değeri yanında refresh token değeri verilerek, access token süresi dolduğu taktirde bu refresh token ile yeni token talebinde bulunabilecektir. Böylece kullanıcı token süresi dolduğu taktirde oturumdan düşürülmeden yeni token elde edebilecek ve yoluna devam edecektir.

Dikkat!!! Her zaman Refresh Token Expiration Access Token Expiration’dan fazla olmalıdır!

İşte “Users” tablosundaki “RefreshToken” kullanıcı için üretilmiş olan refresh token değerini tutacak olan kolondur. “RefreshTokenEndDate” kolonu ise üretilen refresh token değerinin işlev/kullanım süresini belirleyecek olan zaman bilgisini tutan alandır.

Token Servisinin Uygulamaya Eklenmesi

Asp.NET Core uygulamasında token ile authentication işlemlerini gerçekleştirebilmek için JWT Token servisini uygulamaya eklememiz gerekmektedir. Bunun için “Startup.cs” dosyasındaki “ConfigureServices” metodu içerisinde “AddAuthentication” middleware’i aracılığıyla bir şema oluşturarak işe başlamalıyız. İlgili metodu aşağıdaki görselde olduğu gibi çağırarak ikinci overloadına göz atarsak eğer;
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
görüldüğü üzere bir default scheme değeri istemektedir.
Peki bizden istenen bu default scheme değeri nedir?
Bir authentication işlemini farklı pozisyonlar için farklı şekilde tanımlamak isteyebiliriz.
Örneğin; ‘Bayi Authentication‘ – ‘Kullanıcı Authentication‘ gibi…
İşte bu mantıkta bir isimlendirmeyle farklı authentication şeması tanımlanabilir. Bizler ister benzer şekilde opsiyonel değerler tanımlayarak şema belirleyebilir yahut default şema ayarı vererek buradaki ihtiyaca daha spesifik çözüm getirebiliriz. Eğer ki tercihimiz default şema ayarı ise bunun için “Microsoft.AspNetCore.Authentication.JwtBearer” kütüphanesindeki “JwtBearerDefaults” sınıfını kullanmamız gerekecektir.

Velhasıl, JWT Token servisini uygulamaya entegre edersek;

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

        public IConfiguration Configuration { get; }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(option =>
            {
                option.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = true,
                    ValidateIssuer = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Token:Issuer"],
                    ValidAudience = Configuration["Token:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Token:SecurityKey"])),
                    ClockSkew = TimeSpan.Zero
                };
            });
            .
            .
            .
            services.AddControllers();
        }
    }

şeklinde çalışma yapmamız yeterli olacaktır. Burada dikkat ederseniz “Audience”, “Issuer”, “LifeTime”, “SigningKey” ve “ClockSkew” kavramları mevcuttur. Bu kavramların ne olduğuna dair bir açıklama yapmamız gerekirse eğer;

  • Audience
    Oluşturulacak token değerini kimlerin/hangi originlerin/sitelerin kullanacağını belirlediğimiz alandır. Örneğin; “www.bilmemne.com”
  • Issuer
    Oluşturulacak token değerini kimin dağıttığını ifade edeceğimiz alandır. Örneğin; “www.myapi.com”
  • LifeTime
    Oluşturulan token değerinin süresini kontrol edecek olan doğrulamadır.
  • SigningKey
    Üretilecek token değerinin uygulamamıza ait bir değer olduğunu ifade eden security key verisinin doğrulamasıdır.
  • ClockSkew
    Üretilecek token değerinin expire süresinin belirtildiği değer kadar uzatılmasını sağlayan özelliktir. Örneğin; kullanılabilirlik süresi 5 dakika olarak ayarlanan token değerinin ClockSkew değerine 3 dakika verilirse eğer ilgili token 5 + 3 = 8 dakika kullanılabilir olacaktır. Bunun nedeni, aralarında zaman farkı olan farklı lokasyonlardaki sunucularda yayın yapan bir uygulama üzerinde elde edilen ortak token değerinin saati ileride olan sunucuda geçerliliğini daha erken yitirmemesi için ClockSkew propertysi sayesinde aradaki fark kadar zamanı tokena eklememiz gerekmektedir. Böylece kullanım süresi uzatılmış ve tüm sunucularda token değeri adil kullanılabilir hale getirilmiş olunacaktır.

Şimdi yönümüzü tekrar yukarıdaki kod bloğuna çevirerek 15 ile 22. satır arasındaki yapılanları inceleyelim;

  • 15. satır; ‘ValidateAudience’ ile token üzerinde Audience doğrulamasını aktifleştirdik.
  • 16. satır; ‘ValidateIssuer’ ile token üzerinde Issuer doğrulamasını aktifleştirdik.
  • 17. satır; ‘ValidateLifetime’ ile token değerinin kullanım süresi doğrulamasını aktifleştirdik.
  • 18. satır; ‘ValidateIssuerSigningKey’ ile token değerinin bu uygulamaya ait olup olmadığını anlamamızı sağlayan Security Key doğrulamasını aktifleştirdik.
  • 19. satır; ‘ValidIssuer’ ile uygulamadaki tokenın Issuer değerini belirledik.
  • 20. satır; ‘ValidAudience’ ile uygulamadaki tokenın Audience değerini belirledik.
  • 21. satır; ‘IssuerSigningKey’ ile Security Key doğrulaması için SymmetricSecurityKey nesnesi aracılığıyla mevcut keyi belirtiyoruz.
  • 22. satır; ‘ClockSkew’ ile TimeSpan.Zero değeri ile token süresinin üzerine ekstra bir zaman eklemeksizin sıfır değerini belirtiyoruz.

Ayriyetten yukarıdaki kod bloğunda kullanılan değerler için Configuration propertysi kullanılmaktadır. Yani bu ilgili verileri “appsettings.json” dosyasından okuyoruz anlamına gelmektedir. Haliyle örnek uygulamamızda verileri ilgili dosyada aşağıdaki gibi tuttuğumuzu ifade etmekte fayda var;

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Token": {
    "Issuer": "www.myapi.com",
    "Audience": "www.bilmemne.com",
    "SecurityKey":  "doldur be meyhaneci, boş kalmasın kadehim ..."
  }
}

Token Handler Sınıfını Oluşturma

JWT Token servisini uygulamaya entegre ettikten sonra sıra Token değerini oluşturmaktan sorumlu olan Token Handler sınıfını inşa etmeye geldi.

İlk olarak üretilecek token ve refresh token değerlerini taşıyacak olan “Token” modelimizi tasarlıyoruz.

    public class Token
    {
        public string AccessToken { get; set; }
        public DateTime Expiration { get; set; }
        public string RefreshToken { get; set; }
    }

Ardından Token Handler sınıfımızı inşa edebiliriz;

    public class TokenHandler
    {
        public IConfiguration Configuration { get; set; }
        public TokenHandler(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        //Token üretecek metot.
        public TokenAuthentication.Models.Token CreateAccessToken(User user)
        {
            Models.Token tokenInstance = new Models.Token();

            //Security  Key'in simetriğini alıyoruz.
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Token:SecurityKey"]));

            //Şifrelenmiş kimliği oluşturuyoruz.
            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            //Oluşturulacak token ayarlarını veriyoruz.
            tokenInstance.Expiration = DateTime.Now.AddMinutes(5);
            JwtSecurityToken securityToken = new JwtSecurityToken(
                issuer: Configuration["Token:Issuer"],
                audience: Configuration["Token:Audience"],
                expires: tokenInstance.Expiration,//Token süresini 5 dk olarak belirliyorum
                notBefore: DateTime.Now,//Token üretildikten ne kadar süre sonra devreye girsin ayarlıyouz.
                signingCredentials: signingCredentials
                );

            //Token oluşturucu sınıfında bir örnek alıyoruz.
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

            //Token üretiyoruz.
            tokenInstance.AccessToken = tokenHandler.WriteToken(securityToken);

            //Refresh Token üretiyoruz.
            tokenInstance.RefreshToken = CreateRefreshToken();
            return tokenInstance;
        }

        //Refresh Token üretecek metot.
        public string CreateRefreshToken()
        {
            byte[] number = new byte[32];
            using (RandomNumberGenerator random = RandomNumberGenerator.Create())
            {
                random.GetBytes(number);
                return Convert.ToBase64String(number);
            }
        }
    }

Yukarıdaki kod bloğunu incelerseniz eğer access token ile birlikte refresh token değerlerini üretecek bir sınıf tasarlamış bulunmaktayız. Burada “CreateRefreshToken” metodu içerisinde refresh token değeri için “RandomNumberGenerator” nesnesinin kullanıldığına dikkatinizi çekerim. Alternatif olarak burada isterseniz Guid tipinde bir değer dönebilir yahut farklı bir Token değeri oluşturup refresh token olarak kullanabilirsiniz.

Controller’ların Oluşturulması

İlk olarak kullanıcılardan gelecek olan login istekleri için “UserLogin” view model’ını oluşturalım.

    public class UserLogin
    {
        public string Email { get; set; }
        public string Password { get; set; }
    }

Ardından kullanıcılar tarafından yapılacak olan kayıt yahut login isteklerini karşılayacak olan “Login(Controller).cs” dosyasını oluşturalım.

    [ApiController]
    [Route("api/[controller]")]
    public class LoginController : ControllerBase
    {
        readonly TokenExampleContext _context;
        readonly IConfiguration _configuration;
        public LoginController(TokenExampleContext content, IConfiguration configuration)
        {
            _context = content;
            _configuration = configuration;
        }
        [HttpPost("[action]")]
        public async Task<bool> Create([FromForm]User user)
        {
            _context.Users.Add(user);
            await _context.SaveChangesAsync();
            return true;
        }
        [HttpPost("action")]
        public async Task<TokenAuthentication.Models.Token> Login([FromForm]UserLogin userLogin)
        {
            User user = await _context.Users.FirstOrDefaultAsync(x => x.Email == userLogin.Email && x.Password == userLogin.Password);
            if (user != null)
            {
                //Token üretiliyor.
                TokenHandler tokenHandler = new TokenHandler(_configuration);
                TokenAuthentication.Models.Token token = tokenHandler.CreateAccessToken(user);

                //Refresh token Users tablosuna işleniyor.
                user.RefreshToken = token.RefreshToken;
                user.RefreshTokenEndDate = token.Expiration.AddMinutes(3);
                await _context.SaveChangesAsync();

                return token;
            }
            return null;
        }
    }

Authorization işlemlerini test edebilmek için kullanıcı isteklerini karşılayacak “Test(Controller).cs” dosyasını oluşturalım.

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class TestController : ControllerBase
    {
        public string Index()
        {
            return "Yetkilendirme başarılı...";
        }
    }

Yukarıdaki “Test(Controller).cs” sınıfını incelerseniz eğer “Authorize” attribute’u ile işaretlenerek yetkisiz erişim engellenir bir hale getirilmiştir.

Test Edelim

Sıra oluşturduğumuz yapılanmayı test etmeye gelmiştir. Tüm yapılanmayı Postman vasıtasıyla test edeceğiz.
İlk olarak kullanıcı oluşturalım.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
Ardından “Test(Controller)” controller’ına bir istekte bulunalım.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
Görüldüğü üzere ilgili istek neticesinde yetkisiz erişim yapmaya çalışıldığına dair “401 Unauthorized” durum kodunu döndürmektedir.

O halde token talebinde bulunalım.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
Görüldüğü üzere token talebi neticesinde bizlere access token, expiration ve refresh token verilerini barındıran bir JSON verisi döndürülmüştür. Artık yapmamız gereken ilgili access token değerini kullanıp bir önceki “Test(Controller)” sınıfına istekte bulunmaktır.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)

Yukarıdaki ekran görüntüsünü incelerseniz eğer “Headers” kategorisinde “Authorization” keyine karşılık verilen “Bearer {token}” değeri ile yapılan istek neticesinde token değerimizin başarılı bir şekilde doğrulandığını görmekteyiz.

Unutmayın!!! Token bazlı kimlik doğrulama senaryosunda sistemin çalışması için “Startup.cs” dosyasındaki “Configure” metodu içerisinde ‘UseAuthorization’ middleware’ından önce ‘UseAuthentication’ middleware’inin çağrılması gerekmektedir. Aksi taktirde token ile yapılan istekler yine -401 Unauthorized- durum kodu olarak geri dönecektir.

Refresh Token Kullanımı

Üretilen token değerinin süresi bitmeden yahut bittiğinde kullanıcıyı yeniden login işlemleriyle meşgul etmeden gerekli yetkilendirmeyi tekrar sağlayabilmek için refresh token mekanizmasını kullanacağız. Bu mekanizma temelde aşağıdaki gibi bir stratejiden ibarettir.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
Yukarıdaki görüntüde olduğu gibi client öncelikle gerekli authorization için Authorization Server’a bir istekte bulunuyor ve bu istek neticesinde “Access Token” ile birlikte “Refresh Token” değerlerini elde ediyor. Süreçte Resource Server’a yapılan tüm istekler access token aracılığıyla gerçekleştiriliyor… Taa ki access token’ın süresi bitip geçersiz oluncaya kadar… İşte bu durumda kullanıcıyı tekrardan login sayfasına yönlendirerek kullanıcı adı ve şifre kontrolü yapmak yerine kullanıcıya önceden gönderilmiş olan refresh token değeri ile Authorization Server’a bir istekte daha bulunuluyor ve tekrar yeni bir access token üretilerek hiç vakit kaybetmeksizin kullanıcıya bu yeni token değeri ile kaldığı yerden devam etme olanağı tanınıyor. Tabi bu arada refresh token kullanıldıktan sonra geçerliliğini yitirerek üretilen access token değerine eşlik edebilecek yenisi üretilmiş oluyor.

Bu mantıkta refresh token değerini kullanarak yeni bir access token üretebilmek için gerekli istekleri karşılayacak endpointi aşağıdaki gibi tasarlayabiliriz.

    [ApiController]
    [Route("api/[controller]")]
    public class LoginController : ControllerBase
    {
        readonly TokenExampleContext _context;
        readonly IConfiguration _configuration;
        public LoginController(TokenExampleContext content, IConfiguration configuration)
        {
            _context = content;
            _configuration = configuration;
        }
        .
        .
        .
        [HttpGet("[action]")]
        public async Task<TokenAuthentication.Models.Token> RefreshTokenLogin([FromForm] string refreshToken)
        {
            User user = await _context.Users.FirstOrDefaultAsync(x => x.RefreshToken == refreshToken);
            if (user != null && user?.RefreshTokenEndDate > DateTime.Now)
            {
                TokenHandler tokenHandler = new TokenHandler(_configuration);
                TokenAuthentication.Models.Token token = tokenHandler.CreateAccessToken(user);

                user.RefreshToken = token.RefreshToken;
                user.RefreshTokenEndDate = token.Expiration.AddMinutes(3);
                await _context.SaveChangesAsync();

                return token;
            }
            return null;
        }
    }

Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)
Görüldüğü üzere refresh token değeri ile yapılan istek neticesinde yeni bir access token değeri elde etmekte ve bu değeri aşağıdaki görselde olduğu gibi devam faaliyetlerimizde kullanabilmekteyiz.
Asp.NET Core - Token Bazlı Kimlik Doğrulama(JWT)

Evet… Görüldüğü üzere Refresh Token ile birlikte Token Bazlı Yetkilendirme işlemi bu çabadan ibarettir diyebiliriz 🙂 Sabredipte son noktasına kadar okuduğunuz için teşekkür ederim.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

21 Cevaplar

  1. Recep Demir dedi ki:

    Merhabalar hocam
    Jwt te header da token göndermemiz ile bir güvenlik sorunu olmuyormu ?.
    Yani biri profiler dan bakım bizim api endpoint ve token degerimizi bildigi zaman api izinsiz kullanmış olmazmı. Bu konu hakkında nasıl bir çalışma ile jwt daha güvenli yapabiliriz ?.

  2. Ebubekir dedi ki:

    Merhabalar, Refresh Token Login yaparken Get methodunda body göndermişsiniz fakat Get işleminde body alınmıyor, Post olucaktı sanırım.

    • Gençay dedi ki:

      Merhaba,

          [HttpGet("[action]")]
          public async Task<TokenAuthentication.Models.Token> RefreshTokenLogin([FromForm] string refreshToken)
          {
              .
              .
              .
          }
      

      ‘refreshToken’ parametresi [FromForm] attribute’u ile işaretlenmiştir. Sanırım gözünüzden kaçmış 🙂

  3. oğuzhan dedi ki:

    Hocam bu token bazlı kimlik doğrulama yaparken İdentity de olan AppUser :IdentityUser modelini kullanarak yapmaya çalışıyorum yapamadım bi türlü acaba yapılamıormu yapılıorsada bildiğiniz bi kaynak var

  4. Gençay dedi ki:

    Sevgili okurların dikkatine;

    İlgili makalede aşağıdaki middlewareleri eklemeyi unutmuşum. Bilginize 🙂

                app.UseAuthentication();
                app.UseAuthorization();
    

    Sevgiler.

  5. selim dedi ki:

    Hocam refresh token çürüme süresi olamsı doğrum mu ? refresh token da çürürse tekrar login ekranına dönmesi gerekmez mi uygulamanın ?

  6. F.Ahmet dedi ki:

    Merhaba benim anlamadığım bir yer var. Token süresi dolduğunda otomatik olarak RefreshToken kullanılarak yeni Token alınması gerekiyor. Bunu nerede yaptınız. RefreshTokenLogin var ama bu otomatik değil. Yada JWT bunu kendisimi yapıyor.

    • Gençay dedi ki:

      Merhaba,

      İçerikte refresh token’ın mantığı ve teknik tasarımı ele alınmıştır lakin access token’ın süresi dolduğu vakit refresh token ile talepte bulunarak token’ı yenileme senaryosu artık kullanılan UI’da yapılan çalışmadaki stratejiye bırakılmıştır. Misal; jQuery ile yaptığınız istek neticesinde 401 hata koduyla error alırsanız, refresh token kullanılarak ilgili adrese istekte bulunabilir ve geçerli süre içerisindeyseniz access token’ı böylece yenileyebilirsiniz.

      Kolay gelsin.

  7. ibrahim dedi ki:

    Merhaba Recep,

    Genelde Login için gerekli kullanıcı adı ve şifre de açık bir şekilde istenmez. Belli bir algoritma ve key’e göre hashlenip eklenmesi istenir. Client hashleyerek gönderir ve karşı taraf bu hashi çözüp token verir.

  8. nasr dedi ki:

    merhaba,
    mesela bir haftalık bir access token oluşturduk, bir hafta geçti ve süresi doldu. mobil uygulamada da hala kullanıcı giriş yapılmış şekilde karşılanmalı. refresh token süresi ise access token’dan yalnızca 3 dakika fazla. access token bittiği andan itibaren kullanıcı sunucuya herhangi bir istek atmazsa 3 dakika sonra refresh token’ın da süresi bitecek demek oluyor. bu durumda nasıl kullanıcı girişi yapılmış halde kalabilir? (refresh token süresi +3 dakikadan fazla da olabilir yine de o süre içinde kullanıcının istek atmama ihtimali var)

    • Gençay dedi ki:

      Merhaba,

      Ben ne şekilde bir ihtiyaca binaen probleminiz olduğunu ne yazık ki tam olarak anlayabilmiş değilim. Access token süresi bittiğinde kullanıcıyı yormaksızın token değerini yenileyebilmek ve oturumdan düşürmemek için refresh token yapılanması kullanılmaktadır. Ee doğal olarak verilen süreler çerçevesinde kullanıcı tarafında herhangi bir hayat belirtisi yoksa ilgili tokenların etkinliğini yitirmesi en doğalı olacaktır. Refresh token süresinden daha fazla kullanıcıyı oturumda tutmayı istemek birnevi refresh token yapılanmasını gölgeleme zarureti doğuracağından dolayı, sualinize anladığım kadarıyla önerim, refresh token kullanmaksızın 60 günlük, 6 aylık vs. gibi süresi uzun bir access token üretmeniz ve sadece onu kullanmanızdır.

      Sevgiler.

      • nasr dedi ki:

        cevabınız için teşekkür ederim, aslında şunu söylemek istiyorum
        eğer ürün bir mobil uygulama ise ve bir kullanıcı haftada bir uygulamaya bakıyorsa (tüm kullanıcılar bu şekilde olmak zorunda değil bazısı daha sık bakıyordur) sunucuya o kullanıcıdan haftada bir istek geliyor

        token 3 günlük olduğunu varsayalım 3 gün sonra token expire oldu
        3gün+3 dakika sonra refresh token da expire oldu

        kullanıcı bir hafta sonra girdiğinde tekrar oturum açması mı gerekiyor?
        bu bir mobil uygulama için pek doğru bir senaryo olarak gelmedi bana refresh token’ın bu kadar kısa süreli olmasını pek anlayamadım belki örneğin bir banka uygulaması için doğru olabilir

        dediğiniz gibi uzun süre kullanıcıyı oturumda tutmak isteyen bir uygulamanın herhangi bir koşulda refresh token’a ihtiyacı olmaz olarak anlayabilir miyim?

        • Gençay dedi ki:

          Tekrar merhaba,

          Esasında JWT ile refresh token’ı mobil veya PC senaryosu diye ayırmak yanlış bir yorum olacaktır. JWT ile refresh token kullanıcıya kolaylık sağlaması için uygulanan mantıksal bir manevradır, algoritmadır. Kullanılacağı yer vardır, kullanılsa dahi pek yakışmayacağı yerler de vardır. Lakin bir kullanıcının herhangi bir platformdan 1 hafta sonra girdiğinde tekrar oturum açması sizin için problemse bunu JWT ile refresh token’dan bağımsız bir şekilde ele alıp ona göre geliştirme yapmanız sizce de daha doğru olmayacak mıdır?

          Nasıl ki, 10 tane 3’ün toplamı direkt olarak 3 + 3 + 3 + … + 3 şeklinde değilde 3 x 10 olarak hesaplamak işin doğasındansa benzer mantıkla refresh token’ında access token’dan biraz uzun olması bu stratejinin/mantığın/algoritmanın doğasındandır. Ve nasıl ki, ilk örneği anlayabilmek için toplamayı ve toplamanın nedenini anlamak gerekiyorsa, aynı şekilde ikinci vurgudaki refresh token için refresh token’ı ve nedenini anlamak gerekmektedir.

          Sözgelimi, dillendirdiğiniz senaryoda refresh token’ın mantığına aykırı bir problem görmemekteyim. Sanırım siz, çözüm getiremediğiniz noktalar çerçevesinde refresh token’ın kısalığına takılmışsınız 🙂 Bu durumda platformu ayırt edebilir bir kod geliştirerek ona göre access token ve refresh token üretebilmeniz yahut refresh token’ı istediğiniz kadar uzatma hüvviyetine sahip olmanız sizin için yeterli değil mi?

          Uzun lafın kısası demek istediğim ‘kuralları siz koyun, yazılım aracınız olsun‘ 😉

          Çok elzem olmasada yinede basit bir öneride bulunmamız gerekirse;

          Kullanıcıdan gelen isteğin hangi platformdan geldiğini(mobil, pc vs.) algılayıp mobil’den gelen isteklerde token’ın zamansal değerleri ile oynayarak, 1 hafta 10 günlük adil bir süre belirleyebilirsiniz.

          Sevgiler.

  9. Selahattin dedi ki:

    Hocam Merhaba
    JwtTokeni urettikten sonra WebUI kısmında nasıl kullanabiliriz ?

    Yani sessiona hangi adımda eklememiz gerekiyor ?

    Örnek bir config gösterebilir misiniz ?

  10. Selahattin dedi ki:

    Hocam Selamlar

    Jwt web token WebUI tarafında sessiona nasıl kaydedebiliriz. Bende bir takım hatalar oluşuyor runtime kısmında.

    Şöyle ki:

    WebUI tarafında gelen token’i Login actionunda sessiona setobjeyle atıyorum. Sonra startupda şu komuta

                app.Use(async(context, next) =>
                {
                    var JWToken = context.Session.GetString("JWToken");
                    if (!string.IsNullOrEmpty(JWToken))
                    {
                        context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
                    }
                    await next();
                });
    

    sessiiondan okuyorum.

    Şimdi sormak istediğim tam olarak şunlar:
    1- Tokeni sessionda tutmalı mıyım ?
    2- app.use komutu her http isteğine sorgulanıyor. tokenin süresi bitse bile sessionda token duruyor. Bundan dolayı site bir hayli yavaşlıyor ve en sonunda beni sistemden logoff ediyor. app.use komutunu doğru mu kullanıyorum ?
    3- Web site canlıda https üzerinden çıkıyor. Httponly gibi bir durum https istekleri içinde geçerli midir ?

    • Gençay dedi ki:

      Merhaba,

      Cevaplar aşağıdadır;
      1 – Token değerine ihtiyacınız yoksa silebilirsiniz.
      2 – Kanımca doğru bir middleware seçilimi yapmışsınız. Kendinizde yazıp değerlendirebilirsiniz.
      3 – Evet, geçerlidir.

      Kolay gelsin.

  1. 13 Şubat 2020

    […] Asp.NET Core 3.1 ile Token Bazlı Kimlik Doğrulaması ve Refresh Token Kullanımı(JWT) Not : Bu makale direkt olarak Identity mekanizmasıyla ilgili olmasada farklı bir kimlik doğrulama mekanizması konusunu kapsadığı için ilgili yazı dizisine dahil edilmiştir. […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*