背景
我正在我的 React 应用程序中测试隐式流身份验证,并尝试实现所谓的 静默刷新功能,在用户登录时,我定期要求一个新的访问令牌,而无需要求他提供新的授权。
以下是 Flow 模式Auth0 Tenant,在我的例子中,是 Spotify:
虽然使用隐式授权的 SPA(单页应用程序)不能使用刷新令牌,但还有其他方法可以提供类似的功能:
prompt=none调用/authorize端点时使用。用户不会看到登录或同意对话框。
/authorize从隐藏的 iframe调用并从父框架中提取新的访问令牌。用户不会看到重定向发生。
另一种方法是实现类似包axios-auth-refresh 的东西,一个库
帮助您通过
axios拦截器实现授权的自动刷新。当原始请求失败时,您可以轻松拦截原始请求,刷新授权并继续原始请求,无需任何用户交互。
用法:
import axios from 'axios';
import createAuthRefreshInterceptor from 'axios-auth-refresh';
// Function that will be called to refresh authorization
const refreshAuthLogic = failedRequest => axios.post('https://www.example.com/auth/token/refresh').then(tokenRefreshResponse => {
localStorage.setItem('token', tokenRefreshResponse.data.token);
failedRequest.response.config.headers['Authorization'] = 'Bearer ' + tokenRefreshResponse.data.token;
return Promise.resolve();
});
// Instantiate the interceptor (you can chain it as …Run Code Online (Sandbox Code Playgroud) 所以我只是花了最近几天试图解决这个问题并且问这个问题,以便我可以为其他遇到问题的人解答.
首先,谷歌文档是可怕的,并使用不同的oauth2库,具体取决于您正在查看的许多谷歌API示例.它通常是自相矛盾的,有时直接有代码在其中不起作用.
那好吧.
所以我的问题基本上是:
请参阅下面的答案,了解完整功能的授权流程,从获取初始令牌到保存,稍后加载,刷新和使用它.
干杯.
我不确定我是否理解刷新令牌的概念。我知道他们在做什么 - 将它们存储在某个地方,每当访问令牌过期时,就为他们获取一个新的访问令牌。
不泄露这个刷新令牌显然非常重要,否则第三方可以获得新的访问令牌。因此,它需要保持额外的安全。
我的问题是:为什么不让长期访问令牌更加安全?安全性的区别在哪里?
以下是 auth0.com 对这一事实的描述,例如:
好处:泄漏访问令牌的访问窗口更短(这些访问令牌很快过期,减少泄漏令牌允许访问受保护资源的机会)”
这对我来说没有任何意义。所以访问令牌很快过期,因此如果它被泄露,它“还不错”。
另一方面,如果刷新令牌泄漏,则非常糟糕。那么为什么不尝试让访问令牌与刷新令牌一样安全,并获得完全相同的结果,但要管理的令牌少了一个?
我有一个应用程序可以很好地进行身份验证并返回access_token和refresh_token。我将它们存储AsyncStorage并access_token使用 redux保存/获取。这是我正在构建的第一个应用程序,我正在努力解决如何以及在何处使用refresh_token.
这是组件中的 axios 调用 loginForm.js
axios({
url: `${base}/oauth/token`,
method: 'POST',
data: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
}
})
.then(response => {
setStatus({ succeeded: true });
// console.log(response.data);
deviceStorage.saveKey("userToken", response.data.access_token);
deviceStorage.saveKey("refreshToken", response.data.refresh_token);
Actions.main();
})
.catch(error => {
if (error.response) {
console.log(error);
}
});
Run Code Online (Sandbox Code Playgroud)
这是服务 deviceStorage.js
import { AsyncStorage } from 'react-native';
const deviceStorage = {
async saveItem(key, value) {
try {
await AsyncStorage.setItem(key, value);
} catch (error) { …Run Code Online (Sandbox Code Playgroud) 我在 keycloak (7.0.0) 中有一个具有给定配置的客户端 - 突出显示选项“启用对‘客户端凭据授予’的支持”:
当我获取该客户端的令牌 (POST /auth/realms/{my-realm}/protocol/openid-connect/token) 时,我收到以下 json 响应:
{
"access_token": "xxx",
"expires_in": 600,
"refresh_expires_in": 1800,
"refresh_token": "xxx",
"token_type": "bearer",
"not-before-policy": 1572415518,
"session_state": "xxx",
"scope": "xxx xxx"
}
Run Code Online (Sandbox Code Playgroud)
我想将它与OAuth2FeignRequestInterceptor集成,默认情况下它会忽略刷新令牌并每秒创建一个新会话 :access_tokenexpires_in
if (accessToken == null || accessToken.isExpired()) {
try {
// no refresh token usage here
accessToken = acquireAccessToken();
}
...
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
client_credentials,它是后端 -> 后端通信的授予类型?OAuth2 文档链接明确指出对于授权类型“不应包含刷新令牌” client_credentials。client_credentials授予类型的客户端发送刷新令牌?access-token oauth-2.0 openid-connect keycloak refresh-token
我一直试图让我的刷新令牌工作一段时间,我希望我很接近.我的令牌刷新并触发后续200调用导致401的任何调用,但我的页面上的数据不刷新.
访问令牌到期时,会发生以下情况:
在401之后,GetListofCompanyNames使用正确更新的访问令牌返回200,其中包含名称列表.但是,我的下拉列表不会刷新.
我的拦截器:
app.factory('authInterceptorService',['$q', '$location', 'localStorageService', '$injector', function($q, $location, localStorageService, $injector) {
return {
request: function(config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
},
responseError: function(rejection) {
//var promise = $q.reject(rejection);
var authService = $injector.get('authService');
if (rejection.status === 401) {
// refresh the token
authService.refreshToken().then(function() {
// retry the request
var $http = $injector.get('$http');
return $http(rejection.config);
});
}
if (rejection.status === 400) {
authService.logOut(); …Run Code Online (Sandbox Code Playgroud) 我在 IdentityServer4 中请求新的刷新令牌时遇到一些问题。身份验证后的某个时间,我从 API 收到未经授权的响应,好的,但是当我尝试请求新的刷新令牌时,我从服务器收到 invalid_grant。我确保设置了offline_access,但仍然遇到问题。这是我的代码:
服务器 Config.cs 中的我的客户端
new Client
{
ClientId = "myclientId",
ClientName = "MyClient",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
ClientSecrets =
{
new Secret("mySecret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowOfflineAccess = true,
UpdateAccessTokenClaimsOnRefresh = true,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
...
}
}
Run Code Online (Sandbox Code Playgroud)
来自 MVCclient 的我的 Startup.cs
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AccessDeniedPath = "/Home/Error403"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = …Run Code Online (Sandbox Code Playgroud) 在自然不安全的客户端(浏览器、手机等)中使用 JWT 时,我很难理解刷新令牌的使用。
对我来说,认为如果 JWT 被破坏,刷新令牌也没有被破坏的想法似乎很幼稚。
只要刷新令牌保持有效,攻击者本质上就拥有无限的 JWT 来源。即使您使使用的刷新令牌无效,如果攻击者实施稍微激进的刷新策略,他们仍然占上风。这与受损的长寿命 JWT 有何不同?
当使用长期存在的 JWT 时,攻击者只能继续获得有效的 JWT,前提是他们有能力持续利用首先赋予他们 JWT 的任何漏洞。使用刷新令牌,他们可以通过一次漏洞获得 JWT,然后随心所欲地获得新的 JWT,而不受惩罚。这似乎与长期存在的 JWT 一样安全,甚至可能更不安全。
我错过了什么?
我正在阅读Auth0网站上有关刷新令牌和SPA的文档,它们指出SPA不应使用刷新令牌,因为它们不能安全地存储在浏览器中,而应使用静默身份验证来检索新的访问令牌。
单页应用程序(通常实现隐式授予)在任何情况下都不应获得刷新令牌。这样做的原因是该信息的敏感性。您可以将其视为用户凭据,因为“刷新令牌”使用户可以永远保持身份验证。因此,您不能在浏览器中拥有此信息,必须将其安全地存储。
我糊涂了。据我了解,检索新访问令牌的唯一方法是将新请求以及某种形式的Auth0会话cookie提交给Auth服务器,以对登录的用户进行身份验证。收到会话cookie时,Auth0然后,服务器将能够发出新的访问令牌。
但是,与在浏览器或本地存储中具有刷新令牌有什么不同?是什么使会话Cookie比刷新令牌更安全?为什么在SPA中使用刷新令牌是一件坏事?
我知道(在 OAuth 中使用授权代码“授权代码”时),访问令牌的生命周期应该很短,但刷新令牌的生命周期可以很长。所以我为我的项目决定:
但授权码的典型生命周期是多长?我认为它应该非常非常短,对吗?也许像 1 小时甚至只有几分钟?
我找不到任何“最佳实践”。
refresh-token ×10
oauth-2.0 ×5
access-token ×3
jwt ×3
axios ×2
angularjs ×1
asp.net ×1
asp.net-core ×1
auth0 ×1
c# ×1
gmail-api ×1
google-api ×1
google-oauth ×1
keycloak ×1
oauth ×1
openid ×1
python ×1
react-native ×1
reactjs ×1
redux ×1
rest ×1
security ×1
spotify ×1