2017-01-19 9 views
5

के लिए क्विकस्टार्ट का पालन करने के बाद रीफ्रेश टोकन का उपयोग करके मैंने प्रलेखन पृष्ठ में क्विकस्टार्ट का पालन किया है और प्रमाणीकरण के लिए पहचान सर्वर का उपयोग करके तीन सेवाओं (पहचान सर्वर, एक एपीआई सेवा, एक एएसपीएनईटी एमवीसी अनुप्रयोग) की एक कार्यप्रणाली है।पहचान सर्वर 4 - हाइब्रिड एमवीसी

सब कुछ पूरी तरह से काम करता है (लॉगिन, लॉगिन, प्रमाणीकरण, आदि) 1 घंटे के बाद तक access_token की समयसीमा समाप्त हो जाती है। इस बिंदु पर, एमवीसी अनुप्रयोग एपीआई सेवा से 401 (सही ढंग से) प्राप्त करना शुरू कर देता है (क्योंकि टोकन समाप्त हो गया है)। उस बिंदु पर, मुझे पता है कि मुझे एक नया access_token प्राप्त करने के लिए refresh_token का उपयोग करना चाहिए।

मैं एक तंत्र की तलाश में था जो स्वचालित रूप से access_token को रीफ्रेश किया गया था और इस पर ठोकर खाई: https://github.com/mderriey/TokenRenewal/blob/master/src/MvcClient/Startup.cs (this answer से)। मैंने इसका उपयोग करने की कोशिश की लेकिन यह काम नहीं किया (प्रमाणीकरण सफल होने के बावजूद TokenEndpointResponse शून्य था)।

मैं समझता हूं कि refresh_token का उपयोग कैसे करें access_token प्राप्त करने के लिए, लेकिन मेरे पास यह होने के बाद, मैं इसे कुकी में वापस कैसे डालूं ताकि भविष्य के अनुरोध के नए टोकन तक पहुंच हो?

उत्तर

8

मैकहाइब्रिड नमूना के पास access_token और refresh_token को प्रिंसिपल में वापस लाने के लिए एक अच्छा उदाहरण है। कोड के साथ github फ़ाइल में link यहां दिया गया है, जो नीचे दिखाए गए अनुसार RenewTokens() में स्थित है।

public async Task<IActionResult> RenewTokens() 
    { 
     var disco = await DiscoveryClient.GetAsync(Constants.Authority); 
     if (disco.IsError) throw new Exception(disco.Error); 

     var tokenClient = new TokenClient(disco.TokenEndpoint, "mvc.hybrid", "secret"); 
     var rt = await  HttpContext.Authentication.GetTokenAsync("refresh_token"); 
     var tokenResult = await tokenClient.RequestRefreshTokenAsync(rt); 

     if (!tokenResult.IsError) 
     { 
      var old_id_token = await HttpContext.Authentication.GetTokenAsync("id_token"); 
      var new_access_token = tokenResult.AccessToken; 
      var new_refresh_token = tokenResult.RefreshToken; 

      var tokens = new List<AuthenticationToken>(); 
      tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.IdToken, Value = old_id_token }); 
      tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.AccessToken, Value = new_access_token }); 
      tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.RefreshToken, Value = new_refresh_token }); 

      var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn); 
      tokens.Add(new AuthenticationToken { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) }); 

      var info = await HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies"); 
      info.Properties.StoreTokens(tokens); 
      await HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties); 

      return Redirect("~/Home/Secure"); 
     } 

     ViewData["Error"] = tokenResult.Error; 
     return View("Error"); 
    } 
+1

McvHybrid नमूना RenewTokens में केवल (यदि लिंक पर क्लिक के माध्यम से) मैन्युअल रूप से लागू कर रहे हैं। क्या आप एक उदाहरण जानते हैं जहां एक्सेस टोकन समाप्त होने के बारे में टोकन रीफ्रेश किया जाता है? –

+0

आप उपरोक्त कोड को कुछ मिडलवेयर में आसानी से फेंक सकते हैं जो एमवीसी से पहले आपकी पाइपलाइन में पंजीकृत है। – LugTread

+1

@LugTread मुझे नहीं लगता कि आपको इसका कुछ उदाहरण होगा? मैं .NET कोर में एमवीसी के लिए काफी नया हूं और मैंने कभी भी मिडलवेयर नहीं लिखा है, मैं अब इसमें देख रहा हूं लेकिन अगर आपने कुछ ऐसा किया है और कोड नमूना है जो बहुत ही बढ़िया होगा। धन्यवाद। – bgs264

1

MVC ग्राहक example से RenewTokens विधि के लिए एक विकल्प के रूप में, मुझे लगता है कि काम स्वचालित रूप से बनाता है, जब टोकन के बारे में 10 मिनट या समाप्त करने के लिए कम है एक फिल्टर बनाया है।

public class TokenFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var expat = filterContext.HttpContext.Authentication.GetTokenAsync("expires_at").Result; 

     var dataExp = DateTime.Parse(expat, null, DateTimeStyles.RoundtripKind); 

     if ((dataExp - DateTime.Now).TotalMinutes < 10) 
     { 
      var disco = DiscoveryClient.GetAsync("http://localhost:5000/").Result; 
      if (disco.IsError) throw new Exception(disco.Error); 

      var tokenClient = new TokenClient(disco.TokenEndpoint, "clientId", 
       "clientSecret"); 

      var rt = filterContext.HttpContext.Authentication.GetTokenAsync("refresh_token").Result; 
      var tokenResult = tokenClient.RequestRefreshTokenAsync(rt).Result; 

      if (!tokenResult.IsError) 
      { 
       var oldIdToken = filterContext.HttpContext.Authentication.GetTokenAsync("id_token").Result; 
       var newAccessToken = tokenResult.AccessToken; 
       var newRefreshToken = tokenResult.RefreshToken; 

       var tokens = new List<AuthenticationToken> 
       { 
        new AuthenticationToken {Name = OpenIdConnectParameterNames.IdToken, Value = oldIdToken}, 
        new AuthenticationToken 
        { 
         Name = OpenIdConnectParameterNames.AccessToken, 
         Value = newAccessToken 
        }, 
        new AuthenticationToken 
        { 
         Name = OpenIdConnectParameterNames.RefreshToken, 
         Value = newRefreshToken 
        } 
       }; 

       var expiresAt = DateTime.Now + TimeSpan.FromSeconds(tokenResult.ExpiresIn); 
       tokens.Add(new AuthenticationToken 
       { 
        Name = "expires_at", 
        Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) 
       }); 

       var info = filterContext.HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies").Result; 
       info.Properties.StoreTokens(tokens); 
       filterContext.HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties); 
      } 
     } 
    } 
} 

उपयोग:

[Authorize] 
[TokenFilter] 
public class HomeController : Controller 
{} 
संबंधित मुद्दे