msgraph-sdk-java icon indicating copy to clipboard operation
msgraph-sdk-java copied to clipboard

Receiving different exceptions when trying to update the "additionalData" map from "PasswordProfile" from "User" resource

Open GBadila opened this issue 1 year ago • 4 comments

Expected behavior

Updating the map "additionalData" from "PasswordProfile" from "User" resource by adding some entries. I'm trying to add a field called "password-reset-verify-token" of type String.

I'm using:

What could cause my issues? And is there any documentation regarding the naming conventions regarding the namings and formats of the data from "additionalData" map?

Thank you!

Actual behavior

1. First behaviour

  • trying to add the field as key-value (String-String) which results in: com.microsoft.graph.models.odataerrors.ODataError: Expected property 'password-reset-verify-token' is not present on resource of type 'PasswordProfile'
Code
private static void setResetPasswordVerifyTokenOnUser3(
    GraphServiceClient graphServiceClient, String userEmail, String verifyToken) {
  User userResource = getUserFromUserEmail(graphServiceClient, userEmail);

  User userResourceWithUpdates = new User();
  PasswordProfile passwordProfile = new PasswordProfile();
  Map<String, Object> additionalData = new HashMap<>();
  additionalData.put("password-reset-verify-token", verifyToken);
  passwordProfile.setAdditionalData(additionalData);
  userResourceWithUpdates.setPasswordProfile(passwordProfile);

  try {
    graphServiceClient.users().byUserId(userResource.getId()).patch(userResourceWithUpdates);
  } catch (Exception e) {
    // throw exception
  }
}
Outcome
com.microsoft.graph.models.odataerrors.ODataError: Expected property 'password-reset-verify-token' is not present on resource of type 'PasswordProfile'
at com.microsoft.graph.models.odataerrors.ODataError.createFromDiscriminatorValue(ODataError.java:36)
at com.microsoft.kiota.serialization.JsonParseNode.getObjectValue(JsonParseNode.java:212)
at com.microsoft.kiota.http.OkHttpRequestAdapter.lambda$throwIfFailedResponse$0(OkHttpRequestAdapter.java:674)
at com.microsoft.kiota.ApiExceptionBuilder.<init>(ApiExceptionBuilder.java:26)
at com.microsoft.kiota.http.OkHttpRequestAdapter.throwIfFailedResponse(OkHttpRequestAdapter.java:673)
at com.microsoft.kiota.http.OkHttpRequestAdapter.send(OkHttpRequestAdapter.java:281)
at com.microsoft.graph.users.item.UserItemRequestBuilder.patch(UserItemRequestBuilder.java:779)
at com.microsoft.graph.users.item.UserItemRequestBuilder.patch(UserItemRequestBuilder.java:763)

2. Second behaviour

  • trying to add the field as key-value (String-Object) which results in: java.lang.IllegalStateException: Dangling name: password-reset-verify-token
Code
private static void setResetPasswordVerifyTokenOnUser3(
    GraphServiceClient graphServiceClient, String userEmail, String verifyToken) {
  User userResource = getUserFromUserEmail(graphServiceClient, userEmail);

  User userResourceWithUpdates = new User();
  PasswordProfile passwordProfile = new PasswordProfile();
  Map<String, Object> additionalData = new HashMap<>();

  record PasswordAdditionalData(@JsonProperty("password_reset_verify_token") String passwordResetVerifyToken) {}
  PasswordAdditionalData passwordAdditionalData = new PasswordAdditionalData(verifyToken);

  additionalData.put("password-reset-verify-token", passwordAdditionalData);
  passwordProfile.setAdditionalData(additionalData);
  userResourceWithUpdates.setPasswordProfile(passwordProfile);

  try {
    graphServiceClient.users().byUserId(userResource.getId()).patch(userResourceWithUpdates);
  } catch (Exception e) {
    // throw exception
  }
}
Outcome
java.lang.IllegalStateException: Dangling name: password-reset-verify-token
at com.google.gson.stream.JsonWriter.close(JsonWriter.java:346)
at com.google.gson.stream.JsonWriter.endObject(JsonWriter.java:321)
at com.microsoft.kiota.serialization.JsonSerializationWriter.writeObjectValue(JsonSerializationWriter.java:316)
at com.microsoft.graph.models.User.serialize(User.java:1279)
at com.microsoft.kiota.serialization.JsonSerializationWriter.writeObjectValue(JsonSerializationWriter.java:301)
at com.microsoft.kiota.RequestInformation.setContentFromParsable(RequestInformation.java:337)
at com.microsoft.graph.users.item.UserItemRequestBuilder.toPatchRequestInformation(UserItemRequestBuilder.java:854)
at com.microsoft.graph.users.item.UserItemRequestBuilder.patch(UserItemRequestBuilder.java:776)
at com.microsoft.graph.users.item.UserItemRequestBuilder.patch(UserItemRequestBuilder.java:763)

