diff --git a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationHelpers.cs b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationHelpers.cs index 5b82f1d7c2..9b3d3b6070 100644 --- a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationHelpers.cs +++ b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationHelpers.cs @@ -20,7 +20,7 @@ public static IList GetClaimNamespacePrefixes(EdFiAuthorizationContext a if (!namespacePrefixes.Any() || namespacePrefixes.All(string.IsNullOrEmpty)) { throw new SecurityAuthorizationException( - SecurityAuthorizationException.DefaultDetail + " The caller has not been configured correctly for accessing resources authorized by Namespace.", + SecurityAuthorizationException.DefaultTechnicalProblemDetail + " The caller has not been configured correctly for accessing resources authorized by Namespace.", $"The API client has been given permissions on a resource that uses the '{authorizationStrategyName}' authorization strategy but the client doesn't have any namespace prefixes assigned.") { InstanceTypeParts = ["namespace", "invalid-client", "no-namespaces"] diff --git a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs index e70e665790..7ad0d8622b 100644 --- a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs +++ b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs @@ -109,7 +109,7 @@ private InstanceAuthorizationResult AuthorizeInstance( return InstanceAuthorizationResult.Failed( new SecurityAuthorizationException( SecurityAuthorizationException.DefaultDetail + " The resource item is not owned by the caller.", - $"The existing resource item has no 'OwnershipTokenId' value assigned and thus will never be accessible to clients using the '{authorizationStrategyName}' authorization strategy.") + $"The existing resource item has no 'CreatedByOwnershipTokenId' value assigned and thus will never be accessible to clients using the '{authorizationStrategyName}' authorization strategy.") { InstanceTypeParts = ["ownership", "invalid-data", "ownership-uninitialized"] }); diff --git a/Application/EdFi.Ods.Tests/EdFi.Ods.Security/Authorization/NamespaceBasedAuthorizationTests.cs b/Application/EdFi.Ods.Tests/EdFi.Ods.Security/Authorization/NamespaceBasedAuthorizationTests.cs index b74cc4f19e..ea916cfc36 100644 --- a/Application/EdFi.Ods.Tests/EdFi.Ods.Security/Authorization/NamespaceBasedAuthorizationTests.cs +++ b/Application/EdFi.Ods.Tests/EdFi.Ods.Security/Authorization/NamespaceBasedAuthorizationTests.cs @@ -28,15 +28,9 @@ public class NamespaceBasedAuthorizationStrategyTests public class SingleItemAuthorizationTests { [Test] - [TestCase( - AuthorizationPhase.ProposedData, - "Access to the resource could not be authorized. The 'Namespace' value has not been assigned but is required for authorization purposes.", - $"{EdFiProblemDetailsExceptionBase.BaseTypePrefix}:security:authorization:namespace:access-denied:namespace-required")] - [TestCase( - AuthorizationPhase.ExistingData, - "Access to the resource could not be authorized. The existing 'Namespace' value has not been assigned but is required for authorization purposes.", - $"{EdFiProblemDetailsExceptionBase.BaseTypePrefix}:security:authorization:namespace:invalid-data:namespace-uninitialized")] - public void AuthorizationContextNamespaceIsEmpty_ShouldThrowAnException(AuthorizationPhase authorizationPhase, string expectedExceptionDetail, string expectedExceptionType) + [TestCase(AuthorizationPhase.ProposedData)] + [TestCase(AuthorizationPhase.ExistingData)] + public void AuthorizationContextNamespaceIsEmpty_ShouldThrowAnException(AuthorizationPhase authorizationPhase) { //Arrange var filterDefinitionsFactory = new NamespaceBasedAuthorizationFilterDefinitionsFactory(A.Fake()); @@ -71,18 +65,24 @@ public void AuthorizationContextNamespaceIsEmpty_ShouldThrowAnException(Authoriz //Assert var exception = (SecurityAuthorizationException)result.Exception.ShouldBeExceptionType(); - exception.Detail.ShouldContain(expectedExceptionDetail); - exception.Type.ShouldBe(expectedExceptionType); + + if (authorizationPhase == AuthorizationPhase.ProposedData) + { + exception.Detail.ShouldContain("Access to the resource could not be authorized. The 'Namespace' value has not been assigned but is required for authorization purposes."); + exception.Type.ShouldBe($"{EdFiProblemDetailsExceptionBase.BaseTypePrefix}:security:authorization:namespace:access-denied:namespace-required"); + } + else if (authorizationPhase == AuthorizationPhase.ExistingData) + { + exception.Detail.ShouldContain("Access to the resource could not be authorized. The existing 'Namespace' value has not been assigned but is required for authorization purposes."); + exception.Type.ShouldBe($"{EdFiProblemDetailsExceptionBase.BaseTypePrefix}:security:authorization:namespace:invalid-data:namespace-uninitialized"); + exception.Message.ShouldContain($"The existing resource item is inaccessible to clients using the 'NamespaceBased' authorization strategy because the 'Namespace' value has not been assigned."); + } } [Test] - [TestCase( - AuthorizationPhase.ProposedData, - "Access to the resource could not be authorized. The 'Namespace' value of the resource does not start with any of the caller's associated namespace prefixes ('uri://ed-fi.org/', 'uri://ed-fi-2.org/').")] - [TestCase( - AuthorizationPhase.ExistingData, - "Access to the resource could not be authorized. The existing 'Namespace' value of the resource does not start with any of the caller's associated namespace prefixes ('uri://ed-fi.org/', 'uri://ed-fi-2.org/').")] - public void NonMatchingNamespaceClaims_ShouldThrowAnException(AuthorizationPhase authorizationPhase, string expectedExceptionDetail) + [TestCase(AuthorizationPhase.ProposedData)] + [TestCase(AuthorizationPhase.ExistingData)] + public void NonMatchingNamespaceClaims_ShouldThrowAnException(AuthorizationPhase authorizationPhase) { //Arrange var filterDefinitionsFactory = new NamespaceBasedAuthorizationFilterDefinitionsFactory(A.Fake()); @@ -118,8 +118,10 @@ public void NonMatchingNamespaceClaims_ShouldThrowAnException(AuthorizationPhase //Assert var exception = (SecurityAuthorizationException)result.Exception.ShouldBeExceptionType(); - exception.Detail.ShouldContain(expectedExceptionDetail); exception.Type.ShouldBe(string.Join(':', EdFiProblemDetailsExceptionBase.BaseTypePrefix, "security:authorization:namespace:access-denied:namespace-mismatch")); + + string existingLiteral = authorizationPhase == AuthorizationPhase.ExistingData ? "existing " : string.Empty; + exception.Detail.ShouldContain($"Access to the resource could not be authorized. The {existingLiteral}'Namespace' value of the resource does not start with any of the caller's associated namespace prefixes ('uri://ed-fi.org/', 'uri://ed-fi-2.org/')."); } } @@ -158,7 +160,7 @@ public void EmptyNamespaceClaims_ShouldThrowAnException() //Assert - exception.Detail.ShouldContain("Access to the resource could not be authorized. The caller has not been configured correctly for accessing resources authorized by Namespace."); + exception.Detail.ShouldContain("There was a problem authorizing the request. The caller has not been configured correctly for accessing resources authorized by Namespace."); exception.Type.ShouldBe(string.Join(':', EdFiProblemDetailsExceptionBase.BaseTypePrefix, "security:authorization:namespace:invalid-client:no-namespaces")); exception.Message.ShouldContain( "The API client has been given permissions on a resource that uses the 'NamespaceBased' authorization strategy but the client doesn't have any namespace prefixes assigned."); @@ -314,7 +316,7 @@ public void NoNamespaceClaims_ShouldThrowAnException() AuthorizationPhase.ProposedData))); // Assert - exception.Detail.ShouldContain("Access to the resource could not be authorized. The caller has not been configured correctly for accessing resources authorized by Namespace."); + exception.Detail.ShouldContain("There was a problem authorizing the request. The caller has not been configured correctly for accessing resources authorized by Namespace."); exception.Type.ShouldBe(string.Join(':', EdFiProblemDetailsExceptionBase.BaseTypePrefix, "security:authorization:namespace:invalid-client:no-namespaces")); exception.Message.ShouldContain( "The API client has been given permissions on a resource that uses the 'NamespaceBased' authorization strategy but the client doesn't have any namespace prefixes assigned.");