Skip to content

Commit 39faef5

Browse files
hakimmsjsquire
andauthored
Entra - Make Source field in payload required (#37966)
* Marked empty/null actions as failed * replaced tabs with spaces * Updated spacing * Replaced tab with spaces * Updates based on feedback * Updated Validation Logic * WIP Added test cases for OneOrMoreRequiredAttribute * Added test case for EnumberableItemsNotNull Attribute * Feedback updates * Updates based on PR feedback * Sort 'using' lists and removed unapplicable data annotation * Adding necessary updates to merge with azure main * Removed xUnit reference now that we are using NUnit tests * removed Update-Snippets.ps1 changes and will rebase * Added null check and test for response before marking as failed * Updated exception to validation exception and corrected test * Changed back to argument null exception * Added response validation exception type * Update sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/src/AuthenticationEventResource.resx Adding a missing period Co-authored-by: Jesse Squire <[email protected]> * Added period * Added not null check for source field in payload * Changed source attribute to required * Sorted usings * Added test scenarios for AuthenticationEventMetadata * Added big fix to changelog * Refactored test case for consistency with existing tests and added links to changelog * Added assertions for exception messages and removed links to bugs * Ran scripts to update netstandard2.0 class --------- Co-authored-by: Jesse Squire <[email protected]>
1 parent d86f715 commit 39faef5

11 files changed

+199
-14
lines changed

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
### Bugs Fixed
66

7-
- Updated ODataType signature - 2433332
8-
- Empty or null response actions will throw a bad response - 2161553
7+
- Updated ODataType signature
8+
- Empty or null response actions will throw a bad response
9+
- Made the source field in the request a required field
910

1011
## 1.0.0-beta.3 (2022-12-13)
1112

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/api/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.netstandard2.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ protected CloudEventData() { }
130130
internal CloudEventRequest() { }
131131
[System.Text.Json.Serialization.JsonPropertyNameAttribute("oDataType")]
132132
public string ODataType { get { throw null; } set { } }
133+
[System.ComponentModel.DataAnnotations.RequiredAttribute]
133134
[System.Text.Json.Serialization.JsonPropertyNameAttribute("source")]
134135
public string Source { get { throw null; } set { } }
135136
}

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/src/Framework/CloudEventRequest.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.Validators;
4+
using System.ComponentModel.DataAnnotations;
55
using System.Net.Http;
66
using System.Text.Json.Serialization;
7+
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.Validators;
78

