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

UserApi.getUser throws ClassCastException under specific order of operation

Open khloke opened this issue 10 months ago • 5 comments

Describe the bug?

Calling UserApi.getUser(), updateUser() then getUser() on the same ID in that order would throw the following:

java.lang.ClassCastException: class com.okta.sdk.resource.model.User cannot be cast to class com.okta.sdk.resource.model.UserGetSingleton (com.okta.sdk.resource.model.User and com.okta.sdk.resource.model.UserGetSingleton are in unnamed module of loader 'app')

What is expected to happen?

A UserGetSingleton object of the given id would be returned with no exceptions.

What is the actual behavior?

ClassCastException was thrown instead.

Reproduction Steps?

This can be reproduced with the following code:

        String orgUrl = "https://example.okta.com";
        String clientId = "your-client-id";
        String authMode = "SSWS";
        String oktaApiToken = "your-okta-api-token";
        String scopes = "okta.users.read,okta.users.manage";
        String userIdForTesting = "00u9cc7qgvRPapIQG0x7"; //Any valid user ID will work

        ApiClient apiClient = Clients.builder()
                                     .setOrgUrl(orgUrl)
                                     .setAuthorizationMode(AuthorizationMode.valueOf(authMode))
                                     .setClientId(clientId)
                                     .setClientCredentials(new TokenClientCredentials(oktaApiToken))
                                     .setScopes(Set.of(scopes.split(",")))
                                     .build();
        UserApi userApi = new UserApi(apiClient);

        userApi.getUser(userIdForTesting, null, null);
        User updatedUser = userApi.updateUser(userIdForTesting, new UpdateUserRequest(), false);
        UserGetSingleton user = userApi.getUser(userIdForTesting, null, null);

Additional Information?

This is caused by the cache in ApiClient storing a User.class object in the cache (code) during a updateUser() operation, and when getUser() is called for the same user, the cacheKey matches but expects a UserGetSingleton.class object instead and attempts to cast it as such (code). A ClassCastException is thrown because of this.

Java Version

openjdk 21.0.6 2025-01-21
OpenJDK Runtime Environment Homebrew (build 21.0.6)
OpenJDK 64-Bit Server VM Homebrew (build 21.0.6, mixed mode, sharing)

SDK Version

First seen in 20.0.1. Tested and still happening in 21.0.0.

OS version

Darwin HongL 24.3.0 Darwin Kernel Version 24.3.0: Thu Jan  2 20:24:24 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T6030 arm64

khloke avatar Apr 03 '25 13:04 khloke

HI @khloke, thanks for reporting this. I will be taking a look at it and getting back.

prachi-okta avatar Apr 03 '25 16:04 prachi-okta

I'm also see this issue.

Is there a workaround for this?

jimjonah avatar Apr 08 '25 21:04 jimjonah

I'm also see this issue.

Is there a workaround for this?

The way it is written I couldn't find a workaround. I reverted back to v13 of the SDK.

khloke avatar Apr 11 '25 04:04 khloke

I ended up using this. Previous versions of the SDK broke other things for us.

final var userList = oktaUserApi.listUsers( null, // contentType null, // q (search query) null, // after (pagination) null, // limit "id eq "" + oktaUserId + """, // filter null, // search null, // sortBy null // sortOrder );

// Get the first (and should be only) user from the list
return userList.isEmpty() ? null : userList.get(0);

jimjonah avatar Apr 12 '25 18:04 jimjonah

@prachi-okta Where is the fix? This was reported months ago. It is still a problem today in latest SDK version.

shaunlefeuvre avatar Sep 04 '25 15:09 shaunlefeuvre