private static XElement ToXElement(Saml2AuthenticationStatement authnStatement) { var result = new XElement(Saml2Namespaces.Saml2 + "AuthnStatement", new XAttribute("AuthnInstant", authnStatement.AuthenticationInstant.ToSaml2DateTimeString()), new XElement(Saml2Namespaces.Saml2 + "AuthnContext", new XElement(Saml2Namespaces.Saml2 + "AuthnContextClassRef", authnStatement.AuthenticationContext.ClassReference.OriginalString))); if(authnStatement.SessionIndex != null) { result.Add(new XAttribute("SessionIndex", authnStatement.SessionIndex)); } return result; }
/// <summary> /// Writes the <saml:AuthnStatement> element. /// </summary> /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2AuthenticationStatement"/>.</param> /// <param name="data">The <see cref="Saml2AuthenticationStatement"/> to serialize.</param> protected virtual void WriteAuthenticationStatement(XmlWriter writer, Saml2AuthenticationStatement data) { if (null == writer) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); } if (null == data) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data"); } // <AuthnStatement> writer.WriteStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace); // @AuthnInstant - required writer.WriteAttributeString(Saml2Constants.Attributes.AuthnInstant, XmlConvert.ToString(data.AuthenticationInstant.ToUniversalTime(), DateTimeFormats.Generated)); // @SessionIndex - optional if (null != data.SessionIndex) { writer.WriteAttributeString(Saml2Constants.Attributes.SessionIndex, data.SessionIndex); } // @SessionNotOnOrAfter - optional if (null != data.SessionNotOnOrAfter) { writer.WriteAttributeString(Saml2Constants.Attributes.SessionNotOnOrAfter, XmlConvert.ToString(data.SessionNotOnOrAfter.Value.ToUniversalTime(), DateTimeFormats.Generated)); } // <SubjectLocality> 0-1 if (null != data.SubjectLocality) { this.WriteSubjectLocality(writer, data.SubjectLocality); } // <AuthnContext> 1 this.WriteAuthenticationContext(writer, data.AuthenticationContext); // </AuthnStatement> writer.WriteEndElement(); }
/// <summary> /// Reads the <saml:AuthnStatement> element or a <saml:Statement> /// element that specifies an xsi:type of saml:AuthnStatementType. /// </summary> /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2AuthenticationStatement"/> element.</param> /// <returns>A <see cref="Saml2AuthenticationStatement"/> instance.</returns> protected virtual Saml2AuthenticationStatement ReadAuthenticationStatement(XmlReader reader) { if (null == reader) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } // throw if wrong element bool isStatementElement = false; if (reader.IsStartElement(Saml2Constants.Elements.Statement, Saml2Constants.Namespace)) { isStatementElement = true; } else if (!reader.IsStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace)) { reader.ReadStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace); } try { // Must cache the individual data since the required // AuthnContext comes last DateTime authnInstant; Saml2AuthenticationContext authnContext; string sessionIndex; DateTime? sessionNotOnOrAfter = null; Saml2SubjectLocality subjectLocality = null; // defer disallowing empty until after xsi:type bool isEmpty = reader.IsEmptyElement; // @attributes string value; // @xsi:type -- if we're a <Statement> element, this declaration must be present XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.AuthnStatementType, Saml2Constants.Namespace, isStatementElement); // disallow empty, since xsi:type is ok if (isEmpty) { throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace)); } // @AuthnInstant - required value = reader.GetAttribute(Saml2Constants.Attributes.AuthnInstant); if (string.IsNullOrEmpty(value)) { throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.AuthnInstant, Saml2Constants.Elements.AuthnStatement)); } authnInstant = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted); // @SessionIndex - optional sessionIndex = reader.GetAttribute(Saml2Constants.Attributes.SessionIndex); // @SessionNotOnOrAfter - optional value = reader.GetAttribute(Saml2Constants.Attributes.SessionNotOnOrAfter); if (!string.IsNullOrEmpty(value)) { sessionNotOnOrAfter = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted); } // Content reader.Read(); // <SubjectLocality> 0-1 if (reader.IsStartElement(Saml2Constants.Elements.SubjectLocality, Saml2Constants.Namespace)) { subjectLocality = this.ReadSubjectLocality(reader); } // <AuthnContext> 1 authnContext = this.ReadAuthenticationContext(reader); reader.ReadEndElement(); // Construct the actual object Saml2AuthenticationStatement authnStatement = new Saml2AuthenticationStatement(authnContext, authnInstant); authnStatement.SessionIndex = sessionIndex; authnStatement.SessionNotOnOrAfter = sessionNotOnOrAfter; authnStatement.SubjectLocality = subjectLocality; return authnStatement; } 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 a Saml2AuthenticationStatement. /// </summary> /// <param name="statement">The Saml2AuthenticationStatement.</param> /// <param name="subject">The subject.</param> /// <param name="issuer">The issuer.</param> protected virtual void ProcessAuthenticationStatement(Saml2AuthenticationStatement statement, ClaimsIdentity subject, string issuer) { if (subject == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("subject"); } if (statement.AuthenticationContext.DeclarationReference != null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4180)); } if (statement.AuthenticationContext.ClassReference != null) { subject.AddClaim( new Claim( ClaimTypes.AuthenticationMethod, this.NormalizeAuthenticationContextClassReference(statement.AuthenticationContext.ClassReference.AbsoluteUri), ClaimValueTypes.String, issuer)); } subject.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(statement.AuthenticationInstant.ToUniversalTime(), DateTimeFormats.Generated), ClaimValueTypes.DateTime, issuer)); }
/// <summary> /// Given an AuthenticationInformation object, this routine creates a Saml2AuthenticationStatement /// to be added to the Saml2Assertion that is produced by the factory. /// </summary> /// <param name="authInfo"> /// An AuthenticationInformation object containing the state to be wrapped as a Saml2AuthenticationStatement /// object. /// </param> /// <param name="tokenDescriptor">The token descriptor.</param> /// <returns> /// The Saml2AuthenticationStatement to add to the assertion being created or null to ignore the AuthenticationInformation /// being wrapped as a statement. /// </returns> protected virtual Saml2AuthenticationStatement CreateAuthenticationStatement(AuthenticationInformation authInfo, SecurityTokenDescriptor tokenDescriptor) { if (tokenDescriptor == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenDescriptor"); } if (tokenDescriptor.Subject == null) { return null; } string authenticationMethod = null; string authenticationInstant = null; // Search for an Authentication Claim. IEnumerable<Claim> claimCollection = from c in tokenDescriptor.Subject.Claims where c.Type == ClaimTypes.AuthenticationMethod select c; if (claimCollection.Count<Claim>() > 0) { // We support only one authentication statement and hence we just pick the first authentication type // claim found in the claim collection. Since the spec allows multiple Auth Statements, // we do not throw an error. authenticationMethod = claimCollection.First<Claim>().Value; } claimCollection = from c in tokenDescriptor.Subject.Claims where c.Type == ClaimTypes.AuthenticationInstant select c; if (claimCollection.Count<Claim>() > 0) { authenticationInstant = claimCollection.First<Claim>().Value; } if (authenticationMethod == null && authenticationInstant == null) { return null; } else if (authenticationMethod == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4270, "AuthenticationMethod", "SAML2")); } else if (authenticationInstant == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4270, "AuthenticationInstant", "SAML2")); } Uri saml2AuthenticationClass; if (!UriUtil.TryCreateValidUri(this.DenormalizeAuthenticationType(authenticationMethod), UriKind.Absolute, out saml2AuthenticationClass)) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4185, authenticationMethod)); } Saml2AuthenticationContext authCtx = new Saml2AuthenticationContext(saml2AuthenticationClass); DateTime authInstantTime = DateTime.ParseExact(authenticationInstant, DateTimeFormats.Accepted, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).ToUniversalTime(); Saml2AuthenticationStatement authnStatement = new Saml2AuthenticationStatement(authCtx, authInstantTime); if (authInfo != null) { if (!string.IsNullOrEmpty(authInfo.DnsName) || !string.IsNullOrEmpty(authInfo.Address)) { authnStatement.SubjectLocality = new Saml2SubjectLocality(authInfo.Address, authInfo.DnsName); } if (!string.IsNullOrEmpty(authInfo.Session)) { authnStatement.SessionIndex = authInfo.Session; } authnStatement.SessionNotOnOrAfter = authInfo.NotOnOrAfter; } return authnStatement; }
protected override void ProcessAuthenticationStatement(Saml2AuthenticationStatement statement, ClaimsIdentity subject, string issuer) { if (statement.AuthenticationContext != null) { statement.AuthenticationContext.DeclarationReference = null; } base.ProcessAuthenticationStatement(statement, subject, issuer); }
protected override void ProcessAuthenticationStatement(Saml2AuthenticationStatement statement, ClaimsIdentity subject, string issuer) { if (statement.AuthenticationContext != null) { statement.AuthenticationContext.DeclarationReference = null; } base.ProcessAuthenticationStatement(statement, subject, issuer); if(statement.SessionIndex != null) { var nameIdClaim = subject.FindFirst(ClaimTypes.NameIdentifier); subject.AddClaim( new Claim( AuthServicesClaimTypes.LogoutNameIdentifier, DelimitedString.Join( nameIdClaim.Properties.GetValueOrEmpty(ClaimProperties.SamlNameIdentifierNameQualifier), nameIdClaim.Properties.GetValueOrEmpty(ClaimProperties.SamlNameIdentifierSPNameQualifier), nameIdClaim.Properties.GetValueOrEmpty(ClaimProperties.SamlNameIdentifierFormat), nameIdClaim.Properties.GetValueOrEmpty(ClaimProperties.SamlNameIdentifierSPProvidedId), nameIdClaim.Value), null, issuer)); subject.AddClaim( new Claim(AuthServicesClaimTypes.SessionIndex, statement.SessionIndex, null, issuer)); } }
protected override void ProcessAuthenticationStatement(Saml2AuthenticationStatement statement, ClaimsIdentity subject, string issuer) { if (statement.AuthenticationContext != null) { statement.AuthenticationContext.DeclarationReference = null; } base.ProcessAuthenticationStatement(statement, subject, issuer); if(statement.SessionIndex != null) { subject.AddClaim( new Claim(AuthServicesClaimTypes.SessionIndex, statement.SessionIndex, null, issuer)); } }
private void AddAuthenticationStatement() { var authenticationStatement = new Saml2AuthenticationStatement(new Saml2AuthenticationContext(AuthnContextClassTypes.UserNameAndPassword)); Saml2SecurityToken.Assertion.Statements.Add(authenticationStatement); }