microsoftgraph / microsoftgraph/msgraph-beta-sdk-dotnet

Fido2Method - create endpoint is missing + API has a bug

Open
#941 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dependency:metadata type:bug
Dominant language
C#
Stars
112
Forks
37
Avg merge
14h 57m
Merged PRs (30d)
3

Description

Describe the bug

1. Fido2Method PostAsync implementation is missing

I had to implement my own request builder to go further.

2. API does not work as other APIs does

When I send json as API docs describes, API returns a validation error. To fix this, I have to remove @odata.type, then I will received expected error (invalid data). I've debugged "create" user and its sends the @odata.type and its working.

Error code
{
    "error": {
        "code": "badRequest",
        "message": "The request is missing a fido2AuthenticationMethod entity with a displayName and publicKeyCredential in the request body. All other properties will be ignored.",
        "innerError": {
            "message": "The request is missing a fido2AuthenticationMethod entity with a displayName and publicKeyCredential in the request body. All other properties will be ignored.",
            "date": "2024-12-01T12:43:54",
            "request-id": "e279fa99-6eba-488e-8d8e-04d6ac5c7efc",
            "client-request-id": "3084846a-c2d0-02db-59ab-7a574bcbd418"
        }
    }
}
Payload
{"@odata.type":"#microsoft.graph.fido2AuthenticationMethod","displayName":"Crayonic PIV #3223392482","publicKeyCredential":{"id":"asd",,"response":{"attestationObject":"VGhpcyBpcyB0aGUgYXR0ZXN0YXRpb25PYmplY3QgZW5jb2RlZCB0byBiZSB3ZWJzYWZlIHdoaWNoIHdpbGwgYmUgc2VudCB0byBFbnRyYSBJRA","clientDataJSON":"VGhpcyBpcyB0aGUgY2xpZW50RGF0YUpTT04gZW5jb2RlZCB0byBiZSB3ZWJzYWZlIHdoaWNoIHdpbGwgYmUgc2VudCB0byBFbnRyYSBJRA"}}}
Working payload
{"displayName":"Crayonic PIV #3223392482","publicKeyCredential":{"id":"asd","response":{"attestationObject":"VGhpcyBpcyB0aGUgYXR0ZXN0YXRpb25PYmplY3QgZW5jb2RlZCB0byBiZSB3ZWJzYWZlIHdoaWNoIHdpbGwgYmUgc2VudCB0byBFbnRyYSBJRA","clientDataJSON":"VGhpcyBpcyB0aGUgY2xpZW50RGF0YUpTT04gZW5jb2RlZCB0byBiZSB3ZWJzYWZlIHdoaWNoIHdpbGwgYmUgc2VudCB0byBFbnRyYSBJRA"}}}

Thank you for your time.

Expected behavior
  1. Method being implemented
  2. API would accept standart body