Steps to reproduce the behavior

See the code snippets attached above

GBadila avatar Jun 19 '24 10:06 GBadila

Thanks for raising this @GBadila

I believe the first example is appropriate in adding a property, however the API is failing as the type does not accept/support the new property name. Any chance you can confirm if what you are trying to achieve by sharing a json representation of the desired object?

According to the API docs, the only supported properties by the api are documented at https://learn.microsoft.com/en-us/graph/api/resources/passwordprofile?view=graph-rest-1.0

andrueastman avatar Jun 25 '24 11:06 andrueastman

Hi @andrueastman! As per the documentation you linked PasswordProfile should have only 3 fields to set up:

  • forceChangePasswordNextSignIn
  • forceChangePasswordNextSignInWithMfa
  • password

But based on the latest version of the Java SDK for Microsoft Graph it looks like there are 6 setter methods.

  • snippet from PasswordProfile (https://github.com/microsoftgraph/msgraph-sdk-java/blob/main/src/main/java/com/microsoft/graph/generated/models/PasswordProfile.java#L115-L157)
  public void setAdditionalData(@Nullable final Map<String, Object> value) {
    this.backingStore.set("additionalData", value);
  }

  public void setBackingStore(@Nonnull final BackingStore value) {
    Objects.requireNonNull(value);
    this.backingStore = value;
  }

  public void setForceChangePasswordNextSignIn(@Nullable final Boolean value) {
    this.backingStore.set("forceChangePasswordNextSignIn", value);
  }

  public void setForceChangePasswordNextSignInWithMfa(@Nullable final Boolean value) {
    this.backingStore.set("forceChangePasswordNextSignInWithMfa", value);
  }

  public void setOdataType(@Nullable final String value) {
    this.backingStore.set("odataType", value);
  }

  public void setPassword(@Nullable final String value) {
    this.backingStore.set("password", value);
  }

Which made me think that I could use that setAdditionalData method for my own use-case. I'm trying to have a flow where:

  1. When reset password is requested by the client the server generates a verify token (and saves it in that additional data map).
  2. The verify token is sent to the user and the user provides the verify token to the client.
  3. The client sends the verify token to the server.
  4. The server retrieves the verify token from additional data map and compares the 2 tokens.
  5. If the tokens are the same the password is updated.

So basically, I'm trying to add an entry String:String (key:value) to the additional data map, which errors out as mentioned in my issue.

GBadila avatar Jun 26 '24 10:06 GBadila

Unfortunately, in this scenario I don't believe it is possible to add extra properties to the PasswordProfile type and send them to the Graph API.

The AdditionalData property exists in all models in the SDK to enable extensibility as you would have liked to use it as well as holding extra properties returned in the API that are not described.

andrueastman avatar Jun 26 '24 12:06 andrueastman

The AdditionalData property exists in all models in the SDK to enable extensibility as you would have liked to use it as well as holding extra properties returned in the API that are not described.

Then if it's not meant to be used by adding additional properties by the user why let the setter method under the public access modifier? Or if it has to be public why not attached a comment to let people know is not meant to be used by the users? It's a bit confusing as it is at the moment.

GBadila avatar Jul 01 '24 15:07 GBadila

Closing since API does not support adding additional properties & the additionalData property was not designed for this purpose.

Ndiritu avatar Jan 09 '25 12:01 Ndiritu