从元数据端点缓存颁发者和密钥

Caching issuer and keys from the metadata endpoint

我遵循使用 Azure AD B2C 从 ASP.NET Web 应用程序调用 ASP.NET Web API 的示例: https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi

我有一个关于 OpenIdConnectCachingSecurityTokenProvider

的问题
// This class is necessary because the OAuthBearer Middleware does not leverage
// the OpenID Connect metadata endpoint exposed by the STS by default.
public class OpenIdConnectCachingSecurityTokenProvider : IIssuerSecurityKeyProvider
{
    public ConfigurationManager<OpenIdConnectConfiguration> _configManager;
    private string _issuer;
    private IEnumerable<SecurityKey> _keys;
    private readonly string _metadataEndpoint;

    private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim();

    public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint)
    {
        _metadataEndpoint = metadataEndpoint;
        _configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint, new OpenIdConnectConfigurationRetriever());

        RetrieveMetadata();
    }

    /// <summary>
    /// Gets the issuer the credentials are for.
    /// </summary>
    /// <value>
    /// The issuer the credentials are for.
    /// </value>
    public string Issuer
    {
        get
        {
            RetrieveMetadata();
            _synclock.EnterReadLock();
            try
            {
                return _issuer;
            }
            finally
            {
                _synclock.ExitReadLock();
            }
        }
    }

    /// <summary>
    /// Gets all known security keys.
    /// </summary>
    /// <value>
    /// All known security keys.
    /// </value>
    public IEnumerable<SecurityKey> SecurityKeys
    {
        get
        {
            RetrieveMetadata();
            _synclock.EnterReadLock();
            try
            {
                return _keys;
            }
            finally
            {
                _synclock.ExitReadLock();
            }
        }
    }

    private void RetrieveMetadata()
    {
        _synclock.EnterWriteLock();
        try
        {
            OpenIdConnectConfiguration config = Task.Run(_configManager.GetConfigurationAsync).Result;
            _issuer = config.Issuer;
            _keys = config.SigningKeys;
        }
        finally
        {
            _synclock.ExitWriteLock();
        }
    }
}

元数据端点:

https://login.microsoftonline.com/{TENANT}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={POLICY}

为什么我们总是需要调用来检索密钥和发行者?

我可以缓存这些值吗? 如果是,过期的最佳设置是什么?

Why all the time we need to make a call to retrieve the keys and the issuer?

  • 签名密钥:您的应用程序必须使用此签名密钥(public 密钥)来验证 AAD 使用其私钥签名的令牌。此元数据端点包含特定时刻使用的所有 public 关键信息:

    https://login.microsoftonline.com/<yourtenantdomain>/discovery/v2.0/keys?p=<SigninPolicyName>

  • Issuer:您的应用程序需要 Issuer 来验证令牌的 iss 声明以信任此令牌。也可以从 OpenID 连接元数据端点检索颁发者:

    https://login.microsoftonline.com/<YourTenantDomain>/v2.0/.well-known/openid-configuration?p=<SigninPolicyName>

Identifies the security token service (STS) that constructs and returns the token. In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID is an immutable and reliable identifier of the directory.

此外,OAuthBearer Middleware 默认情况下不利用此元数据端点,因此您需要使用代码检索它。 因此,您必须检索密钥和颁发者以验证令牌。

Can I cache these values? If yes, what's the best setting for the expiration?

是的,使用您 post 的代码,它会将这些值缓存在 configManager.GetConfigurationAsync 中,并 OpenIdConnectCachingSecurityTokenProvider 在启动时使用它。

关于过期:签名密钥可以滚动。所以,不用担心唱歌键的设置过期时间。重要的是你最好动态获取元数据位置以保持签名密钥是正确的。

参考:

您可以在 this documentaion 中查看有关验证 B2C 令牌签名的详细信息。

this documentation 中查看有关 AAD 中签名密钥滚动更新的更多详细信息。

查看有关 OpendID 提供程序元数据的更多详细信息:http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata