最低权限的身份服务器无法在 Azure 上正常工作

2024-03-12

我正在尝试实现一个遵循 OAUTH2/OIDC 协议的架构。为了做到这一点,我为客户端提供了 STS(Identity Server v3)、ASP.NET WebApi 和 ASP.NET MVC 应用程序。我的目标是将 STS 和 REST 服务托管在 Azure 上,以便不同的客户端可以将它们用作公共服务。到目前为止,一切都很好。在我决定添加一个使用重定向流之一(授权代码流)的新客户端之前,一切似乎都运行顺利且完美。我想利用它提供的刷新令牌选项。我想向该客户端提供短期访问令牌(10 分钟),并让他使用刷新令牌来获取新令牌。这就是代码中的样子:

STS:

new Client 
{
    ClientId = "tripgalleryauthcode",
    ClientName = "Trip Gallery (Authorization Code)",
    Flow = Flows.AuthorizationCode, 
    AllowAccessToAllScopes = true,
    RequireConsent = false,

    RedirectUris = new List<string>
    {
        Tripgallery.Constants.TripgalleryMvcAuthCodePostLogoutCallback
    },           

    ClientSecrets = new List<Secret>()
    {
        new Secret(Tripgallery.Constants.TripgalleryClientSecret.Sha256())
    },

    // refresh token options
    AccessTokenType = AccessTokenType.Jwt,
    AccessTokenLifetime = 600,
    RefreshTokenUsage = TokenUsage.OneTimeOnly, // Every time generates new refresh token. Not only access token.
    RefreshTokenExpiration = TokenExpiration.Sliding,
    SlidingRefreshTokenLifetime = 1296000,

    PostLogoutRedirectUris = new List<string>()
    {
        Tripgallery.Constants.TripgalleryPostLogoutCallback
    }
}

Mvc应用程序(客户端):

private ObjectCache _cache;
private readonly string tokensCacheKey = "Tokens";

public HomeController()
{
    _cache = MemoryCache.Default;
}

// GET: Home
public ActionResult Index()
{
    var authorizeRequest = new AuthorizeRequest(Constants.BoongalooSTSAuthorizationEndpoint);

    var state = HttpContext.Request.Url.OriginalString;

    var url = authorizeRequest.CreateAuthorizeUrl(
    "tripgalleryauthcode",
    "code",
    "openid profile address tripgallerymanagement offline_access",
    Constants.TripgalleryMvcAuthCodePostLogoutCallback,
    state);

    HttpContext.Response.Redirect(url);
    return null;
}

public async Task<ActionResult> StsCallBackForAuthCodeClient()
{
    var authCode = Request.QueryString["code"];

    var client = new TokenClient(
    Constants.TripgallerySTSTokenEndpoint,
    "tripgalleryauthcode",
    Constants.TripgalleryClientSecret
    );

    var tokenResponse = await client.RequestAuthorizationCodeAsync(
    authCode,
    Constants.TripgalleryMvcAuthCodePostLogoutCallback
    );

    this._cache[this.tokensCacheKey] = new TokenModel()
    {
        AccessToken = tokenResponse.AccessToken,
        IdToken = tokenResponse.IdentityToken,
        RefreshToken = tokenResponse.RefreshToken,
        AccessTokenExpiresAt = DateTime.Parse(DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToString(CultureInfo.InvariantCulture))
    };

    return View();
}

public ActionResult StartCallingWebApi()
{
    var timer = new Timer(async (e) =>
    {
        var cachedStuff = this._cache.Get(this.tokensCacheKey) as TokenModel;
        await ExecuteWebApiCall(cachedStuff);
    }, null, 0, Convert.ToInt32(TimeSpan.FromMinutes(20).TotalMilliseconds));

    return null;
}

private async Task ExecuteWebApiCall(TokenModel cachedStuff)
{
    // Ensure that access token expires in more than one minute
    if (cachedStuff != null && cachedStuff.AccessTokenExpiresAt > DateTime.Now.AddMinutes(1))
    {
        await MakeValidApiCall(cachedStuff);
    }
    else
    {
        // Use the refresh token to get a new access token, id token and refresh token
        var client = new TokenClient(
            Constants.TripgallerySTSTokenEndpoint,
            "tripgalleryauthcode",
            Constants.TripgalleryClientSecret
        );

        if (cachedStuff != null)
        {
            var newTokens = await client.RequestRefreshTokenAsync(cachedStuff.RefreshToken);

            var value = new TokenModel()
            {
                AccessToken = newTokens.AccessToken,
                IdToken = newTokens.IdentityToken,
                RefreshToken = newTokens.RefreshToken,
                AccessTokenExpiresAt =
                    DateTime.Parse(
                        DateTime.Now.AddSeconds(newTokens.ExpiresIn).ToString(CultureInfo.InvariantCulture))
            };

            this._cache.Set(this.tokensCacheKey, (object)value, new CacheItemPolicy());

            await MakeValidApiCall(value);
        }
    }
}