89
namespace Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework
910
{
@@ -17,7 +18,7 @@ public abstract class CloudEventRequest<TResponse, TData> : AuthenticationEventR
1718
/// <summary>Gets or sets the source.</summary>
1819
/// <value>The source.</value>
1920
[JsonPropertyName("source")]
20-
[RequireNonDefault]
21+
[Required]
2122
public string Source { get; set; }
2223

2324
/// <summary>Gets or sets the cloud event data type.</summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using System.ComponentModel.DataAnnotations;
6+
using System.Net.Http;
7+
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
8+
using NUnit.Framework;
9+
using Payload = Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Tests.Payloads.TokenIssuanceStart;
10+
11+
namespace Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Tests.Framework
12+
{
13+
[TestFixture]
14+
public class AuthenticationEventMetadataTests
15+
{
16+
[Test]
17+
[TestCaseSource(nameof(TestScenarios))]
18+
public void TestRequestCreateInstance(object testObject, string message, bool success, string exceptionMessage)
19+
{
20+
string payload = testObject.ToString();
21+
AuthenticationEventMetadata eventMetadata = AuthenticationEventMetadataLoader.GetEventMetadata(payload);
22+
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, $"http://localhost:7278/runtime/webhooks/customauthenticationextension?code=opVsbQul8-MsRuM9x6yVoghE2Xda5G-MeV_Ybv1MdEfuAzFuVtpEpg==&functionName=onTokenIssuanceStart");
23+
24+
if (success == false)
25+
{
26+
var ex = Assert.Throws<ValidationException>(() => eventMetadata.CreateEventRequestValidate(requestMessage, payload, string.Empty));
27+
Assert.AreEqual(exceptionMessage, ex.Message);
28+
}
29+
else
30+
{
31+
Assert.DoesNotThrow(() => eventMetadata.CreateEventRequestValidate(requestMessage, payload, string.Empty));
32+
}
33+
}
34+
35+
private static IEnumerable<object[]> TestScenarios()
36+
{
37+
#region Invalid
38+
yield return new TestCaseStructure()
39+
{
40+
Test = Payload.TokenIssuanceStart.RequestWithoutSourcePayload,
41+
Message = "Testing request payload without source field passed and verifies it throws an error",
42+
ExceptionMessage = "TokenIssuanceStartRequest: The Source field is required."
43+
}.ToArray;
44+
#endregion
45+
46+
#region Valid
47+
yield return new TestCaseStructure()
48+
{
49+
Test = Payload.TokenIssuanceStart.ValidRequestPayload,
50+
Message = "Testing valid full request payload",
51+
Success = true,
52+
}.ToArray;
53+
#endregion
54+
}
55+
}
56+
}

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/tests/Framework/Validators/EnumerableItemsNotNullAttributeTests.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using System.Collections.Generic;
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
25
using System.ComponentModel.DataAnnotations;
36
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.Validators;
47
using NUnit.Framework;
@@ -13,13 +16,14 @@ public class EnumerableItemsNotNullAttributeTests
1316
{
1417
[Test]
1518
[TestCaseSource(nameof(TestScenarios))]
16-
public void EnumberableItemsNotNullIsValidWithTestCase(object testObject, string message, bool success)
19+
public void EnumberableItemsNotNullIsValidWithTestCase(object testObject, string message, bool success, string exceptionMessage)
1720
{
1821
DummyClass dummyObj = new() { Obj = testObject };
1922

2023
if (success == false)
2124
{
22-
Assert.Throws<ValidationException>(() => Validator.ValidateObject(dummyObj, new ValidationContext(dummyObj), true), AuthenticationEventResource.Ex_Null_Action_Items);
25+
var ex = Assert.Throws<ValidationException>(() => Validator.ValidateObject(dummyObj, new ValidationContext(dummyObj), true));
26+
Assert.AreEqual(exceptionMessage, ex.Message);
2327
}
2428
else
2529
{
@@ -43,30 +47,35 @@ private static IEnumerable<object[]> TestScenarios()
4347
{
4448
Test = null,
4549
Message = "Testing null",
50+
ExceptionMessage = AuthenticationEventResource.Ex_Null_Action_Items,
4651
}.ToArray;
4752
yield return new TestCaseStructure()
4853
{
4954
Test = new object(),
5055
Message = "Testing object",
56+
ExceptionMessage = AuthenticationEventResource.Ex_Null_Action_Items,
5157
}.ToArray;
5258
yield return new TestCaseStructure()
5359
{
5460
Test = new List<object>() { null },
5561
Message = "Testing object list with null item",
62+
ExceptionMessage = AuthenticationEventResource.Ex_Null_Action_Items,
5663
}.ToArray;
5764
yield return new TestCaseStructure()
5865
{
5966
Test = new List<object>() { new(), null, new() },
6067
Message = "Testing object list with multiple items with one null",
68+
ExceptionMessage = AuthenticationEventResource.Ex_Null_Action_Items,
6169
}.ToArray;
6270
yield return new TestCaseStructure()
6371
{
6472
Test = new object[1],
6573
Message = "Testing single null item array",
74+
ExceptionMessage = AuthenticationEventResource.Ex_Null_Action_Items,
6675
}.ToArray;
67-
#endregion
76+
#endregion
6877

69-
#region Valid
78+
#region Valid
7079
yield return new TestCaseStructure()
7180
{
7281
Test = new List<object>() { new(), new() },

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/tests/Framework/Validators/OneOrMoreRequiredAttributeTests.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using System.Collections.Generic;
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
25
using System.ComponentModel.DataAnnotations;
36
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework.Validators;
47
using NUnit.Framework;
@@ -13,13 +16,14 @@ public class OneOrMoreRequiredAttributeTests
1316
{
1417
[Test]
1518
[TestCaseSource(nameof(TestScenarios))]
16-
public void OneOrMoreRequiredIsValidWithTestCase(object testObject, string message, bool success)
19+
public void OneOrMoreRequiredIsValidWithTestCase(object testObject, string message, bool success, string exceptionMessage)
1720
{
1821
DummyClass dummyObj = new() { Obj = testObject };
1922

2023
if (success == false)
2124
{
22-
Assert.Throws<ValidationException>(() => Validator.ValidateObject(dummyObj, new ValidationContext(dummyObj), true), AuthenticationEventResource.Ex_No_Action);
25+
var ex = Assert.Throws<ValidationException>(() => Validator.ValidateObject(dummyObj, new ValidationContext(dummyObj), true));
26+
Assert.AreEqual(exceptionMessage, ex.Message);
2327
}
2428
else
2529
{
@@ -43,21 +47,25 @@ private static IEnumerable<object[]> TestScenarios()
4347
{
4448
Test = null,
4549
Message = "Testing null",
50+
ExceptionMessage = AuthenticationEventResource.Ex_No_Action,
4651
}.ToArray;
4752
yield return new TestCaseStructure()
4853
{
4954
Test = new object(),
5055
Message = "Testing object",
56+
ExceptionMessage = AuthenticationEventResource.Ex_No_Action,
5157
}.ToArray;
5258
yield return new TestCaseStructure()
5359
{
5460
Test = new List<object>(),
5561
Message = "Testing initialized object",
62+
ExceptionMessage = AuthenticationEventResource.Ex_No_Action,
5663
}.ToArray;
5764
yield return new TestCaseStructure()
5865
{
5966
Test = new object[0],
6067
Message = "Testing empty array",
68+
ExceptionMessage = AuthenticationEventResource.Ex_No_Action,
6169
}.ToArray;
6270
#endregion
6371

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/tests/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
<None Remove="Payloads\TokenIssuanceStart\InvalidActionResponse.json" />
1111
<None Remove="Payloads\TokenIssuanceStart\NoActionResponse.json" />
1212
<None Remove="Payloads\TokenIssuanceStart\QueryParameters.json" />
13+
<None Remove="Payloads\TokenIssuanceStart\RequestMissingSource.json" />
14+
<None Remove="Payloads\TokenIssuanceStart\ValidRequest.json" />
1315
</ItemGroup>
1416

1517
<ItemGroup>
@@ -19,6 +21,8 @@
1921
<EmbeddedResource Include="Payloads\TokenIssuanceStart\ConversionPayload.json" />
2022
<EmbeddedResource Include="Payloads\TokenIssuanceStart\InvalidActionResponse.json" />
2123
<EmbeddedResource Include="Payloads\TokenIssuanceStart\NoActionResponse.json" />
24+
<EmbeddedResource Include="Payloads\TokenIssuanceStart\RequestMissingSource.json" />
25+
<EmbeddedResource Include="Payloads\TokenIssuanceStart\ValidRequest.json" />
2226
<EmbeddedResource Include="Payloads\TokenIssuanceStart\NullResponse.json" />
2327
<EmbeddedResource Include="Payloads\TokenIssuanceStart\ExpectedPayload.json" />
2428
<EmbeddedResource Include="Payloads\TokenIssuanceStart\QueryParameters.json" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"type": "microsoft.graph.authenticationEvent.tokenIssuanceStart",
3+
"data": {
4+
"@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData",
5+
"tenantId": "d33b1c3f-49c2-8cb3-963b-ca195de1e704",
6+
"authenticationEventListenerId": "6fd9cb25-ff72-304b-7b27-5fd793aa3c2f",
7+
"customAuthenticationExtensionId": "ce1b2217-fdf9-a19f-2f46-a639514a4107",
8+
"authenticationContext": {
9+
"correlationId": "1dc14bea-414b-a99e-64de-b4702d82ab59",
10+
"client": {
11+
"ip": "30.51.176.110",
12+
"locale": "en-us",
13+
"market": "en-us"
14+
},
15+
"protocol": "OAUTH2.0",
16+
"clientServicePrincipal": {
17+
"id": "1dc14bea-414b-a99e-64de-b4702d82ab59",
18+
"appId": "d56ef0c3-a4e8-b26c-484c-8873b560eab3",
19+
"appDisplayName": "My Test application",
20+
"displayName": "My Test application"
21+
},
22+
"resourceServicePrincipal": {
23+
"id": "8de396f3-6559-a65c-398e-43a2fc6a2141",
24+
"appId": "d56ef0c3-a4e8-b26c-484c-8873b560eab3",
25+
"appDisplayName": "My Test application",
26+
"displayName": "My Test application"
27+
},
28+
"user": {
29+
"createdDateTime": "2016-03-01T15:23:40Z",
30+
"displayName": "Bob",
31+
"givenName": "Bob Smith",
32+
"id": "90847c2a-e29d-4d2f-9f54-c5b4d3f26471",
33+
"mail": "[email protected]",
34+
"preferredLanguage": "en-us",
35+
"surname": "Smith",
36+
"userPrincipalName": "[email protected]",
37+
"userType": "Member"
38+
}
39+
}
40+
}
41+
}

sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents/tests/Payloads/TokenIssuanceStart/TokenIssuanceStart.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,23 @@ public static string NullResponsePayload
7070
return PayloadHelper.GetPayload("TokenIssuanceStart.NullResponse.json");
7171
}
7272
}
73+
74+
/// <summary> Gets the valid request payload </summary>
75+
public static string ValidRequestPayload
76+
{
77+
get
78+
{
79+
return PayloadHelper.GetPayload("TokenIssuanceStart.ValidRequest.json");
80+
}
81+
}
82+
83+
/// <summary> Gets the request payload without source field </summary>
84+
public static string RequestWithoutSourcePayload
85+
{
86+
get
87+
{
88+
return PayloadHelper.GetPayload("TokenIssuanceStart.RequestMissingSource.json");
89+
}
90+
}
7391
}
7492
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"type": "microsoft.graph.authenticationEvent.tokenIssuanceStart",
3+
"source": "/tenants/d33b1c3f-49c2-8cb3-963b-ca195de1e704/applications/d56ef0c3-a4e8-b26c-484c-8873b560eab3",
4+
"data": {
5+
"@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData",
6+
"tenantId": "d33b1c3f-49c2-8cb3-963b-ca195de1e704",
7+
"authenticationEventListenerId": "6fd9cb25-ff72-304b-7b27-5fd793aa3c2f",
8+
"customAuthenticationExtensionId": "ce1b2217-fdf9-a19f-2f46-a639514a4107",
9+
"authenticationContext": {
10+
"correlationId": "1dc14bea-414b-a99e-64de-b4702d82ab59",
11+
"client": {
12+
"ip": "30.51.176.110",
13+
"locale": "en-us",
14+
"market": "en-us"
15+
},
16+
"protocol": "OAUTH2.0",
17+
"clientServicePrincipal": {
18+
"id": "1dc14bea-414b-a99e-64de-b4702d82ab59",
19+
"appId": "d56ef0c3-a4e8-b26c-484c-8873b560eab3",
20+
"appDisplayName": "My Test application",
21+
"displayName": "My Test application"
22+
},
23+
"resourceServicePrincipal": {
24+
"id": "8de396f3-6559-a65c-398e-43a2fc6a2141",
25+
"appId": "d56ef0c3-a4e8-b26c-484c-8873b560eab3",
26+
"appDisplayName": "My Test application",
27+
"displayName": "My Test application"
28+
},
29+
"user": {
30+
"createdDateTime": "2016-03-01T15:23:40Z",
31+
"displayName": "Bob",
32+
"givenName": "Bob Smith",
33+
"id": "90847c2a-e29d-4d2f-9f54-c5b4d3f26471",
34+
"mail": "[email protected]",
35+
"preferredLanguage": "en-us",
36+
"surname": "Smith",
37+
"userPrincipalName": "[email protected]",
38+
"userType": "Member"
39+
}
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)