首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IdentityServer4 -在执行混合MVC快速启动之后使用刷新令牌

IdentityServer4 -在执行混合MVC快速启动之后使用刷新令牌
EN

Stack Overflow用户
提问于 2017-01-19 12:36:57
回答 6查看 25.8K关注 0票数 17

我遵循了文档页面中的Quickstart,并使用IdentityServer进行身份验证,使用IdentityServer对三个服务(IdentityServer、一个Api服务、一个ASPNET应用程序)进行了工作配置。

一切都很完美(登录、登录、授权等)直到1小时后access_token到期。此时,MVC应用程序开始(正确地)从API服务接收401 (因为令牌过期)。此时,我知道我应该使用refresh_token来获得一个新的access_token。

我正在寻找一种自动刷新access_token的机制,并无意中发现了这个机制:https://github.com/mderriey/TokenRenewal/blob/master/src/MvcClient/Startup.cs (来自这个答案)。我试着使用它,但它没有工作( TokenEndpointResponse是空的,即使身份验证是成功的)。

我理解如何使用refresh_token来获得新的access_token,但是在获得它之后,我将如何将它插入cookie中,以便将来的请求能够访问新的令牌?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-01-19 15:09:36

McvHybrid示例有一个很好的示例,可以将新的access_tokenrefresh_token返回到主体中。下面是带有代码的github文件的链接,它位于RenewTokens()中,如下所示。

代码语言:javascript
复制
    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");
    }
票数 13
EN

Stack Overflow用户

发布于 2017-07-24 19:01:36

作为MVC客户端RenewTokens方法的一种选择,我做了一个筛选器,在令牌到期大约10分钟或更短的时间内自动完成任务。

代码语言:javascript
复制
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);
            }
        }
    }
}

用法:

代码语言:javascript
复制
[Authorize]
[TokenFilter]
public class HomeController : Controller
{}
票数 9
EN

Stack Overflow用户

发布于 2018-06-12 11:13:48

首先,确保使用IdentityModel库(nuget )。第二,由于8月2.0已经发布,因此存在一些严重的变化,拉法解决方案中使用的HttpContext.Authentication现在已经过时。以下是重新启动并作为过滤器运行所应做的更改

代码语言:javascript
复制
var expat = filterContext.HttpContext.Authentication.GetTokenAsync("expires_at").Result;

应成为:

代码语言:javascript
复制
var expat = filterContext.HttpContext.GetTokenAsync("expires_at").Result;
代码语言:javascript
复制
var rt = filterContext.HttpContext.Authentication.GetTokenAsync("refresh_token").Result;

应成为:

代码语言:javascript
复制
var rt = filterContext.HttpContext.GetTokenAsync("refresh_token").Result;
代码语言:javascript
复制
var oldIdToken = filterContext.HttpContext.Authentication.GetTokenAsync("id_token").Result;

应该变成

代码语言:javascript
复制
var oldIdToken = filterContext.HttpContext.GetTokenAsync("id_token").Result;
代码语言:javascript
复制
var info = filterContext.HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies").Result;

应该变成

代码语言:javascript
复制
var info = filterContext.HttpContext.AuthenticateAsync("Cookies").Result;
代码语言:javascript
复制
filterContext.HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);

应该变成

代码语言:javascript
复制
filterContext.HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);

这是一个完整的代码:

代码语言:javascript
复制
public class TokenFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var expat = filterContext.HttpContext.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.GetTokenAsync("refresh_token").Result;
            var tokenResult = tokenClient.RequestRefreshTokenAsync(rt).Result;

            if (!tokenResult.IsError)
            {
                var oldIdToken = filterContext.HttpContext.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.AuthenticateAsync("Cookies").Result;
                info.Properties.StoreTokens(tokens);  
                filterContext.HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);
            }
        }
    }
}

美国а通用和拉斐尔展示的一样。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41741982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档