【问题标题】:Difference between Azure AD and Azure AD B2C tokensAzure AD 和 Azure AD B2C 令牌之间的区别
【发布时间】:2017-11-23 16:10:09
【问题描述】:

这些天我一直在研究 Azure AD 授权代码流,突然开始将所有内容转移到 Azure AD B2C,我发现 Azure AD 和 Azure AD B2C 之间存在很多差异。有人可以在下面回答我的问题吗?

  1. 在 Azure AD 中,当我们注册本机应用程序时,它允许 http 或 https 作为重定向 url。 Azure AD B2C 不支持这一点(因为两者都遵循 OAUTH 规范,所以两者的行为应该相似)

  2. Azure AD JWT 访问令牌具有 x5c 条目,而 B2C 没有此条目。任何特殊原因。我尝试从 Azure AD 复制公钥并尝试将相同的签名密钥上传到 B2C,但这不起作用。不知道我错过了什么,但我的问题是为什么这些访问令牌的签名不同。

【问题讨论】:

  • 您无法将 Azure AD 的签名密钥上传到 B2C,因为您可以看到的是公钥。您需要私钥才能与他们进行签名。如果签名不同,则签名密钥不同。

标签: azure azure-active-directory azure-ad-b2c


【解决方案1】:

对于第一个问题,如果您需要此功能,我建议您在此处提出反馈from

对于第二个问题,验证来自 Azure AD B2C 和普通 Azure AD 的令牌是相同的。我们可以使用指数(e)和模数(n)生成公钥。 但是密钥端点不同,我们需要使用如下链接来检索 Azure AD B2C 的密钥

https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys?p={signInPolicy}

以下是验证 Azure AD B2C 颁发的令牌的代码,供您参考:

static void Main(string[] args)
{          
    var idtoken = "";

    var exponent = "AQAB";
    var modulus = "";
    var result=  VerifyTokenDetails(idtoken, exponent, modulus);
}
private static bool VerifyTokenDetails(string idToken, string exponent, string modulus)
{
    try
    {              
        var parts = idToken.Split('.');
        var header = parts[0];
        var payload = parts[1];
        string signedSignature = parts[2];
        //Extract user info from payload   
        string userInfo = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        //Which will be Verified
        string originalMessage = string.Concat(header, ".", payload);
        byte[] keyBytes = Base64UrlDecode(modulus);
        string keyBase = Convert.ToBase64String(keyBytes);
        string key = @"<RSAKeyValue> <Modulus>" + keyBase + "</Modulus> <Exponent>" + exponent + "</Exponent> </RSAKeyValue>";
        bool result = VerifyData(originalMessage, signedSignature, key);
        if (result)
            return true;
        else
            return false;
    }
    catch (Exception ex) { }
    return false;
}

/// <summary>  
/// Verifies encrypted signed message with public key encrypted original message.  
/// </summary>  
/// <param name="originalMessage">Original message as string. (Encrypted form)</param>  
/// <param name="signedMessage">Signed message as string. (Encrypted form)</param>  
/// <param name="publicKey">Public key as XML string.</param>  
/// <returns>Boolean True if successful otherwise return false.</returns>  
private static bool VerifyData(string originalMessage, string signedMessage, string publicKey)
{
    bool success = false;
    using (var rsa = new RSACryptoServiceProvider())
    {
        var encoder = new UTF8Encoding();
        byte[] bytesToVerify = encoder.GetBytes(originalMessage);
        byte[] signedBytes = Base64UrlDecode(signedMessage);
        try
        {

            rsa.FromXmlString(publicKey);
            SHA256Managed Hash = new SHA256Managed();
            byte[] hashedData = Hash.ComputeHash(signedBytes);
            // Summary:
            //     Verifies that a digital signature is valid by determining the hash value in the
            //     signature using the provided public key and comparing it to the hash value of
            //     the provided data.
            success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA256"), signedBytes);
        }
        catch (CryptographicException e)
        {
            success = false;
        }
        finally
        {
            rsa.PersistKeyInCsp = false;
        }
    }
    return success;
}

private static byte[] Base64UrlDecode(string input)
{
    var output = input;
    output = output.Replace('-', '+'); // 62nd char of encoding  
    output = output.Replace('_', '/'); // 63rd char of encoding  
    switch (output.Length % 4) // Pad with trailing '='s  
    {
        case 0: break; // No pad chars in this case  
        case 2: output += "=="; break; // Two pad chars  
        case 3: output += "="; break; // One pad char  
        default: throw new System.Exception("Illegal base64url string!");
    }
    var converted = Convert.FromBase64String(output); // Standard base64 decoder  
    return converted;
}

【讨论】:

  • 感谢您的回复。我也在使用类似的方法来生成公钥。 play.golang.org/p/7wWMBOp10R 。想知道 Azure AD 和 B2C 之间的令牌差异是否有任何原因?
  • 令牌验证问题是否已修复? AFAIK,Azure AD 颁发的令牌中没有x5c 声明(请参阅here)。
  • 我能够以某种方式使用 golang 库。我必须将其转换为 lua,因为令牌由服务器验证,在我们的例子中是运行一些 lua 库的 nginx。示例说明 Azure AD 令牌包含此标头,这意味着它将具有 x5c 条目。我经历了各种场景并注意到令牌{ "typ": "JWT", "alg": "RS256", "x5t": "kriMPdmBvx68skT8-mPAB3BseeA" } 的差异
  • @VenkateshMarepalli AFAIK,在令牌验证过程中无需使用x5c。我们只是使用x5t 声明来识别来自密钥端点的公钥。然后我们可以使用en 的值创建密钥来生成公钥来验证令牌。有关从 Azure AD B2C 验证令牌的更多详细信息,请参阅link
  • 我想这会让我的问题更清楚。我应该问你关于 jwks 端点的问题。为什么 B2C 和 AD 的公钥不同。 Azure AD 密钥有 x5c 条目 B2C 没有。
猜你喜欢
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 2016-04-08
  • 2023-03-06
  • 1970-01-01
  • 2017-01-09
  • 2020-05-10
  • 1970-01-01
相关资源
最近更新 更多