Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to create user with additional security attributes: Dangling Name #2063

Closed
cascer1 opened this issue Jun 26, 2024 · 3 comments
Closed
Labels
type:bug A broken experience

Comments

@cascer1
Copy link

cascer1 commented Jun 26, 2024

Describe the bug

I am trying to create a new user in Entra using the Graph API, and include some custom security attributes that I've defined earlier in the Azure portal.

My attribute set is called UserManagementAPI with attributes userType, userRoles, lastEnabledDate, and organizationIds. All attributes are of type string, plural names indicate that multiple values are allowed.

I suspect that there's a problem somewhere in the backing store for the CustomSecurityAttributeValue class.

Expected behavior

It should be possible to create users with custom security attributes

How to reproduce

First, create a user without custom security attributes to verify that this works. Then, try adding custom security attributes to the request and observe exceptions.

Code sample:

User newUser = new User();
newUser.setAccountEnabled(true);
newUser.setDisplayName("Test User");
// truncated extra fields for brevity

CustomSecurityAttributeValue attributeValue = new CustomSecurityAttributeValue();
HashMap<String, Object> additionalData = new HashMap<>();

JsonObject additionalUserProperties = new JsonObject();

additionalUserProperties.add("@odata.type", new JsonPrimitive("#Microsoft.DirectoryServices.CustomSecurityAttributeValue"));

// Set organization IDs
JsonArray organizationIds = new JsonArray();
organizationIds.add("123");
organizationIds.add("321");
additionalUserProperties.add("organizationIds", organizationIds);

// Set user type
additionalUserProperties.add("userType", new JsonPrimitive("basic"));

// Finalize custom attribute object
additionalData.put("UserManagementAPI", additionalUserProperties);
attributeValue.setAdditionalData(additionalData);

newUser.setCustomSecurityAttributes(attributeValue); // <-- Creating a user works until this line is uncommented

User createdUser = graphClient.users().post(requestUser); // <-- Exception is thrown here

SDK Version

6.13.0

Latest version known to work for scenario above?

No response

Known Workarounds

No response

Debug output

Click to expand log
java.lang.IllegalStateException: Dangling name: UserManagementAPI
	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:1215)
	at com.microsoft.kiota.serialization.JsonSerializationWriter.writeObjectValue(JsonSerializationWriter.java:301)
	at com.microsoft.kiota.RequestInformation.setContentFromParsable(RequestInformation.java:337)
	at com.microsoft.graph.users.UsersRequestBuilder.toPostRequestInformation(UsersRequestBuilder.java:190)
	at com.microsoft.graph.users.UsersRequestBuilder.post(UsersRequestBuilder.java:144)
	at com.microsoft.graph.users.UsersRequestBuilder.post(UsersRequestBuilder.java:131)
	at com.example.user.management.api.comm.graphapi.GraphApiCommunicatorImpl.createUser(GraphApiCommunicatorImpl.java:85)
	at com.example.user.management.api.comm.graphapi.GraphApiCommunicatorImpl_ClientProxy.createUser(Unknown Source)
	at com.example.user.management.api.logic.UserFacade.createEntraUser(UserFacade.java:64)
	at com.example.user.management.api.logic.UserFacade.createOrganizationUser(UserFacade.java:50)
	at com.example.user.management.api.logic.UserFacade.createUser(UserFacade.java:44)
	at com.example.user.management.api.logic.UserFacade_Subclass.createUser$$superforward(Unknown Source)
	at com.example.user.management.api.logic.UserFacade_Subclass$$function$$36.apply(Unknown Source)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
	at com.example.user.management.api.security.propertybased.PropertyBasedPolicyInterceptor.enforcePolicy(PropertyBasedPolicyInterceptor.java:34)
	at com.example.user.management.api.security.propertybased.PropertyBasedPolicyInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
	at com.example.user.management.api.logic.UserFacade_Subclass.createUser(Unknown Source)
	at com.example.user.management.api.logic.UserFacade_ClientProxy.createUser(Unknown Source)
	at com.example.user.management.api.api.UserApiImpl.createUser(UserApiImpl.java:27)
	at com.example.user.management.api.api.UserApiImpl_Subclass.createUser$$superforward(Unknown Source)
	at com.example.user.management.api.api.UserApiImpl_Subclass$$function$$26.apply(Unknown Source)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
	at io.quarkus.hibernate.validator.runtime.interceptor.AbstractMethodValidationInterceptor.validateMethodInvocation(AbstractMethodValidationInterceptor.java:71)
	at io.quarkus.hibernate.validator.runtime.jaxrs.JaxrsEndPointValidationInterceptor.validateMethodInvocation(JaxrsEndPointValidationInterceptor.java:38)
	at io.quarkus.hibernate.validator.runtime.jaxrs.JaxrsEndPointValidationInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
	at com.example.user.management.api.api.UserApiImpl_Subclass.createUser(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:154)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:118)
	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:560)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:452)
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:413)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:415)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:378)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:356)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:70)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:429)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:240)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:154)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:157)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:229)
	at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:82)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:147)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:93)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:829)
	Suppressed: java.io.IOException: Incomplete document
		at com.google.gson.stream.JsonWriter.close(JsonWriter.java:610)
		at com.microsoft.kiota.serialization.JsonSerializationWriter.close(JsonSerializationWriter.java:441)
		at com.microsoft.kiota.RequestInformation.setContentFromParsable(RequestInformation.java:327)
		... 61 more

Configuration

No response

Other information

No response

@andrueastman
Copy link
Member

Thanks for raising this @cascer1

Looks like the serializer may not be able to serialize the JsonObject type. Any chance you can confirm if the following workaround works out for you?

            CustomSecurityAttributeValue attributeValue = new CustomSecurityAttributeValue();
            HashMap<String, Object> additionalData = new HashMap<>();
            var additionalUserProperties = new UntypedObject(
                    new HashMap<>() {
                        {
                            put("@odata.type", new UntypedString("#Microsoft.DirectoryServices.CustomSecurityAttributeValue"));
                            put("organizationIds", new UntypedArray(Arrays.asList(new UntypedString("123"),new UntypedString("321"))));
                            put("userType", new UntypedString("basic"));
                        }
                    });
            additionalData.put("UserManagementAPI", additionalUserProperties);
            attributeValue.setAdditionalData(additionalData);
            newUser.setCustomSecurityAttributes(attributeValue);

@andrueastman
Copy link
Member

Created microsoft/kiota-java#1388 to investigate/fix

@andrueastman andrueastman added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed status:waiting-for-triage An issue that is yet to be reviewed or assigned labels Jun 26, 2024
@cascer1
Copy link
Author

cascer1 commented Jun 26, 2024

Hi @andrueastman, thanks a lot for the quick response!

Your provided workaround works perfectly, I'm now able to create users and assign custom security attributes like I expected. Since you've already created a new issue in the underlying library to handle this case, I'll close this one :)

Cheers

@cascer1 cascer1 closed this as completed Jun 26, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot removed the status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close label Jun 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:bug A broken experience
Projects
None yet
Development

No branches or pull requests

2 participants