我正在将 AWS Cognito 用于我的 Web 应用程序。
\n我登录到我的网络应用程序并从浏览器开发模式获取访问/刷新令牌。
\n访问令牌可以在https://jwt.io/上解码上解码:
\n标题是
\n{\n "kid": "M+aYDxi5AeOrvlUkPyNA5GmA4V8ZdTPPnr5wO6M1neU=",\n "alg": "RS256"\n}\n\nRun Code Online (Sandbox Code Playgroud)\n有效负载为:
\n{\n "origin_jti": "0cf3100a-bfdd-49e0-bae3-12345678",\n "sub": "1585d704-2985-4447-b265-12345678",\n "event_id": "ead55f68-59d0-4b7f-9bb8-123",\n "token_use": "access",\n "scope": "aws.cognito.signin.user.admin",\n "auth_time": 1646640361,\n "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_123",\n "exp": 1646640661,\n "iat": 1646640361,\n "jti": "ea239510-8fd4-497d-b2ac-05a0377d63ef",\n "client_id": "123qwe",\n "username": "staff"\n}\n\nRun Code Online (Sandbox Code Playgroud)\n但是,刷新令牌未正确解码:\n标头:
\n{\n "cty": "JWT",\n "enc": "A256GCM",\n "alg": "RSA-OAEP"\n}\nRun Code Online (Sandbox Code Playgroud)\n有效负载是:
\n"v\xef\xbf\xbdzsV_%\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd$\xef\xbf\xbd\xef\xbf\xbd\\u0014\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd1\xef\xbf\xbd\xef\xbf\xbdZ\xef\xbf\xbdc\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdhyE\xef\xbf\xbd\\u0000\xef\xbf\xbd\\u0001\xef\xbf\xbd9W\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd5\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\\n\\n\xd2\xb4\xef\xbf\xbd\\t!8Mc\\u0000~3}K\xef\xbf\xbd4\xef\xbf\xbd\xef\xbf\xbdX=\\"\xef\xbf\xbd%\\u0015\xef\xbf\xbd2\xef\xbf\xbd\\"S,\xef\xbf\xbd\xef\xbf\xbdM\xef\xbf\xbd\xef\xbf\xbd\\u0000=S\xef\xbf\xbd\\u0011r\xef\xbf\xbd*H9\xef\xbf\xbd}\\u0002\xef\xbf\xbd\xef\xbf\xbdt]\xef\xbf\xbdxU\'\xef\xbf\xbdLk\xef\xbf\xbd\xef\xbf\xbdN\xee\xad\xa2\\n\xef\xbf\xbdxB\xef\xbf\xbdYg\xef\xbf\xbd`\xef\xbf\xbdm\xef\xbf\xbd\\n\xef\xbf\xbd_\xef\xbf\xbdey\xef\xbf\xbd\xef\xbf\xbdj\xef\xbf\xbdo\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd_\xef\xbf\xbdlJ\xef\xbf\xbde^\xef\xbf\xbdh\\n=\xef\xbf\xbd\\u001a\xef\xbf\xbdV7\xef\xbf\xbd!\xef\xbf\xbd]\xef\xbf\xbd5A\\u0014\\u0012(3\xef\xbf\xbd\xef\xbf\xbdi(mu\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\\u0018\xef\xbf\xbdc\xef\xbf\xbdY\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xd7\x81\xef\xbf\xbd\xef\xbf\xbd.VC\xef\xbf\xbd\xef\xbf\xbd3\xef\xbf\xbdyk6\xef\xbf\xbd\xef\xbf\xbd$b\xef\xbf\xbdX\xef\xbf\xbd5\xef\xbf\xbdC\xef\xbf\xbdQ\xef\xbf\xbd/\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd)\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd=\\u001b|a\xef\xbf\xbd\\u000b\\f\xef\xbf\xbd\\u0015/\\u0005\\u00057\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbda\xdf\xa8`\xef\xbf\xbdB\xef\xbf\xbd.\xef\xbf\xbd\\u000f\xef\xbf\xbd(]\xef\xbf\xbd\\\\\xef\xbf\xbd\\u0007G\xef\xbf\xbd"\nRun Code Online (Sandbox Code Playgroud)\n看起来刷新令牌的算法是RSA-OAEPhttps://jwt.io/站点尚不支持此算法。
是否有在线工具可以正确解码刷新令牌?
\nMicrosoft 建议不要HttpContext在 Blazor Server 中使用(此处)。为了解决如何将用户令牌传递到 Blazor Server 应用程序的问题,Microsoft 建议将令牌存储在服务中Scoped(此处)。Jon McGuire\xe2\x80\x99s 博客建议采用类似的方法将令牌存储在Cache(此处)中。
只要用户保持在同一个 Blazor 服务器连接中,上述 Microsoft\xe2\x80\x99s 方法就可以正常工作。但是,如果access_token刷新并且用户通过按 F5 或将 URL 粘贴到地址栏中来重新加载页面,则会尝试从 cookie 中检索令牌。此时, cookie中的和access_token就refresh_token不再有效了。Jon McGuire 在他的博客文章末尾提到了这个问题,并将其称为 Stale Cookies(此处)。他给出了有关可能的解决方案的提示,但对实施说明却很少提及。该帖子的底部有许多来自无法实施解决方案的人的评论,但没有提出明显的可行解决方案。我花了很多时间寻找解决方案,但我发现人们都在寻求解决方案,但没有收到任何有效的答案。
找到了一个似乎运行良好并且似乎相当有原则的解决方案后,我认为可能值得在这里分享我的解决方案。我欢迎任何建设性的批评或对任何重大改进的建议。
\noauth access-token openid-connect refresh-token blazor-server-side
我想在访问令牌过期时刷新它。我已经实现了 Authenticator,如下所示:
@Singleton
class TokenAuthenticator(
val authService: Lazy<AuthService>,
private val sharedPreferences: SharedPreferences
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
return authRequestWithNewToken(response.request)
}
private fun authRequestWithNewToken(
request: Request
): Request? {
getFreshAccessToken()?.let { freshToken ->
return getNewRequest(request, freshToken)
}
return null
}
private fun getFreshAccessToken(): String? {
val refreshResponse = authService.get().refreshTokenTemp().execute()
if (refreshResponse.isSuccessful) {
val updatedAccessToken =
refreshResponse.body()?.data?.accessToken ?: return null
val updatedRefreshToken =
refreshResponse.body()?.data?.refreshToken ?: return null
updateToken(updatedAccessToken, updatedRefreshToken)
Timber.tag("TOKEN")
.d("Auth Updated token\n AccessToken: $updatedAccessToken …Run Code Online (Sandbox Code Playgroud) 我已经使用模型createToken上的方法User来创建个人访问令牌。现在我想在代码中刷新该令牌,而不需要对oauth/token/refresh. 我怎么能这么做呢?
注意:我已经分离了我的客户端(Vue.js)和服务器(DjangoRest)。我正在使用 JWT 来验证从客户端向服务器发出的每个请求。Flow- 客户端将用户凭据发送到服务器。如果凭据有效,服务器会发回刷新和访问令牌。客户端存储访问和刷新令牌。我已将刷新令牌到期时间设置为 1 周,访问时间为 30 分钟。接下来,我想确保访问令牌在其到期前 15 分钟自动刷新。为此,将客户端存储的刷新令牌发送到服务器,然后服务器发出新的访问令牌和刷新令牌,将其发送回客户端。我如何在 Vuex 商店中实现这一点?我是 Web 开发和 vue.js 的完全新手。如果有人可以提供一些代码或详细解释,那就太好了。
我已经在商店中实现了 loginUser、logout user、registerUser,它们运行良好。但我坚持使用自动刷新逻辑。我的猜测是客户端必须反复检查剩余的访问令牌到期时间。当还剩下大约 15 分钟时,我们必须初始化自动刷新功能。请帮我解决这个逻辑。
这是我的 Vueex 商店:
import Vue from 'vue'
import Vuex from 'vuex'
import axiosBase from './api/axios-base'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
accessToken: '' || null,
refreshToken: '' || null
},
getters: {
loggedIn (state) {
return state.accessToken != null
}
},
mutations: {
loginUser (state) {
state.accessToken = localStorage.getItem('access_token')
state.refreshToken = localStorage.getItem('refresh_token')
},
destroyToken (state) {
state.accessToken = …Run Code Online (Sandbox Code Playgroud) 我正在我的一个节点应用程序中实现 JWT。我想知道,是否有任何明确的格式/结构可以生成刷新令牌?
通过明确的格式,我的意思是刷新令牌是否包含任何像 JWT 这样的声明?
更新
让我们假设刷新令牌是:(fdb8fdbecf1d03ce5e6125c067733c0d51de209c取自Auth0)。现在,我应该从中了解什么?
我的应用程序使用 Google 刷新令牌(从 Google 获取 access_token)。我在这里有两个问题:
refresh_token_old假设我在 1 月 1 日下午 5:00获得了刷新令牌,并且我的应用程序refresh_token_new在 1 月 1 日下午 5:30(即 30 分钟后)向 Google 请求了另一个刷新令牌,旧的刷新令牌是否仍然有效(显然是旧的还没过期)?-- 基本上,我是在问新发行的refresh_token是否会清除旧refresh_token的有效性;access_token_a对于我使用从 Google 获取的访问令牌refresh_token_old,在我的应用程序请求新的新鲜令牌后它仍然有效吗refresh_token_new?-- 基本上,我问新的refresh_token是否会清除旧的refresh_token获得的access_token的有效性,即使该access_token尚未过期;google-api access-token oauth-2.0 google-oauth refresh-token
我对此访问令牌和刷新令牌完全陌生,如果有任何地方错误,请纠正我。据我所知,刷新令牌轮换意味着每次用户请求 AT(具有有效 RT)时,都会给出新的 AT1 和 RT1 对。因此,下次用户应使用新的 RT1 更新 AT,并将获得新的 AT2 和 RT2 对。
我的问题是:
为了实现 RT 旋转,我们需要将 RT 存储在数据库中。那么我们需要将旧的 RT 和新发布的 RT 存储在 DB 中。根据这个,我们需要存储所有过期的 RT,并且需要检查 DB 中的每个 AT 续订请求,如果它在 DB 中,那么我们需要立即使刷新令牌系列失效。但如果我们这样做,我们可能需要在数据库中为单个用户存储更多的 RT,当考虑到系统中的所有用户时,这将是巨大的。这是实现 RT 旋转的正确方法吗?如果不是,那么实现 RT 旋转的正确方法是什么?
在本文档中,关于 RT 轮换(在自动重用检测第四点下),他们提到这样会立即使刷新令牌系列失效。这是否意味着从初始身份验证发出的每个 RT 都将具有相同的特征来将它们标识为一个令牌系列(因为它被称为“刷新令牌系列”)
当用户从系统注销时,我们如何使 RT 失效?我不认为简单地从 cookie 中删除 RT 不是正确的方法,因为例如,如果 RT 的过期时间是一天,并且用户在过期时间之前注销,那么 RT 仍然可用(除非我们将之前的 RT 存储在数据库中)并检查AT的下一次更新),直到达到其到期时间。那么如何解决这个问题呢。
当用户登录 API 时会生成一个令牌,以便他可以访问其他端点,但该令牌会在 60 秒后过期,我创建了一个函数来使用旧令牌(存储在数据库中)生成新的有效令牌,但是当我要生成新的有效令牌时,我收到 SecretOrPrivateKey 必须有一个值错误
函数refreshToken使用函数login生成一个新的token
secretOrPrivateKey must have a value
Error: secretOrPrivateKey must have a value
at Object.module.exports [as sign] (C:\Users\talis\nova api\myflakes_api\node_modules\jsonwebtoken\sign.js:107:20)
at JwtService.sign (C:\Users\talis\nova api\myflakes_api\node_modules\@nestjs\jwt\dist\jwt.service.js:28:20)
at AuthService.login (C:\Users\talis\nova api\myflakes_api\src\auth\auth.service.ts:18:39)
at TokenService.refreshToken (C:\Users\talis\nova api\myflakes_api\src\token\token.service.ts:39:37)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at TokenController.refreshToken (C:\Users\talis\nova api\myflakes_api\src\token\token.controller.ts:12:16)
at C:\Users\talis\nova api\myflakes_api\node_modules\@nestjs\core\router\router-execution-context.js:46:28
at C:\Users\talis\nova api\myflakes_api\node_modules\@nestjs\core\router\router-proxy.js:9:17
Run Code Online (Sandbox Code Playgroud)
token.service.ts文件中的函数refreshToken
async refreshToken(oldToken: string) {
let objToken = await this.tokenRepository.findOne({hash: oldToken})
if (objToken) {
let user = await this.userService.findOneOrFail({email:objToken.email})
return this.authService.login(user)
} else {
return new UnauthorizedException(MessagesHelper.TOKEN_INVALID)
} …Run Code Online (Sandbox Code Playgroud) 我已经在这个问题上摸不着已经好几天了.我在IdentityServer4上遇到问题,其中令牌响应不包含刷新令牌.我已经在获取访问令牌方面做得很好 - 这只是我似乎无法弄清楚的刷新令牌.
在我的project.json文件中,我添加了以下条目:
"IdentityServer4": "1.0.0-rc3",
"IdentityServer4.AccessTokenValidation": "1.0.1-rc3"
Run Code Online (Sandbox Code Playgroud)
我的Startup.cs文件包含以下内容:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddInMemoryClients(Config.Clients.Get())
.AddInMemoryScopes(Config.Scopes.Get())
.AddInMemoryUsers(Config.Users.Get())
.AddTemporarySigningCredential();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseIdentityServer();
}
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到我正在使用Config.Clients,Config.Scope和Config.Users.这是(Config.cs)的代码:
public class Config
{
internal class Clients
{
public static IEnumerable<Client> Get()
{
return new List<Client> {
new Client
{
ClientId = "client",
ClientName = "Authentication Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AccessTokenLifetime = 1800,
RefreshTokenExpiration = TokenExpiration.Absolute,
AbsoluteRefreshTokenLifetime = 1800,
ClientSecrets = new List<Secret> {
new Secret("secret".Sha256())
},
AllowedScopes …Run Code Online (Sandbox Code Playgroud) c# access-token asp.net-core-1.0 identityserver4 refresh-token
refresh-token ×10
access-token ×5
jwt ×5
oauth ×3
node.js ×2
oauth-2.0 ×2
android ×1
c# ×1
express ×1
google-api ×1
google-oauth ×1
javascript ×1
laravel ×1
nestjs ×1
okhttp ×1
retrofit ×1
token ×1
typescript ×1
vue.js ×1