Skip to content

Commit 91327b5

Browse files
committed
Fix AOT-incompatible JSON in DeviceCodeLogin and add AOT regression test
1 parent 4b84873 commit 91327b5

8 files changed

Lines changed: 403 additions & 7 deletions

File tree

SafeguardDotNet.Core.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeguardDotNetUnitTest", "
5656
EndProject
5757
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeguardDotNet.SerializationTests", "Test\SafeguardDotNet.SerializationTests\SafeguardDotNet.SerializationTests.csproj", "{F5591287-9C28-4778-951A-31F6A6766B63}"
5858
EndProject
59+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeguardDotNetAotTest", "Test\SafeguardDotNetAotTest\SafeguardDotNetAotTest.csproj", "{3E63CCAE-63D0-4E10-85F4-03D35091144D}"
60+
EndProject
5961
Global
6062
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6163
Debug|Any CPU = Debug|Any CPU
@@ -118,6 +120,10 @@ Global
118120
{F5591287-9C28-4778-951A-31F6A6766B63}.Debug|Any CPU.Build.0 = Debug|Any CPU
119121
{F5591287-9C28-4778-951A-31F6A6766B63}.Release|Any CPU.ActiveCfg = Release|Any CPU
120122
{F5591287-9C28-4778-951A-31F6A6766B63}.Release|Any CPU.Build.0 = Release|Any CPU
123+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
124+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Debug|Any CPU.Build.0 = Debug|Any CPU
125+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Release|Any CPU.ActiveCfg = Release|Any CPU
126+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Release|Any CPU.Build.0 = Release|Any CPU
121127
{6802F7A9-CD3D-4608-9EEC-C98636DA2708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
122128
{6802F7A9-CD3D-4608-9EEC-C98636DA2708}.Debug|Any CPU.Build.0 = Debug|Any CPU
123129
{6802F7A9-CD3D-4608-9EEC-C98636DA2708}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -144,6 +150,7 @@ Global
144150
{1EB6D64D-7AFB-41DC-B11B-58934D053684} = {9249E337-656D-4970-B45C-7A077C56FA44}
145151
{1B11B367-2F76-49EE-A820-2A0A8B1721B1} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
146152
{F5591287-9C28-4778-951A-31F6A6766B63} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
153+
{3E63CCAE-63D0-4E10-85F4-03D35091144D} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
147154
EndGlobalSection
148155
GlobalSection(ExtensibilityGlobals) = postSolution
149156
SolutionGuid = {5A3B2C1D-4E6F-7A8B-9C0D-1E2F3A4B5C6D}

SafeguardDotNet.DeviceCodeLogin/DeviceCodeLogin.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace OneIdentity.SafeguardDotNet.DeviceCodeLogin;
1010
using System.Threading;
1111
using System.Threading.Tasks;
1212

13+
using OneIdentity.SafeguardDotNet.DeviceCodeLogin.Serialization;
14+
1315
using Serilog;
1416

1517
/// <summary>
@@ -87,7 +89,9 @@ public static async Task<ISafeguardConnection> ConnectAsync(
8789
Log.Debug("Requesting device authorization from {Appliance}", appliance);
8890

8991
var deviceAuthUrl = $"https://{appliance}/RSTS/oauth2/DeviceLogin";
90-
var requestBody = JsonSerializer.Serialize(new { client_id = clientId, scope });
92+
var requestBody = JsonSerializer.Serialize(
93+
new DeviceAuthRequest { ClientId = clientId, Scope = scope },
94+
DeviceCodeJsonContext.Default.DeviceAuthRequest);
9195
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
9296

9397
HttpResponseMessage response;
@@ -142,12 +146,14 @@ public static async Task<ISafeguardConnection> ConnectAsync(
142146

143147
await Task.Delay(TimeSpan.FromSeconds(intervalSeconds), cancellationToken).ConfigureAwait(false);
144148

145-
var pollBody = JsonSerializer.Serialize(new
146-
{
147-
grant_type = "urn:ietf:params:oauth:grant-type:device_code",
148-
device_code = deviceCode,
149-
client_id = clientId,
150-
});
149+
var pollBody = JsonSerializer.Serialize(
150+
new DeviceTokenRequest
151+
{
152+
GrantType = "urn:ietf:params:oauth:grant-type:device_code",
153+
DeviceCode = deviceCode,
154+
ClientId = clientId,
155+
},
156+
DeviceCodeJsonContext.Default.DeviceTokenRequest);
151157
var pollContent = new StringContent(pollBody, Encoding.UTF8, "application/json");
152158
var pollResponse = await http.PostAsync(tokenUrl, pollContent, cancellationToken).ConfigureAwait(false);
153159
var pollResponseBody = await pollResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) One Identity LLC. All rights reserved.
2+
3+
namespace OneIdentity.SafeguardDotNet.DeviceCodeLogin.Serialization;
4+
5+
using System.Text.Json.Serialization;
6+
7+
/// <summary>
8+
/// Request body for the rSTS device authorization endpoint
9+
/// (POST /RSTS/oauth2/DeviceLogin).
10+
/// </summary>
11+
internal sealed class DeviceAuthRequest
12+
{
13+
/// <summary>
14+
/// Gets or sets the OAuth2 client identifier. May be empty; rSTS normalizes
15+
/// an empty value to its built-in ApplicationClientId.
16+
/// </summary>
17+
[JsonPropertyName("client_id")]
18+
public string ClientId { get; set; }
19+
20+
/// <summary>
21+
/// Gets or sets the OAuth2 scope (e.g. "rsts:sts:primaryproviderid:local").
22+
/// </summary>
23+
[JsonPropertyName("scope")]
24+
public string Scope { get; set; }
25+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) One Identity LLC. All rights reserved.
2+
3+
namespace OneIdentity.SafeguardDotNet.DeviceCodeLogin.Serialization;
4+
5+
using System.Text.Json.Serialization;
6+
7+
/// <summary>
8+
/// Source-generated JSON serializer context for the DeviceCodeLogin package.
9+
/// Guarantees AOT-compatible, reflection-free serialization at compile time.
10+
/// </summary>
11+
[JsonSerializable(typeof(DeviceAuthRequest))]
12+
[JsonSerializable(typeof(DeviceTokenRequest))]
13+
internal partial class DeviceCodeJsonContext : JsonSerializerContext
14+
{
15+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) One Identity LLC. All rights reserved.
2+
3+
namespace OneIdentity.SafeguardDotNet.DeviceCodeLogin.Serialization;
4+
5+
using System.Text.Json.Serialization;
6+
7+
/// <summary>
8+
/// Request body for the rSTS token endpoint when polling for device-code
9+
/// redemption (POST /RSTS/oauth2/token with the device_code grant type).
10+
/// </summary>
11+
internal sealed class DeviceTokenRequest
12+
{
13+
/// <summary>
14+
/// Gets or sets the OAuth2 grant type. For the device authorization grant
15+
/// this is "urn:ietf:params:oauth:grant-type:device_code".
16+
/// </summary>
17+
[JsonPropertyName("grant_type")]
18+
public string GrantType { get; set; }
19+
20+
/// <summary>
21+
/// Gets or sets the device code returned by the device authorization endpoint.
22+
/// </summary>
23+
[JsonPropertyName("device_code")]
24+
public string DeviceCode { get; set; }
25+
26+
/// <summary>
27+
/// Gets or sets the OAuth2 client identifier. May be empty; see rSTS notes
28+
/// in <see cref="DeviceCodeLogin"/>.
29+
/// </summary>
30+
[JsonPropertyName("client_id")]
31+
public string ClientId { get; set; }
32+
}

SafeguardDotNet.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeguardDotNet.PkceNoninte
5252
EndProject
5353
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeguardDotNetPkceNoninteractiveLoginTester", "Test\SafeguardDotNetPkceNoninteractiveLoginTester\SafeguardDotNetPkceNoninteractiveLoginTester.csproj", "{C6D34567-3456-4321-9876-345678901CDE}"
5454
EndProject
55+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeguardDotNetAotTest", "Test\SafeguardDotNetAotTest\SafeguardDotNetAotTest.csproj", "{3E63CCAE-63D0-4E10-85F4-03D35091144D}"
56+
EndProject
5557
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{867EB36D-7893-444D-900D-29733E8E2636}"
5658
EndProject
5759
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleA2aService", "Samples\SampleA2aService\SampleA2aService.csproj", "{0149D659-78E3-476B-81F1-A80BDFA6F8A9}"
@@ -150,6 +152,10 @@ Global
150152
{BE0C60E2-002E-42A0-A1D1-3BB9AE90D607}.Debug|Any CPU.Build.0 = Debug|Any CPU
151153
{BE0C60E2-002E-42A0-A1D1-3BB9AE90D607}.Release|Any CPU.ActiveCfg = Release|Any CPU
152154
{BE0C60E2-002E-42A0-A1D1-3BB9AE90D607}.Release|Any CPU.Build.0 = Release|Any CPU
155+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
156+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Debug|Any CPU.Build.0 = Debug|Any CPU
157+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Release|Any CPU.ActiveCfg = Release|Any CPU
158+
{3E63CCAE-63D0-4E10-85F4-03D35091144D}.Release|Any CPU.Build.0 = Release|Any CPU
153159
EndGlobalSection
154160
GlobalSection(SolutionProperties) = preSolution
155161
HideSolutionNode = FALSE
@@ -165,6 +171,7 @@ Global
165171
{1EB6D64D-7AFB-41DC-B11B-58934D053684} = {9249E337-656D-4970-B45C-7A077C56FA44}
166172
{D0009DBA-16E1-4E6F-AC1E-D11B16AB3C41} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
167173
{C6D34567-3456-4321-9876-345678901CDE} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
174+
{3E63CCAE-63D0-4E10-85F4-03D35091144D} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}
168175
{0149D659-78E3-476B-81F1-A80BDFA6F8A9} = {867EB36D-7893-444D-900D-29733E8E2636}
169176
{BE0C60E2-002E-42A0-A1D1-3BB9AE90D607} = {867EB36D-7893-444D-900D-29733E8E2636}
170177
{FB679533-9E9A-416B-BDE6-CC2D5EE52D49} = {DD89D86B-68DA-4EB0-8EBC-60DE3DC2B084}

0 commit comments

Comments
 (0)