Azure AD 和 Azure AD B2C 令牌之间的区别
Difference between Azure AD and Azure AD B2C tokens
这些天我一直在研究 Azure AD 授权代码流,突然开始将所有内容都转移到 Azure AD B2C,我发现 Azure AD 和 Azure AD B2C 之间存在很多差异。有人可以在下面回答我的问题吗?
在 Azure AD 中,当我们注册一个本地应用程序时,它允许 http 或 https 作为重定向 url。 Azure AD B2C 不支持这一点(因为两者都遵循 OAUTH 规范,两者的行为应该相似)
Azure AD JWT 访问令牌具有 x5c
条目,而 B2C 没有此条目。任何特殊原因。我尝试从 Azure AD 复制 public 密钥并尝试将相同的签名密钥上传到 B2C,但这没有用。不确定我遗漏了什么,但我的问题是为什么这些访问令牌的签名不同。
对于第一个问题,如果您需要此功能,我建议您在这里反馈from。
而对于第二个问题,验证来自Azure AD B2C 和普通Azure AD 的令牌是一样的。我们可以使用指数 (e
) 和模数 (n
) 生成 public 密钥。 但密钥端点不同,我们需要使用如下所示的 link 来检索 Azure AD B2C 的密钥:
https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys?p={signInPolicy}
这里是验证Azure AD B2C颁发的token的代码,供大家参考:
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;
}
这些天我一直在研究 Azure AD 授权代码流,突然开始将所有内容都转移到 Azure AD B2C,我发现 Azure AD 和 Azure AD B2C 之间存在很多差异。有人可以在下面回答我的问题吗?
在 Azure AD 中,当我们注册一个本地应用程序时,它允许 http 或 https 作为重定向 url。 Azure AD B2C 不支持这一点(因为两者都遵循 OAUTH 规范,两者的行为应该相似)
Azure AD JWT 访问令牌具有
x5c
条目,而 B2C 没有此条目。任何特殊原因。我尝试从 Azure AD 复制 public 密钥并尝试将相同的签名密钥上传到 B2C,但这没有用。不确定我遗漏了什么,但我的问题是为什么这些访问令牌的签名不同。
对于第一个问题,如果您需要此功能,我建议您在这里反馈from。
而对于第二个问题,验证来自Azure AD B2C 和普通Azure AD 的令牌是一样的。我们可以使用指数 (e
) 和模数 (n
) 生成 public 密钥。 但密钥端点不同,我们需要使用如下所示的 link 来检索 Azure AD B2C 的密钥:
https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys?p={signInPolicy}
这里是验证Azure AD B2C颁发的token的代码,供大家参考:
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;
}