Skip to content

Support JSON object state values in SignIn VerifyState activities (non-breaking)#329

Draft
Copilot wants to merge 6 commits intomainfrom
copilot/fix-signin-verifystate-json-error
Draft

Support JSON object state values in SignIn VerifyState activities (non-breaking)#329
Copilot wants to merge 6 commits intomainfrom
copilot/fix-signin-verifystate-json-error

Conversation

Copy link
Contributor

Copilot AI commented Feb 12, 2026

  • Understand the codebase structure and the issue
  • Modify StateVerifyQuery to handle both string and JSON object types using custom JsonConverter
  • Keep State property as string? to maintain backward compatibility
  • Update tests for state as string (existing behavior)
  • Update tests for state as JSON object (new behavior for Android/iOS)
  • Run tests to verify the fix
  • Run additional tests to ensure no regressions
  • Address reviewer feedback about breaking changes
  • Address code review feedback about potential recursion
  • Remove redundant test case
  • Run security scan - No security issues found
Original prompt

This section details on the original issue you should resolve

<issue_title>SignIn VerifyState activity state may be json objects on android and ios devices</issue_title>
<issue_description>Please refer to OfficeDev/microsoft-teams-library-js#2189, OfficeDev/microsoft-teams-library-js#528. The state property may not be string type, so it can cause json deserialization error when user signin on android and ios devices.

System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.value.state | LineNumber: 0 | BytePositionInLine: 1123.
[ERROR]  ---> System.InvalidOperationException: Cannot get the value of a token type 'StartObject' as a string.
[ERROR]    at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ExpectedString(JsonTokenType tokenType)
[ERROR]    at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)        
[ERROR]    at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
[ERROR]    at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)        
[ERROR]    at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)   
[ERROR]    --- End of inner exception stack trace ---
[ERROR]    at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)   
[ERROR]    at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
[ERROR]    at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
[ERROR]    at Microsoft.Teams.Api.Activities.Invokes.SignInActivity.JsonConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)   
[ERROR]    at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
[ERROR]    at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
[ERROR]    at Microsoft.Teams.Api.Activities.InvokeActivity.JsonConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)  
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)   
[ERROR]    at System.Text.Json.JsonSerializer.ReadFromNode[TValue](JsonNode node, JsonTypeInfo`1 jsonTypeInfo)
[ERROR]    at Microsoft.Teams.Api.Activities.Activity.JsonConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)        
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
[ERROR]    at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)   
[ERROR]    at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
[ERROR]    at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
[ERROR]    at Microsoft.Teams.Plugins.AspNetCore.AspNetCorePlugin.ParseActivity(HttpRequest httpRequest)
[ERROR]    at Microsoft.Teams.Plugins.AspNetCore.AspNetCorePlugin.Do(HttpContext httpContext, CancellationToken ca...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes microsoft/teams.net#302

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/microsoft/teams.net/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits February 12, 2026 17:59
…nd object types

Co-authored-by: singhk97 <115390646+singhk97@users.noreply.github.com>
Co-authored-by: singhk97 <115390646+singhk97@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix JSON deserialization error in SignIn VerifyState activity Support JSON object state values in SignIn VerifyState activities Feb 12, 2026
Copilot AI requested a review from singhk97 February 12, 2026 18:05
@singhk97
Copy link
Collaborator

#302 issue for reference

/// </summary>
[JsonPropertyName("state")]
[JsonPropertyOrder(0)]
public string? State { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot This is a change that will break existing customers. Can you help me understand if it's possible to keep this as a string, and deserialize values (even if they're json objects) into a string as well. How will that look like?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the implementation to use a custom JsonConverter that keeps the State property as string?, maintaining full backward compatibility. The converter automatically handles both cases:

  • When the value is a string, it returns it directly
  • When the value is a JSON object (Android/iOS), it serializes it to a JSON string

This approach is non-breaking - existing code that reads State as a string will continue to work without any changes. See commit 415b665.

[JsonPropertyName("state")]
[JsonPropertyOrder(0)]
public string? State { get; set; }
public JsonElement? State { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot also consider the scenario where if state is not a string this would be parsed as the default value, and the onus is on the end user to access this from a catch all property bag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to make sure I understand your suggestion correctly. Are you proposing that:

  1. If state is a string → State property gets the string value
  2. If state is an object → State property is null, and the object is available in a Properties extension data dictionary?

The concern I have with this approach is that it would lose the state information when it's sent as an object (Android/iOS case). The current implementation converts objects to JSON strings, so the state data is preserved and accessible via the State property, maintaining backward compatibility while ensuring no data loss.

Could you clarify if you're suggesting this alternative, or if you have a different scenario in mind?

Copilot AI and others added 2 commits February 13, 2026 18:01
Co-authored-by: singhk97 <115390646+singhk97@users.noreply.github.com>
Co-authored-by: singhk97 <115390646+singhk97@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 13, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • token.botframework.com
    • Triggering command: /usr/share/dotnet/dotnet /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net8.0/Microsoft.Teams.Apps.Tests.runtimeconfig.json --depsfile /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net8.0/Microsoft.Teams.Apps.Tests.deps.json /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net8.0/testhost.dll --port 39419 --endpoint 127.0.0.1:039419 --role client --parentprocessid 4364 --telemetryoptedin false (dns block)
    • Triggering command: /usr/share/dotnet/dotnet /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net10.0/Microsoft.Teams.Apps.Tests.runtimeconfig.json --depsfile /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net10.0/Microsoft.Teams.Apps.Tests.deps.json /home/REDACTED/work/teams.net/teams.net/Tests/Microsoft.Teams.Apps.Tests/bin/Debug/net10.0/testhost.dll --port 39019 --endpoint 127.0.0.1:039019 --role client --parentprocessid 4399 --telemetryoptedin false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Support JSON object state values in SignIn VerifyState activities Support JSON object state values in SignIn VerifyState activities (non-breaking) Feb 13, 2026
Copilot AI requested a review from singhk97 February 13, 2026 18:05
}

[Fact]
public void setupSignInVerifyStateActivity_StateAsString()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot remove this test case as it is redundant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the redundant test case. The string state behavior is already covered by the existing tests. See commit 641a08c.

Co-authored-by: singhk97 <115390646+singhk97@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants