SAML responses come with a signature and a public key for that signature.
You can use the public key to verify that the content of the SAML response matches the key - in other words - that response definitely came from someone who has the matching private key to the public key in the message, and the response hasn't been tampered with.
I don't know what tech you're working with, but in .Net you can check it like this:
// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");
// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");
// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);
// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);
// get the certificate, basically:
// signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);
// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);
That just checks that the message is from who it says it is. You need an additional check that the message has come from someone that you trust, and this check is slower - it needs to include revocation and may need to verify a whole chain of certificates.
Normally this will be a list of public keys that you would accept SAML responses from.
Then you can check that this message hasn't been tampered with, and is from someone that you trust, so you can authorise the user details supplied in the SAML attributes supplied.
You could already have the public key, meaning that the signature shouldn't need to include the public key again, but you could also have multiple possible known senders, or even a chain of known senders.
For instance you may have two trusted providers - in either case you check that the message has not been tampered with before checking whether you trust either provider. If the key isn't in the signature the assertions can be a little smaller, but now you have to know in advance which identity provider the assertion has come from.
So, really, there are two main reasons that the public key is in the signature:
- The tamper check is quicker than the identity check, and can be isolated if the public key is known.
- Multiple identities are much easier to support if the key is in the assertion.
In Java 8 and above, you can use the String
's method chars()
:
myString.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
And if you need to convert char[]
to List<Character>
, you might create a String
from it first and then apply the above solution. Though it won't be very readable and pretty, it will be quite short.
Best Answer
From the SAML 2.0 core spec, the NameIDPolicy
Specifies constraints on the name identifier to be used to represent the requested subject. If omitted, then any type of identifier supported by the identity provider for the requested subject can be used, constrained by any relevant deployment-specific policies, with respect to privacy, for example.
When performing identity federation, the affiliated parties must agree upon an identifier for the principal's linked accounts. The identifier string is called a NameID and its specification, including format, is the NameIDPolicy.
For example, a Service Provider (SP) initiates federation by sending an AuthnRequest to the Identity Provider (IDP) containing
This tells the IDP that its response Assertion XML should contain something like
where the email address represents the subject being authenticated.
You can learn more by reading SAML 2.0 Wikipedia page (well-written), the SAML 2.0 core spec and the SAML 2.0 Name Identifier document.