public void Saml2SubjectExtensions_ToXElement() { var subjectName = "JohnDoe"; var saml2Subject = new Saml2Subject(new Saml2NameIdentifier(subjectName)); var subject = saml2Subject.ToXElement(); subject.Element(Saml2Namespaces.Saml2 + "NameID").Value.Should().Be(subjectName); // Although SubjectConfirmation is optional in the SAML core spec, it is // mandatory in the Web Browser SSO Profile and must have a value of bearer. subject.Element(Saml2Namespaces.Saml2 + "SubjectConfirmation") .Attribute("Method").Value.Should().Be("urn:oasis:names:tc:SAML:2.0:cm:bearer"); }
public void ProcessSamlSubjectPublic(Saml2Subject assertionSubject, ClaimsIdentity subject, string issuer) { base.ProcessSamlSubject(assertionSubject, subject, issuer); }
/// <summary> /// Writes the <saml:Subject> element. /// </summary> /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2Subject"/>.</param> /// <param name="data">The <see cref="Saml2Subject"/> to serialize.</param> protected virtual void WriteSubject(XmlWriter writer, Saml2Subject data) { if (null == writer) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); } if (null == data) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data"); } // If there's no ID, there has to be a SubjectConfirmation #pragma warning suppress 56506 // SubjectConfirmations is never null if (null == data.NameId && 0 == data.SubjectConfirmations.Count) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4108))); } // <Subject> writer.WriteStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace); // no attributes // <NameID> 0-1 if (null != data.NameId) { this.WriteNameId(writer, data.NameId); } // <SubjectConfirmation> 0-OO foreach (Saml2SubjectConfirmation subjectConfirmation in data.SubjectConfirmations) { this.WriteSubjectConfirmation(writer, subjectConfirmation); } // </Subject> writer.WriteEndElement(); }
/// <summary> /// Reads the <saml:Subject> element. /// </summary> /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2Subject"/> element.</param> /// <returns>An instance of <see cref="Saml2Subject"/> .</returns> /// <remarks> /// The default implementation does not handle the optional /// <EncryptedID> element. To handle encryped IDs in the Subject, /// override this method. /// </remarks> protected virtual Saml2Subject ReadSubject(XmlReader reader) { if (null == reader) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } // throw if wrong element if (!reader.IsStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace)) { reader.ReadStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace); } try { // disallow empty if (reader.IsEmptyElement) { #pragma warning suppress 56504 // bogus - thinks reader.LocalName, reader.NamespaceURI need validation throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, reader.LocalName, reader.NamespaceURI)); } // @attributes // @xsi:type XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.SubjectType, Saml2Constants.Namespace); // <elements> Saml2Subject subject = new Saml2Subject(); reader.Read(); // <NameID> | <EncryptedID> | <BaseID> 0-1 subject.NameId = this.ReadSubjectId(reader, Saml2Constants.Elements.Subject); // <SubjectConfirmation> 0-OO while (reader.IsStartElement(Saml2Constants.Elements.SubjectConfirmation, Saml2Constants.Namespace)) { subject.SubjectConfirmations.Add(this.ReadSubjectConfirmation(reader)); } reader.ReadEndElement(); // Must have a NameID or a SubjectConfirmation if (null == subject.NameId && 0 == subject.SubjectConfirmations.Count) { throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4108)); } return subject; } catch (Exception e) { if (System.Runtime.Fx.IsFatal(e)) throw; Exception wrapped = TryWrapReadException(reader, e); if (null == wrapped) { throw; } else { throw wrapped; } } }
/// <summary> /// Creates claims from the Saml2Subject. /// </summary> /// <param name="assertionSubject">The Saml2Subject.</param> /// <param name="subject">The ClaimsIdentity subject.</param> /// <param name="issuer">The issuer.</param> protected virtual void ProcessSamlSubject(Saml2Subject assertionSubject, ClaimsIdentity subject, string issuer) { if (assertionSubject == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertionSubject"); } if (subject == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("subject"); } Saml2NameIdentifier nameId = assertionSubject.NameId; if (nameId != null) { Claim claim = new Claim(ClaimTypes.NameIdentifier, nameId.Value, ClaimValueTypes.String, issuer); if (nameId.Format != null) { claim.Properties[ClaimProperties.SamlNameIdentifierFormat] = nameId.Format.AbsoluteUri; } if (nameId.NameQualifier != null) { claim.Properties[ClaimProperties.SamlNameIdentifierNameQualifier] = nameId.NameQualifier; } if (nameId.SPNameQualifier != null) { claim.Properties[ClaimProperties.SamlNameIdentifierSPNameQualifier] = nameId.SPNameQualifier; } if (nameId.SPProvidedId != null) { claim.Properties[ClaimProperties.SamlNameIdentifierSPProvidedId] = nameId.SPProvidedId; } subject.AddClaim(claim); } }
/// <summary> /// Creates a SAML2 subject of the assertion. /// </summary> /// <param name="tokenDescriptor">The security token descriptor to create the subject.</param> /// <exception cref="ArgumentNullException">Thrown when 'tokenDescriptor' is null.</exception> /// <returns>A Saml2Subject.</returns> protected virtual Saml2Subject CreateSamlSubject(SecurityTokenDescriptor tokenDescriptor) { if (null == tokenDescriptor) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenDescriptor"); } Saml2Subject saml2Subject = new Saml2Subject(); // Look for name identifier claims string nameIdentifierClaim = null; string nameIdentifierFormat = null; string nameIdentifierNameQualifier = null; string nameIdentifierSpProviderId = null; string nameIdentifierSpNameQualifier = null; if (tokenDescriptor.Subject != null && tokenDescriptor.Subject.Claims != null) { foreach (Claim claim in tokenDescriptor.Subject.Claims) { if (claim.Type == ClaimTypes.NameIdentifier) { // Do not allow multiple name identifier claim. if (null != nameIdentifierClaim) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4139))); } nameIdentifierClaim = claim.Value; if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierFormat)) { nameIdentifierFormat = claim.Properties[ClaimProperties.SamlNameIdentifierFormat]; } if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierNameQualifier)) { nameIdentifierNameQualifier = claim.Properties[ClaimProperties.SamlNameIdentifierNameQualifier]; } if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierSPNameQualifier)) { nameIdentifierSpNameQualifier = claim.Properties[ClaimProperties.SamlNameIdentifierSPNameQualifier]; } if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierSPProvidedId)) { nameIdentifierSpProviderId = claim.Properties[ClaimProperties.SamlNameIdentifierSPProvidedId]; } } } } if (nameIdentifierClaim != null) { Saml2NameIdentifier nameIdentifier = new Saml2NameIdentifier(nameIdentifierClaim); if (nameIdentifierFormat != null && UriUtil.CanCreateValidUri(nameIdentifierFormat, UriKind.Absolute)) { nameIdentifier.Format = new Uri(nameIdentifierFormat); } nameIdentifier.NameQualifier = nameIdentifierNameQualifier; nameIdentifier.SPNameQualifier = nameIdentifierSpNameQualifier; nameIdentifier.SPProvidedId = nameIdentifierSpProviderId; saml2Subject.NameId = nameIdentifier; } // Add subject confirmation data Saml2SubjectConfirmation subjectConfirmation; if (null == tokenDescriptor.Proof) { subjectConfirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.Bearer); } else { subjectConfirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.HolderOfKey, new Saml2SubjectConfirmationData()); subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Add(tokenDescriptor.Proof.KeyIdentifier); } saml2Subject.SubjectConfirmations.Add(subjectConfirmation); return saml2Subject; }
protected override Saml2Subject CreateSamlSubject(SecurityTokenDescriptor tokenDescriptor) { Saml2SubjectConfirmation confirmation; if (tokenDescriptor == null) { throw new ArgumentNullException("tokenDescriptor"); } Saml2Subject subject = new Saml2Subject(); string name = null; string uriString = null; if ((tokenDescriptor.Subject != null) && (tokenDescriptor.Subject.Claims != null)) { foreach (Claim claim in tokenDescriptor.Subject.Claims) { if (claim.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier") { if (name != null) { throw new InvalidOperationException( "No suitable Saml2NameIdentifier could be created for the SAML2:Subject because more than one Claim of type NameIdentifier was supplied."); } name = claim.Value; if (claim.Properties.ContainsKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format")) { uriString = claim.Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"]; } } } } if (name != null) { Saml2NameIdentifier identifier = new Saml2NameIdentifier(name); if ((uriString != null) && UriUtil.CanCreateValidUri(uriString, UriKind.Absolute)) { identifier.Format = new Uri(uriString); } subject.NameId = identifier; } // IGNORE SAML confirmation and just create the SenderVouches // GFIPM S2S 8.8.2.6.c confirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.SenderVouches); // SAML V2.0 Condition for Delegation Restriction Version 1.0 // 2.5 Use of Identifiers Within <saml:SubjectConfirmation> string lastDelegateNameId = tokenDescriptor.Subject.Actor.Name; confirmation.NameIdentifier = new Saml2NameIdentifier(lastDelegateNameId); subject.SubjectConfirmations.Add(confirmation); return subject; }