问题是,如果我在 Azure 上托管 STS,由于某种原因,如果我决定在访问令牌过期后 20 分钟或更长时间内使用刷新令牌,则会收到错误。不管我的刷新令牌生命周期是 15 天。

这是STS生成的日志:

w3wp.exe Warning: 0 : 2017-04-06 12:01:21.456 +00:00 [Warning] AuthorizationCodeStore not configured - falling back to InMemory
w3wp.exe Warning: 0 : 2017-04-06 12:01:21.512 +00:00 [Warning] TokenHandleStore not configured - falling back to InMemory
w3wp.exe Warning: 0 : 2017-04-06 12:01:21.512 +00:00 [Warning] ConsentStore not configured - falling back to InMemory
w3wp.exe Warning: 0 : 2017-04-06 12:01:21.512 +00:00 [Warning] RefreshTokenStore not configured - falling back to InMemory
w3wp.exe Information: 0 : 2017-04-06 12:01:22.371 +00:00 [Information] Start token request
w3wp.exe Information: 0 : 2017-04-06 12:01:22.418 +00:00 [Information] Client secret id found: "tripgalleryauthcode"
w3wp.exe Information: 0 : 2017-04-06 12:01:22.418 +00:00 [Information] Client validation success
w3wp.exe Information: 0 : 2017-04-06 12:01:22.418 +00:00 [Information] Start token request validation
w3wp.exe Information: 0 : 2017-04-06 12:01:22.433 +00:00 [Information] Start validation of refresh token request
w3wp.exe Warning: 0 : 2017-04-06 12:01:22.574 +00:00 [Warning] "Refresh token is invalid"
 "{
  \"ClientId\": \"tripgalleryauthcode\",
  \"ClientName\": \"Trip Gallery (Authorization Code)\",
  \"GrantType\": \"refresh_token\",
  \"RefreshToken\": \"140cfb19405a6a4cbace29646751194a\",
  \"Raw\": {
    \"grant_type\": \"refresh_token\",
    \"refresh_token\": \"140cfb19405a6a4cbace29646751194a\"
  }
}"
w3wp.exe Information: 0 : 2017-04-06 12:01:22.590 +00:00 [Information] End token request
w3wp.exe Information: 0 : 2017-04-06 12:01:22.590 +00:00 [Information] Returning error: invalid_grant
w3wp.exe Information: 0 : 2017-04-06 12:01:29.465 +00:00 [Information] Start discovery request
w3wp.exe Information: 0 : 2017-04-06 12:01:29.512 +00:00 [Information] Start key discovery request

在我的本地计算机上运行的 STS 的情况与预期相同。我可以使用刷新令牌获取新令牌。

解决:问题到底是什么Fred Han - 微软金融时报指出。我需要为我的刷新令牌实现持久存储。实现它真的很容易。我就是这样做的:

Identity Server的Startup.cs :

var idServerServiceFactory = new IdentityServerServiceFactory()
                                .UseInMemoryClients(Clients.Get())
                                .UseInMemoryScopes(Scopes.Get());

//...

// use custom service for tokens maintainance
var customRefreshTokenStore = new CustomRefreshTokenStore();
idServerServiceFactory.RefreshTokenStore = new Registration<IRefreshTokenStore>(resolver => customRefreshTokenStore);

var options = new IdentityServerOptions
{
    Factory = idServerServiceFactory,

    // .....

}

idsrvApp.UseIdentityServer(options);

CustomRefreshTokenStore.cs

public class CustomRefreshTokenStore : IRefreshTokenStore
{
    public Task StoreAsync(string key, RefreshToken value)
    {
        // code that uses persitant storage mechanism
    }

    public Task<RefreshToken> GetAsync(string key)
    {
        // code that uses persitant storage mechanism
    }

    public Task RemoveAsync(string key)
    {
        // code that uses persitant storage mechanism
    }

    public Task<IEnumerable<ITokenMetadata>> GetAllAsync(string subject)
    {
        // code that uses persitant storage mechanism
    }

