diff --git a/src/ITfoxtec.Identity.Saml2.Mvc/ITfoxtec.Identity.Saml2.Mvc.csproj b/src/ITfoxtec.Identity.Saml2.Mvc/ITfoxtec.Identity.Saml2.Mvc.csproj index 37e7194..a520be5 100644 --- a/src/ITfoxtec.Identity.Saml2.Mvc/ITfoxtec.Identity.Saml2.Mvc.csproj +++ b/src/ITfoxtec.Identity.Saml2.Mvc/ITfoxtec.Identity.Saml2.Mvc.csproj @@ -26,10 +26,10 @@ Support the Danish NemLog-in 2 / OIOSAML 2 and NemLog-in 3 / OIOSAML 3.SAML SAML 2.0 SAML2.0 SAML2 SAML 2 SAML-P SAMLP SSO Identity Provider (IdP) and Relying Party (RP) Authentication Metadata OIOSAML OIOSAML 2 OIOSAML 3 NemLogin NemLog-in 2 NemLog-in 3 ASP.NET MVC en-US https://itfoxtec.com/favicon.ico - 4.10.7.0 - 4.10.7.0 + 4.10.8.0 + 4.10.8.0 Copyright © 2023 - 4.10.7.0 + 4.10.8.0 true ITfoxtec.SAML2.snk false diff --git a/src/ITfoxtec.Identity.Saml2.MvcCore/ITfoxtec.Identity.Saml2.MvcCore.csproj b/src/ITfoxtec.Identity.Saml2.MvcCore/ITfoxtec.Identity.Saml2.MvcCore.csproj index 3cc7f17..a85490b 100644 --- a/src/ITfoxtec.Identity.Saml2.MvcCore/ITfoxtec.Identity.Saml2.MvcCore.csproj +++ b/src/ITfoxtec.Identity.Saml2.MvcCore/ITfoxtec.Identity.Saml2.MvcCore.csproj @@ -31,10 +31,10 @@ Support the Danish NemLog-in 2 / OIOSAML 2 and NemLog-in 3 / OIOSAML 3.SAML SAML 2.0 SAML2.0 SAML2 SAML 2 SAML-P SAMLP SSO Identity Provider (IdP) Relying Party (RP) Authentication Metadata OIOSAML OIOSAML 2 OIOSAML 3 NemLogin NemLog-in 2 NemLog-in 3 ASP.NET MVC Core en-US https://itfoxtec.com/favicon.ico - 4.10.7.0 - 4.10.7.0 + 4.10.8.0 + 4.10.8.0 Copyright © 2023 - 4.10.7.0 + 4.10.8.0 true ITfoxtec.SAML2.snk false diff --git a/src/ITfoxtec.Identity.Saml2/ITfoxtec.Identity.Saml2.csproj b/src/ITfoxtec.Identity.Saml2/ITfoxtec.Identity.Saml2.csproj index 3be4b0f..724574b 100644 --- a/src/ITfoxtec.Identity.Saml2/ITfoxtec.Identity.Saml2.csproj +++ b/src/ITfoxtec.Identity.Saml2/ITfoxtec.Identity.Saml2.csproj @@ -32,10 +32,10 @@ Support the Danish NemLog-in 2 / OIOSAML 2 and NemLog-in 3 / OIOSAML 3.SAML SAML 2.0 SAML2.0 SAML2 SAML 2 SAML-P SAMLP SSO Identity Provider (IdP) Relying Party (RP) Authentication Metadata OIOSAML OIOSAML 2 OIOSAML 3 NemLogin NemLog-in 2 NemLog-in 3 en-US https://itfoxtec.com/favicon.ico - 4.10.7.0 - 4.10.7.0 + 4.10.8.0 + 4.10.8.0 Copyright © 2023 - 4.10.7.0 + 4.10.8.0 true ITfoxtec.SAML2.snk false diff --git a/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/EntityDescriptor.cs b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/EntityDescriptor.cs index 5f3cacc..118134a 100644 --- a/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/EntityDescriptor.cs +++ b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/EntityDescriptor.cs @@ -79,6 +79,12 @@ public string IdAsString /// public IdPSsoDescriptor IdPSsoDescriptor { get; set; } + /// + /// [Optional] + /// Optional element specifying the organization associated with the entity described by the metadata. + /// + public Organization Organization { get; set; } + /// /// [Optional] /// Optional element identifying various kinds of contact personnel. @@ -146,6 +152,11 @@ protected IEnumerable GetXContent() yield return IdPSsoDescriptor.ToXElement(); } + if (Organization != null) + { + yield return Organization.ToXElement(); + } + if (ContactPersons != null) { foreach (var contactPerson in ContactPersons) diff --git a/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Organization.cs b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Organization.cs new file mode 100644 index 0000000..c9e1dbc --- /dev/null +++ b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Organization.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.Xml.Linq; + +namespace ITfoxtec.Identity.Saml2.Schemas.Metadata +{ + /// + /// The Organization element specifies basic contact information about the company or organization that is publishing the metadata document. + /// The use of this element is always optional. Its content is informative in + /// nature and does not directly map to any core SAML elements or attributes. + /// + public class Organization + { + const string elementName = Saml2MetadataConstants.Message.Organization; + + public Organization(string name, string displayName, string url) + { + OrganizationName = name; + OrganizationDisplayName = displayName; + OrganizationURL = url; + } + + /// + /// [Required] + /// Specifies the name of the organization responsible for the SAML entity or role. + /// + public string OrganizationName { get; protected set; } + + /// + /// [Required] + /// OrganizationDisplayName is an optional string element that specifies the display name of the organization. + /// + public string OrganizationDisplayName { get; protected set; } + + /// + /// [Required] + /// OrganizationURL is an optional anyURI element that specifies the URL of the organization. + /// + public string OrganizationURL { get; protected set; } + + public XElement ToXElement() + { + var envelope = new XElement(Saml2MetadataConstants.MetadataNamespaceX + elementName); + + envelope.Add(GetXContent()); + + return envelope; + } + + protected IEnumerable GetXContent() + { + if (OrganizationName != null) + { + yield return new XElement(Saml2MetadataConstants.MetadataNamespaceX + Saml2MetadataConstants.Message.OrganizationName, OrganizationName); + } + + if (OrganizationDisplayName != null) + { + yield return new XElement(Saml2MetadataConstants.MetadataNamespaceX + Saml2MetadataConstants.Message.OrganizationDisplayName, OrganizationDisplayName); + } + + if (OrganizationURL != null) + { + yield return new XElement(Saml2MetadataConstants.MetadataNamespaceX + Saml2MetadataConstants.Message.OrganizationURL, OrganizationURL); + } + } + } +} \ No newline at end of file diff --git a/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Saml2MetadataConstants.cs b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Saml2MetadataConstants.cs index 7ef27d4..1a15fdd 100644 --- a/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Saml2MetadataConstants.cs +++ b/src/ITfoxtec.Identity.Saml2/Schemas/Metadata/Saml2MetadataConstants.cs @@ -49,7 +49,9 @@ public class Message public const string SPSsoDescriptor = "SPSSODescriptor"; - public const string IdPSsoDescriptor = "IDPSSODescriptor"; + public const string IdPSsoDescriptor = "IDPSSODescriptor"; + + public const string Organization = "Organization"; public const string ContactPerson = "ContactPerson"; @@ -129,7 +131,13 @@ public class Message public const string Type = "type"; - public const string FriendlyName = "FriendlyName"; + public const string FriendlyName = "FriendlyName"; + + public const string OrganizationName = "OrganizationName"; + + public const string OrganizationDisplayName = "OrganizationDisplayName"; + + public const string OrganizationURL = "OrganizationURL"; } public class KeyTypes diff --git a/test/TestIdPCore/Controllers/AuthController.cs b/test/TestIdPCore/Controllers/AuthController.cs index f586104..db968fd 100644 --- a/test/TestIdPCore/Controllers/AuthController.cs +++ b/test/TestIdPCore/Controllers/AuthController.cs @@ -171,7 +171,9 @@ private IActionResult LoginPostResponse(Saml2Id inResponseTo, Saml2StatusCodes s //saml2AuthnResponse.NameId = new Saml2NameIdentifier(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).Select(c => c.Value).Single()); saml2AuthnResponse.ClaimsIdentity = claimsIdentity; - var token = saml2AuthnResponse.CreateSecurityToken(relyingParty.Issuer, /*declAuthnContext: new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"),*/ subjectConfirmationLifetime: 5, issuedTokenLifetime: 60); + + + var token = saml2AuthnResponse.CreateSecurityToken(relyingParty.Issuer, /*authnContext: new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"),*/ /*declAuthnContext: new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"),*/ subjectConfirmationLifetime: 5, issuedTokenLifetime: 60); } return responsebinding.Bind(saml2AuthnResponse).ToActionResult(); diff --git a/test/TestIdPCore/Controllers/MetadataController.cs b/test/TestIdPCore/Controllers/MetadataController.cs index 93f42f4..2976bdd 100644 --- a/test/TestIdPCore/Controllers/MetadataController.cs +++ b/test/TestIdPCore/Controllers/MetadataController.cs @@ -51,6 +51,7 @@ public IActionResult Index() new SamlAttribute("urn:oid:1.3.6.1.4.1.5923.1.1.1.1", new string[] { "member", "student", "employee" }) } }; + entityDescriptor.Organization = new Organization("Some Organization", "Some Organization Display Name", "http://some-organization.com"); entityDescriptor.ContactPersons = new[] { new ContactPerson(ContactTypes.Administrative) { diff --git a/test/TestWebAppCore/Controllers/MetadataController.cs b/test/TestWebAppCore/Controllers/MetadataController.cs index 609a8f8..636884c 100644 --- a/test/TestWebAppCore/Controllers/MetadataController.cs +++ b/test/TestWebAppCore/Controllers/MetadataController.cs @@ -50,6 +50,7 @@ public IActionResult Index() new AttributeConsumingService { ServiceName = new ServiceName("Some SP", "en"), RequestedAttributes = CreateRequestedAttributes() } }, }; + entityDescriptor.Organization = new Organization("Some Organization", "Some Organization Display Name", "http://some-organization.com"); entityDescriptor.ContactPersons = new[] { new ContactPerson(ContactTypes.Administrative) {