How to reproduce
  1. Check the code for PostAsync in the code base
  2. Take example body from the docs and run it on the API. Remove the @odata.type and send the request. Normal error would be given (invalid client data json
SDK Version

5.88.0-preview

Latest version known to work for scenario above?

No response

Known Workarounds
  1. Implement own request and body authentication method and remove @odata.type
  2. Remove @odata.type from API request
Debug output

No response

Configuration
  • MAC, apple sillicon
Other information
Custom request for create
using Microsoft.Kiota.Abstractions.Serialization;
using Microsoft.Kiota.Abstractions;

namespace MicrosoftGraph.Requests;

// <auto-generated/>
#pragma warning disable CS0618

[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
public partial class Fido2CreateBuilder : BaseRequestBuilder
{
    public Fido2CreateBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(
        requestAdapter, "{+baseurl}/users/{user%2Did}/authentication/fido2Methods",
        pathParameters)
    {
    }

    public Fido2CreateBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter,
        "{+baseurl}/users/{user%2Did}/authentication/fido2Methods", rawUrl)
    {
    }

#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
    public async Task<global::Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod?> PostAsync(
        global::Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod body,
        Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default,
        CancellationToken cancellationToken = default)
    {
#nullable restore
#else
        public async Task<global::Microsoft.Graph.Beta.Models.User> PostAsync(global::Microsoft.Graph.Beta.Models.User body, Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration
 = default, CancellationToken cancellationToken = default)
        {
#endif
        _ = body ?? throw new ArgumentNullException(nameof(body));
        var requestInfo = ToPostRequestInformation(body, requestConfiguration);
        var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
        {
            { "XXX", global::Microsoft.Graph.Beta.Models.ODataErrors.ODataError.CreateFromDiscriminatorValue },
        };
        return await RequestAdapter.SendAsync<global::Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod>(
                requestInfo,
                global::Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod.CreateFromDiscriminatorValue,
                errorMapping, cancellationToken)
            .ConfigureAwait(false);
    }

#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
    public RequestInformation ToPostRequestInformation(
        global::Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod body,
        Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
    {
#nullable restore
#else
        public RequestInformation ToPostRequestInformation(global::Microsoft.Graph.Beta.Models.User body, Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration
 = default)
        {
#endif
        _ = body ?? throw new ArgumentNullException(nameof(body));
        var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters);
        requestInfo.Configure(requestConfiguration);
        requestInfo.Headers.TryAdd("Accept", "application/json");
        requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body);
        return requestInfo;
    }

    public Fido2CreateBuilder WithUrl(string rawUrl)
    {
        return new Fido2CreateBuilder(rawUrl, RequestAdapter);
    }

    [Obsolete(
        "This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
    [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
    public partial class UsersRequestBuilderPostRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
    {
    }
}
#pragma warning restore CS0618
Custom body model

using Microsoft.Kiota.Abstractions.Serialization;

namespace MicrosoftGraph.Requests;

public class CreateFido2AuthenticationMethod:  Microsoft.Graph.Beta.Models.Fido2AuthenticationMethod
{
    public override void Serialize(ISerializationWriter writer)
    {
        // TODO: hotfix: @odata.type cant be sent (base())
        _ = writer ?? throw new ArgumentNullException(nameof(writer));
        
        writer.WriteStringValue("aaGuid", AaGuid);
        writer.WriteCollectionOfPrimitiveValues<string>("attestationCertificates", AttestationCertificates);
        writer.WriteEnumValue<global::Microsoft.Graph.Beta.Models.AttestationLevel>("attestationLevel", AttestationLevel);
        writer.WriteStringValue("displayName", DisplayName);
        writer.WriteStringValue("model", Model);
        writer.WriteObjectValue<global::Microsoft.Graph.Beta.Models.WebauthnPublicKeyCredential>("publicKeyCredential", PublicKeyCredential);
    }
}
Usage code
 var requestBuilder = client.GraphService.Users[create.ExternalUserId].Authentication.Fido2Methods;

        var fido2CreateBuilder = new Fido2CreateBuilder(
            (requestBuilder.ToGetRequestInformation().PathParameters as Dictionary<string, object>)!,
            client.GraphService.RequestAdapter
        );
        
        await fido2CreateBuilder.PostAsync(
            body: new CreateFido2AuthenticationMethod
            {
                DisplayName = create.DisplayName,
                PublicKeyCredential = new WebauthnPublicKeyCredential()
                {
                    Id = create.Id,
                    Response = new WebauthnAuthenticatorAttestationResponse()
                    {
                        ClientDataJSON = create.ClientDataJson,
                        AttestationObject = create.AttestationObject
                    }
                }
            }, cancellationToken: cancellationToken
        );

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the generated Fido2Method PostAsync implementation and comparing it with the custom Fido2CreateBuilder shown in the issue. Inspect Fido2AuthenticationMethod serialization, especially the @odata.type output, and reproduce the documented payload against the create endpoint. Done means the generated method exists and the documented request reaches normal payload validation without requiring @odata.type removal.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.