    public Task RevokeAsync(string subject, string client)
    {
        // code that uses persitant storage mechanism
    }
}

w3wp.exe 警告:0 : 2017-04-06 12:01:21.456 +00:00 [警告] AuthorizationCodeStore 未配置 - 回退到 InMemory

w3wp.exe 警告:0 : 2017-04-06 12:01:21.512 +00:00 [警告] TokenHandleStore 未配置 - 回退到 InMemory

w3wp.exe 警告:0 : 2017-04-06 12:01:21.512 +00:00 [警告] ConsentStore 未配置 - 回退到 InMemory

w3wp.exe 警告:0 : 2017-04-06 12:01:21.512 +00:00 [警告] RefreshTokenStore 未配置 - 回退到 InMemory

您似乎在内存中存储/维护数据,如果您将数据托管在负载均衡器后面具有多个实例的 Azure 网站上,这可能是问题的原因。您可以尝试将数据存储在其他数据存储中,而不是内存存储中。

_cache = MemoryCache.Default;

此外,您还可以存储和检索tokensCacheKey通过 Web API 应用程序中的内存,这在 Azure 多实例 Web 场环境中无法正常工作。请将数据存储在外部存储中,例如Azure存储、数据库或Redis缓存。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最低权限的身份服务器无法在 Azure 上正常工作 的相关文章

  • keycloak 令牌自省总是失败并显示 {"active":false}

    我有点急于让这件钥匙斗篷发挥作用 我可以进行身份 验证 但由于某种原因 我的令牌内省总是失败 例如 如果我尝试进行身份验证 curl d client id flask api d client secret 98594477 af85 4
  • Azure 移动服务和 Azure Web 应用身份验证

    当用户通过 Azure Web 应用程序 ASP NET MVC 和 Xamarin iOS 应用程序登录时 我为同一用户获得两个不同的 SID Setup 带有 API 控制器的 Azure WebApp ASP NET 5 带有 Mic
  • Google / OAuth 2 - 自动登录

    我正在尝试结合一些 Google API 来使用 OAuth 2 0 虽然授权过程非常简单 但在初始授权完成后 我遇到了自动授权的问题 So 1 Authorization is done for the first time user g
  • Android Google+ 无法获取授权码

    我正在尝试根据这篇文章获取 Google 授权码 您的应用程序的服务器端访问 https developers google com mobile android sign in server side access for your ap
  • 始终“具有离线访问权限”|谷歌 OAuth 2

    我正在尝试使用 Google OAuth2 api 获取用户的个人资料 用户身份验证后 在同意页面上 总是要求我 具有离线访问权限 浏览器中的 URL 如下所示 https accounts google com o oauth2 auth
  • 如何使用 OAuth 2.0 实现 Web 小部件

    我想创建一个 Web 小部件来显示我网站上的信息 该小部件将使用 JavaScript 包含在客户网站的 HTML 中 并且只能用于我的客户 在我的网站上注册的网站 小部件中的信息应该特定于当前正在访问客户站点的用户 因此 我需要对客户端
  • JavaMail 连接到 Office 365 XOAUTH2 进行 IMAP 身份验证失败

    使用 OAuth2 0 在线 Office365 面临连接问题 我已经设置了应用程序权限以及 IMAP 和 SMTP 连接 基本身份验证似乎工作正常 我相信 IMAP 已启用 我的应用程序配置为任何组织目录 任何 Azure AD 目录 多
  • Azure WebApp - 无法自动检测应用程序的运行时堆栈

    我正在尝试创建只有静态 HTML 的 Web 应用程序 我正在关注这个链接https learn microsoft com en us azure app service app service web get started html
  • 当用户存储在外部身份提供商服务中时与用户的关系

    我正在尝试为其创建一个 API 和一个网站客户端 最近 我读了很多关于 OAuth2 作为安全机制的文章 以及提供身份验证服务的公司 例如auth0 com https auth0 com 甚至 Azure Active Directory
  • 使用 localhost 端点从 Web 作业访问 Azure Web 应用程序?

    如果我在 Azure 中部署了一个 Web 应用程序 ASP NET MVC 并且还配置了一个与该 Web 应用程序一起运行的 Web 作业 那么我的理解是 该 Web 作业是一个运行并等待的控制台应用程序 或类别 来自队列的消息 当消息到
  • 函数 isAssignableFrom 在服务器启动期间返回 false

    实施oauth2系统 我在使用以下代码时遇到一些问题 import org springframework security oauth2 provider endpoint FrameworkEndpointHandlerMapping
  • OAuth 2.0:优点和用例 - 为什么?

    谁能解释一下 OAuth2 的优点以及为什么我们应该实施它 我问这个问题是因为我对此有点困惑 这是我目前的想法 OAuth1 更准确地说是 HMAC 请求看起来合乎逻辑 易于理解 易于开发并且非常非常安全 相反 OAuth2 带来了授权请求
  • 使用 OAuth2 对应用程序*和*网站进行身份验证

    我正在开发一个主要通过应用程序访问的网站 我想使用 OAuth2 进行用户注册和身份验证 由于它是一个 Android 应用程序 我将开始使用 Google 的 OAuth2 东西 因为它在 Android 上提供了一个不错的 UI 谷歌表
  • 客户端凭据授予的访问令牌是否可以映射到用户?

    我想使用 oauth2 中的客户端凭据授予来保护 API 但是 我希望访问令牌映射到单个用户 由我在带外信任 设置阶段选择 在该阶段我共享密钥 秘密 这是一个问题吗 我知道使用客户端凭据授予的访问令牌不应该在用户的上下文中 以这种方式绑定它
  • Azure 应用服务 API 应用程序的访问安全性

    我们有一个基于 2 层的系统 即后端层和前端层 现在两者都是通过 WebAPI 进行通信的 Azure 网站 我不想将后端 WebAPI 移至 API 应用程序 问题是 是否可以以这种方式配置 API 应用程序的安全性 那就是only可从配
  • 如何从 Azure webjob 到 Azure webapp 进行通信?

    我正在运行 Azure Web 作业和 Azure Web 应用程序 该作业定期运行 并且 Web 应用程序需要作业的结果 我如何在那里得到结果 我尝试过使用 WCFnetNamedPipeBinding但由于 Azure webapps
  • Windows Azure 网站 - 获取实例标识符

    在具有多个实例的 Azure 网站上确定哪个实例正在响应 某些 ID 或其他唯一信息 的可能方法是什么 以下环境设置将包含当前请求正在其上运行的实例 ID WEBSITE INSTANCE ID 您还将在响应中收到此 id 作为 cooki
  • 当我进行部署槽交换时,为什么 azure 会重新启动网站?

    我有一个在 Azure 网站上运行的 net 4 5 网站 我已经设置了暂存部署 我预热两个站点 然后运行交换过程 从 azure 门户和 Azure powershell 无论我尝试什么 交换过程都会重新启动我的网站 两个 并且它们需要大
  • org.springframework.security.oauth2.common.exceptions.InvalidGrantException:凭据错误

    我正在开发Spring Boot 授权服务器 OAuth 资源服务器 在这个例子中 我可以通过邮递员轻松查询spring microservices oauth 服务器并获取受保护的数据 我创建了客户端来访问邮递员正在执行的数据 但我遇到了
  • ApplicationController 的未定义方法“helper_method”,Rails 5

    我正在尝试使用doorkeeper 将oAuth2 0 集成到我的仅rails api 应用程序中 但我不断收到此错误 ApplicationController 的未定义方法 helper method 但无法找到解决该问题的明确解决方案

