kinde-oss / kinde-typescript-sdk

Kinde SDK for TypeScript
https://docs.kinde.com/developer-tools/sdks/backend/typescript-sdk/
MIT License
32 stars 11 forks source link

Bug: unable to reload users information when reassigning organizations #63

Open drochag opened 2 months ago

drochag commented 2 months ago

Prerequisites

Describe the issue

While reassigning an organization for a logged in user we're unable to see the user as part of the newly created organization in any way.

Tried out using refreshTokens on getKindeServerSession from @kinde-oss/kinde-auth-nextjs/server and also refreshUserClaims from UsersApi on @kinde-oss/kinde-typescript-sdk (although the last one not sure could help on reloading the current user information).

Steps to reproduce:

Reproduction repo / PR here

Library URL

https://github.com/kinde-oss/kinde-auth-nextjs and @kinde-oss/kinde-typescript-sdk

Library version

2.3.8 and 2.9.1

Operating system(s)

macOS

Operating system version(s)

Sonoma 14.6

Further environment details

No response

Reproducible test case URL

https://github.com/drochag/kinde-nextjs-app-router-starter-kit/pull/1

Additional information

No response

dxptqhtlutehvlyxcmtg commented 2 months ago

We're seeing this too with @kinde-oss/kinde-typescript-sdk. For new users, in our auth callback request handler we're removing the user from the default org and placing them in a newly created one.

A query to the Management API shows the new org state, but, querying the user's orgs via the session attached to the request still shows the user assigned only to the default org. Here's some more or less psuedo-code to illustrate. See the very last call to getUserOrganizations to see the issue:

async function processRegisterCallback(request) {
  const DEFAULT_ORG_CODE = 'org_111111111111';

  // Get Management API access token
  const managementAccessToken = await createKindeServerClient(
    GrantType.CLIENT_CREDENTIALS,
    {
      // '...'
    },
  ).getToken(getSessionManager('admin-session'));

  const orgApiClient = new OrganizationsApi(
    new Configuration({
      accessToken: managementAccessToken,
      // ...
    }),
  );

  // Make session manager for current request
  const sessionManager = makeSessionManager(
    request.headers.get('Cookie').get('session_id'),
  );

  const kindeClient = createKindeServerClient(
    GrantType.AUTHORIZATION_CODE,
    {
      // '...'
    }
  );

  /*
    see newly created user from registering

    console.log:
    {
      user: {
        family_name: '...',
        given_name: '...',
        picture: '...',
        email: '...',
        id: 'kp_00000000000000000000000000000000'
      }
    }
  */
  const user = await kindeClient.getUser(sessionManager);

  /*
    User is in default org by default

    console.log:
    { orgCodes: [ 'org_111111111111' ] }
  */
  await kindeClient.getUserOrganizations(sessionManager);

  /*
    Create a new org via Management API

  {
    message: 'Success',
    code: 'OK',
    organization: { code: 'org_222222222222' }
  }
  */
  const createOrgResponse = await orgApiClient.createOrganization({
    createOrganizationRequest: {
      name: 'New Org',
    },
  });

  /*
    Add user to the new org

    {
      code: 'OK',
      message: 'Users successfully added',
      usersAdded: [ 'kp_00000000000000000000000000000000' ]
    }
  */
  await orgApiClient.addOrganizationUsers({
    orgCode: createOrgResponse.organization.code,
    addOrganizationUsersRequest: {
      users: [
        {
          id: user.id,
        },
      ],
    },
  });

  /*
    Remove user from our default org_111111111111

    { 
      message: 'User successfully removed', 
      code: 'OK' 
    }
  */
  await orgApiClient.removeOrganizationUser({
    orgCode: DEFAULT_ORG_CODE,
    userId: user.id,
  });

  /*
    Get user data via Management API, it correctly shows
    new org org_222222222222 is now assigned and user is no
    longer in default org org_111111111111

    {
      id: 'kp_00000000000000000000000000000000',
      providedId: undefined,
      preferredEmail: '...',
      username: undefined,
      lastName: '...',
      firstName: '...',
      isSuspended: false,
      picture: '...',
      totalSignIns: 1,
      failedSignIns: 0,
      lastSignedIn: '...',
      createdOn: '...',
      organizations: [ 'org_222222222222' ],
      identities: undefined
    }
  */
  const usersApiClient = new UsersApi(
    new Configuration({
      accessToken: managementAccessToken,
      // ...
    }),
  );

  await usersApiClient.getUserData({ id: user.id, expand: 'organizations' });

  /*
    Read user orgs via request session

    This is wrong, it should be org_222222222222

    { 
      orgCodes: [ 'org_111111111111' ] 
    }
  */
  await kindeClient.getUserOrganizations(sessionManager);
}
coel commented 1 month ago

@drochag, thank you for providing the code example. I believe a recent server fix has addressed this. Using the example code I am able to get the updated list of organizations after adding await to await currentSession.refreshTokens().

@dxptqhtlutehvlyxcmtg, to get the new details, a call will need to be made to refreshTokens() first to retrieve a token with the updated values.

drochag commented 1 month ago

Thanks for the update @coel

I updated the PR with the needed await, however this isn't working correctly either

Screenshot 2024-10-04 at 6 25 14 p m

did two clips to hide my google accounts WALi is my default org

https://github.com/user-attachments/assets/f1482e76-83f5-47fb-80b2-eb40c199b865

-- deleted part.2.mov --

you can see the client organization is correct, although being correct after reloading the page, not after refreshing the token the server organization is wrong

coel commented 1 month ago

@drochag, I've deleted the second video as the preview frame still showed your email addresses. I'll have a closer look at this today.

dxptqhtlutehvlyxcmtg commented 1 month ago

@coel Calling refreshTokens seems to fix the issue for us, thanks. However, I'm having trouble locating any references for that method. Could you please point to where it is documented?

coel commented 1 month ago

@drochag, I've raised a PR that may help with the server listing of organizations: https://github.com/kinde-oss/kinde-auth-nextjs/pull/217

For the client listing, there is a function refreshData returned from useKindeBrowserClient that needs to be called for it to retrieve the updated data.

@dxptqhtlutehvlyxcmtg, I can't seem to locate the documentation myself, I will look into it further. The only thing I have found is this video tutorial we released https://www.youtube.com/watch?v=7eLs7OOSH80

coel commented 1 month ago

@drochag , We've released a new version of the Next.js SDK v2.3.11, can you try this version and see if your server listing now displays?

Just to note, assigning an organization to a user will add the organization to the list of available organizations for that user, but it won't change the organization currently logged into. The active organization can be switched by initiating login again, but with the organization code passed through.

Some relevant documentation: https://docs.kinde.com/authenticate/manage-authentication/navigate-between-organizations/