私は署名付きアサーションを持つSAMLResponseを生成するIDPを持っています。私は生成されたXMLファイルの例を追加するつもりはありません。なぜなら、それは質問をあまりにも長くするからです。しかし、それが本当に役立つなら、私に知らせてください、私はそれを追加します。SAMLResponseに署名し、C#でアサーションを暗号化する方法は?
SPは、アサーションを暗号化して応答することを要求しています(現時点ではそうではありません)。研究の後、私はそれを行う方法を見つけることができませんでした、私は試したコードを投稿するだろうが、私は正直であるためにちょっと無責任です、そして私が試したものはどこにもありません。
質問:私はどのように応答に署名し、アサーションを暗号化するのですか?ここで
は、応答が作成され、署名されている方法は次のとおりです。
public class SAML
{
private const int tokenLifetime = 30;
private const string issuer = "https://some.domain/IdP";
private const string CertificateSerialNumber = "XXXXXXXXXXXXX";
private static string _RequestId;
private static string _RequestIssueInstant;
private static string _RequestProviderName;
private static string _RequestACS;
private static Dictionary<string, string> _claimDescriptors = new Dictionary<string, string>();
public static string CreateSamlResponse(string RequestId, string RequestIssueInstant, string RequestProviderName, string RequestACS, Dictionary<string,string> claimDescriptors)
{
_RequestId = RequestId;
_RequestIssueInstant = RequestIssueInstant;
_RequestProviderName = RequestProviderName;
_RequestACS = RequestACS;
_claimDescriptors = claimDescriptors;
var claims = CreateClaims();
var tokenHandler = new Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler();
var token = CreateToken(claims, tokenHandler);
return CreateSamlResponseXml(tokenHandler, token);
}
private static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken CreateToken(IEnumerable<Microsoft.IdentityModel.Claims.Claim> claims,
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler tokenHandler)
{
var descriptor = CreateTokenDescriptor(claims);
var token = tokenHandler.CreateToken(descriptor) as Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken;
AddAuthenticationStatement(token);
AddConfirmationData(token);
return token;
}
private static void AddConfirmationData(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var confirmationData = new Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmationData
{
Recipient = new Uri(_RequestACS),
NotOnOrAfter = DateTime.UtcNow.AddSeconds(tokenLifetime),
InResponseTo = new Microsoft.IdentityModel.Tokens.Saml2.Saml2Id(_RequestId),
};
token.Assertion.Subject.SubjectConfirmations.Add(new Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmation(
Microsoft.IdentityModel.Tokens.Saml2.Saml2Constants.ConfirmationMethods.Bearer, confirmationData));
}
private static void AddAuthenticationStatement(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var authenticationMethod = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password";
var authenticationContext = new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationContext(new Uri(authenticationMethod));
var authenticationStatement = new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationStatement(authenticationContext);
token.Assertion.Statements.Add(authenticationStatement);
}
private static string CreateSamlResponseXml(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler tokenHandler, Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var buffer = new StringBuilder();
using (var stringWriter = new StringWriter(buffer))
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings()))
{
xmlWriter.WriteStartElement("Response", "urn:oasis:names:tc:SAML:2.0:protocol");
xmlWriter.WriteAttributeString("IssueInstant", DateTime.UtcNow.ToString("o"));
xmlWriter.WriteAttributeString("ID", "_" + Guid.NewGuid());
xmlWriter.WriteAttributeString("Version", "2.0");
xmlWriter.WriteStartElement("Status");
xmlWriter.WriteStartElement("StatusCode");
xmlWriter.WriteAttributeString("Value", "urn:oasis:names:tc:SAML:2.0:status:Success");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
tokenHandler.WriteToken(xmlWriter, token);
xmlWriter.WriteEndElement();
}
return buffer.ToString();
}
private static Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor CreateTokenDescriptor(IEnumerable<Microsoft.IdentityModel.Claims.Claim> claims)
{
var descriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
{
TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.OasisWssSaml2TokenProfile11,
Lifetime = new Microsoft.IdentityModel.Protocols.WSTrust.Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddMinutes(1)),
//AppliesToAddress = appliesTo,
AppliesToAddress = _RequestACS,
TokenIssuerName = issuer,
Subject = new Microsoft.IdentityModel.Claims.ClaimsIdentity(claims),
SigningCredentials = GetSigningCredentials()
};
return descriptor;
}
private static System.IdentityModel.Tokens.SigningCredentials GetSigningCredentials()
{
System.Security.Cryptography.X509Certificates.X509Certificate2 myCertificate = null;
X509Certificate2Collection selectedCerts = new X509Certificate2Collection();
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 cert in store.Certificates)
{
if (cert.SerialNumber.Trim().ToLower().Equals(CertificateSerialNumber.ToLower())){ myCertificate = cert; }
}
return new Microsoft.IdentityModel.SecurityTokenService.X509SigningCredentials(myCertificate, System.IdentityModel.Tokens.SecurityAlgorithms.RsaSha1Signature, System.IdentityModel.Tokens.SecurityAlgorithms.Sha1Digest);
}
private static IEnumerable<Microsoft.IdentityModel.Claims.Claim> CreateClaims()
{
foreach (var claimDescriptor in _claimDescriptors)
{
yield return new Microsoft.IdentityModel.Claims.Claim(claimDescriptor.Key, claimDescriptor.Value);
}
}
}
トゥアンです!これは本当に役に立ちました!私は1つの問題を抱えています。あなたが言及したようにEncryptingCredentialsプロパティを使用していますが、アサーションが暗号化されていますが、X509Certificate要素がX509Dataセクションに追加されていないため、理由がわかりません。助言がありますか? – Naner
SecurityKeyIdentifierプロパティを確認することができます:https://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.x509encryptingcredentials(v=vs.110).aspx IIRC、それはkeyinfoの追加を担当します。 – Thuan