随机推荐

  • 使用 JTable 作为 JTree 单元格编辑器

    我想使用 JTable 来编辑 JTree 我扩展了 DefaultTreeCellEditor 并实现了 isCellEditable getTreeCellEditorComponent 在 getTreeCellEditorCompo
  • 有 DGML 查看器吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我已经开始玩了DGML http en wikipedia org wiki DGML用于基于某些制造
  • 现在 x86 上有多少指令? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在尝试
  • 仅使用套接字的 Python 邮件客户端(无 smtplib)

    我正在尝试编写一个 python 程序 它将在不使用 smtplib 的情况下发送电子邮件 我尝试查看有关此问题的其他帖子 但找不到解决方案 from socket import msg r n My email s content end
  • Spring MVC 项目无法发布和运行...消息:无法自省注释

    我有一个 Spring MVC 应用程序 4 1 1 发布版本 当我尝试发布并在服务器上运行时 我收到以下错误 附加信息 使用Spring工具套件3 6 1 春季版本 4 1 1 RELEASE 这是一个maven项目 它没有任何编译错误
  • OCMock - 部分模拟 [UIAlertView alloc]

    我有一个问题OCMockiOS 框架 我本质上是想嘲笑UIAlertView s initWithTitle message delegate 方法 下面的示例不起作用 因为当我调用时 未返回存根返回值initWithTitle metho
  • 使用 Gson 2.3.1 反序列化包含在 Java 中不起作用的接口的 Json 字符串

    我正在尝试使用 Gson 将包含接口和哈希图 具有接口类型和包含接口类型的列表 的 json 字符串反序列化为 java 对象 但我越来越 java lang RuntimeException 无法调用接口 com abc Dummy 的无
  • R - 使用匹配运算符时保留顺序 (%in%)

    我正在使用匹配运算符从单独的数据框中获取矩阵中出现的值 但是 生成的矩阵的值按照它们在数据框中出现的顺序排列 而不是按原始矩阵排列 有没有办法使用匹配运算符来保留原始矩阵的顺序 这是一个简单的例子 vec c b a c vec df da
  • jQuery 克隆表行

    我有一个表 末尾有一个 添加 按钮 当您单击此按钮时 我希望在当前行下方创建一个新的表行 我还希望该行的输入字段为空 我尝试使用 clone 来执行此操作 但它会克隆页面上的所有行 请帮忙 谢谢 Script input tr clone
  • 位置侦听器从服务工作,但不是 IntentService

    我有一个应用程序 我试图定期获取用户位置并将其发送到服务器 我有一项服务附加到AlarmManager每分钟执行一次 用于测试 该服务正确找到用户位置并注销 GPS 坐标 一旦出现 GPS 锁定 我就会取消位置请求并停止服务 当我请求位置更
  • C++ 2D 曲面细分库?

    我有一些凸多边形存储为点的 STL 向量 或多或少 我想要镶嵌 http en wikipedia org wiki Tesselate它们非常快 最好分成大小相当均匀的块 并且没有 条子 我将用它来将一些物体分解成小碎片 有谁知道一个很好
  • 如何使用线程在java中暂停执行

    我以编程方式创建了一个向导 它包含 3 个面板 第二个是devicePane 第三个是detailsPane 第三个面板包含一个进度条 我希望我的程序启动一个功能process 显示第三个面板后 可以使用线程吗 else if Parser
  • HTML+CSS 中的不确定进度条

    我想创建一个不确定的HTML CSS进度条所以它看起来像 Vista 上的那个 source microsoft com http i msdn microsoft com dynimg IC121865 png 我想 水平调整进度条宽度
  • 在同一终端中同时运行多个命令

    I want to run a few commands each of which doesn t quit until Ctrl C is pressed Is there something I can run to run all
  • 客户愤怒,与未知的 DLL 依赖项作斗争

    我是一位为客户开发 C Windows 应用程序的单人秀 在过去的几个月里 我们一直遇到同样的问题 即客户计算机上缺少 DLL 依赖项 尽管我尽了最大努力 但问题仍然存在 我们收到了愤怒的电子邮件 我的老板和我老板的老板对我很生气 顾客也不
  • 如何在 Swift 中将*正数*转换为数字数组

    我想转换一个positive数字到相应的数字列表中 数字也应该是整数 转换时 例如 1024 它应该返回 1 0 2 4 在 Swift 4 1 或更高版本中 let number 1024 let digits String number
  • 部署时使 Google Cloud Function 的 Firebase 缓存失效

    我最近使用 Cloud Functions 和 Firebase Hosting 实现了 SSR 当 JS 包构建时 它会收到一个缓存突发后缀 main 1 js 在我的函数内部 我有以下代码段用于缓存云函数的结果 res set Cach
  • winapi 中子窗口编辑控件上的 WS_TABSTOP

    在我的 WinAPI 应用程序中 我的子窗口中有一系列编辑控件 我希望用户能够通过按 Tab 键前进并按 Shift Tab 键返回来在它们之间移动 但我似乎不知道如何使用WS TABSTOP与子窗口 我想要发生的是 当用户单击 Tab 键
  • 将 HTML 元素的引用传递给自定义挂钩

    假设我有一个自定义挂钩 我将使用它来将单击事件侦听器添加到 HTML 元素中 我创建参考const buttonRef useRef null 因此第一次渲染时的值为 null ref 值仅在渲染方法的final 中分配 此时我的自定义钩子
  • 最低权限的身份服务器无法在 Azure 上正常工作

    我正在尝试实现一个遵循 OAUTH2 OIDC 协议的架构 为了做到这一点 我为客户端提供了 STS Identity Server v3 ASP NET WebApi 和 ASP NET MVC 应用程序 我的目标是将 STS 和 RES