Adding an existing Kinde user to a new organisation
Hi,
Thanks for a wonderful product. This is more of a generic question that I'm unable to find an answer to. I'm currently building a B2B2C SaaS application and the business admins can add users(clients) to their business so that they can login to the business dashboard.
What I have noticed is that if a user already exists in Kinde, and I want to try to add a user from the organization, I get a "Email already in use" error. (Example a user is already a client with one business and is becoming a client in another business).
What is the best way to deal with this scenario ? Do I have to write a custom logic to check if the user exists in Kinde. If yes, add the user to the organisation. If not, then create an user and then add them to the organisation ?
Or is there a way where Kinde as a platform can do this check ? Check if user exists in pool, add to org if yes. Or create a new user and add to org ?
Thanks.
50 Replies
Adding on to this, when a user is added by a business, is there a way to send user invitation emails from Kinde or is this an additional workflow that we have to build ?
Hey there Maxom,
I'm confident this is something that can be done - but HOW it can be done might depend on a few things. Can you tell us what SDK / framework you are using, how your B2B's are set up in terms of auth (e.g. are they SAML, SSO, Passwordless, etc.). How do you onboard businesses? Do they bring their own SSO or do you supply the auth via Kinde?
On the other question, there is currently no email invitation OOTB, but you can use webhooks to trigger a third party application (like mailchimp) to send one when a user signs up. We also have a feature called workflows (just finishing the beta) about to release that will be able to do this as well. Here's some links to docs.
https://docs.kinde.com/integrate/webhooks/about-webhooks/
https://kinde.notion.site/Beta-Workflows-docs-137d97b0d20580269a53f42525252087 You might find the #Kinde-AI channel useful as well, where you can query the docs. Or ask more here in the support channel 🙂
On the other question, there is currently no email invitation OOTB, but you can use webhooks to trigger a third party application (like mailchimp) to send one when a user signs up. We also have a feature called workflows (just finishing the beta) about to release that will be able to do this as well. Here's some links to docs.
https://docs.kinde.com/integrate/webhooks/about-webhooks/
https://kinde.notion.site/Beta-Workflows-docs-137d97b0d20580269a53f42525252087 You might find the #Kinde-AI channel useful as well, where you can query the docs. Or ask more here in the support channel 🙂
Hi Claire, I'm using the React SDK with React19. I have done a force install for now as the Kinde React SDK does not have React 19 as its dependencies.
Auth is handled completely by Kinde. For now, businesses can join the platform by signing up with email password or google. Once logged in, I check if an org_code exists in the access token. If it does not exist, then I trigger an onboarding flow to capture additional details and call the Kinde Management API's to create a new org, add this user to the org and assign the user an "owner" role.
After onboarding, they can setup their business in the app dashboard, invite users, grant permissions to the users etc.
So when testing invite users. I was testing a scenario where there are 2 businesses A, B. A user is a member/client of business A so this user's email already exists in Kinde. If the user wants to use the same email with business B, then I get the email errors.
As this is a B2B2C app, the business B does not have to know if the user is already a part of my platform with another business. My question is around can Kinde handle this as a built in functionality or do I have to write some logic to achieve this ?
Thanks a lot for the additional info and the description of the flow. I'll need to consult our react dev to see if there's a way to handle this for you. It is a common scenario for B2B2C to need this, so I'll see what they say and get back to you. Perhaps someone in the community sees this and has overcome a similar issue.
Actually I think it might be a matter of passing the org code in the sign up flow. So if your business customers send invitations that pass the org code in the token, they should be able to add the user without issue. Here's the React function https://docs.kinde.com/developer-tools/sdks/frontend/react-sdk/#sign-upsign-in-users-to-organizations
Also we are about to release the new React SDK - it is in final testing.
So essentially we need to build an external flow where a business adds a user, we send an invitation to login with any email but the login() method should have the org code in it. So when the user tries to login, then they automatically get added into the org ?
When I try adding a user from the Kinde Management console, Home > Organizations > Business > Users > Add User. Fill in the email and select the organization, then save. I get the same error. So this will not work from the Kinde UI.
This is my sandbox:

Any ETA on this ? We are currently still developing the application and intending to launch in a month for private beta. Hoping to get this update and still have some time to do proper testing before we release. For now I have force installed the the React SDK which is causing conflicts and the functionality seems to work for a majority of things apart from a few (either the functionality does not work or I am unable to find proper information on how to get it to work)
Example: https://discord.com/channels/1070212618549219328/1343107436780851281
We are hoping this week for React.
Thanks Claire
Hi maxom
Here's the new React package! https://github.com/kinde-oss/kinde-auth-react/releases/tag/5.0.0
Hi Claire, does this updated package address the issue here ? https://discord.com/channels/1070212618549219328/1343107436780851281
Currently passing in the org_code to the login() method explicitly solves the issue but I believe if we have refreshed the user claims and invalidated caches in the backend using the Kinde Management API's, on page reload, new access tokens should be generated to give context about organizations, roles, permissions etc
Or how to handle scenarios where a user is logged in but the admin has changed their permissions, how to get the updated permissions reflected in user’s token
Another dev is going to reply about the org code issue. On the React, I don't know if it solves another user's specific issue. They will need to try it and see. I know a lot of work was done on refresh issues, though.
Hey maxom, have you tried going to the user and then clicking the checkboxes under organizations - that should add users to the org
User details => Edit organizations
Hi Peter, it works if I assign an organization from the user but it does not work if I try to assign user from the organization
For my current use case B2B2C model, I need to have the capability to add users from the organization
And it seems this functionality does not work with Kinde
Not from the console
I have even tried using the management API
And still the same error
My payload for the Create User API looks like this and I'm providing the org_code as a part of the API body:
And when I hit the Kinde management API with the above body, which is a valid one based on https://docs.kinde.com/kinde-apis/management/#tag/users/post/api/v1/user, I get the error:
So for any request, I need to first check if the user already exists in the Kinde global pool and if they do not exist, then create user or if they exists add user to organization ?
Adding on top of this, your Get User Kinde Management API requires the userid in "kp_xxx" format. This is a required parameter. So how would I even check if the user exists based on email id when I do not know their user_id ?
It feels like I need to add a custom db component which stores the email -> userid mapping and then use this db to query the user id first, then use this user id to call Get User to see if they exist or not. If they exist make an API call to add user to org, else make API call to create user.
All this seems super confusing. Kinde advertises B2B2C auth can be handled with Kinde: https://docs.kinde.com/build/set-up-options/kinde-business-model/#you-provide-services-to-companies-and-their-customers-b2b2c
So how can I achieve this ?
Kinde docs
Kinde for different business models
Our developer tools provide everything you need to get started with Kinde.
Kinde docs
Kinde Management API
The management API is for managing your Kinde account. Most things that can be done via the Kinde admin UI can be done with this API
Hi Claire, that is also a thread raised by me. All of these issues kind of seem interlinked with each other
Hi Maxom. I think that you are expecting Kinde to treat organizations like empty buckets that you put users in. Kinde does not work this way. Users are added to Kinde and can exist in multiple organizations. Identities are managed at the top level, not per org. That's why you are getting an error when you try to add an existing user.
We do this so that we can support multiple models where a user might be a buyer or a selller (in a marketplace for example).
And might also be part of a business, as well as a user of a nother business.
For your case, once a user is added, and you want them to belong to other organizations, you just add them to that organization. Can you explain a bit more fully what the end goal is? Do you just want your business customers (orgs) to be able to add users? Well they can, if they pass the org code with the sign in and if a user exists they will be added to the oirg, if they do not exist, they will be added to Kinde and the org.
In addition, how are users being added? Via API, self-sign-up? Manually added?
How do you want your business customers to add users?
Hey Maxom, wanted to also ask how you're using React 19 - are you creating the app from scratch or working with a framework (next.js / react-router)?
Hi @CB_Kinde , thanks for your response. To give you a bit more context, I’m building a club management SaaS applications.
The idea is various clubs can signup to my application and each club can manage their own members, post events, timetables etc. Members can login to my portal. If they are associated with one club, they’ll view the club specific information directly. If the member is associated with more than one club, then they can choose which club they want to login to (built in Kinde org chooser UI) and they’ll be logged into that club.
Now, as each club can add their own members, I want to provide the club owners a functionality to add users to their club. They will click a add member button in my UI with all the details which will interact with my backend API. My backend API interacts with the Kinde management API.
Now a member or a user can be a member of multiple clubs who are all using my application for their club management.
If a member joins a club say A which uses my software, the user does not exist in Kinde yet. With the create user management API call, I can successfully create the user in Kinde and add the user to the org and send email to the member.
Now say the same user is wants to join another club B with the same email and B also uses my software. How do I add them to this new org ? If I use the create user API with the org code, it throws the error as provided above.
Members are added into my application by the clubs. Member cannot join a club directly. If someone tries to sign up from my application, they’ll be treated as a club owner
Me as an application does not manage users. Logically, it is like each club is its own tenant and each tenant can have its own users
And a user can be a part of one or more orgs and due to security I cannot show a club if the user has previously signed up or used the same email with another org
Hope that explains my use case
It is a pure React (Vite) app + Tanstack Router + Kinde for auth
Tech stack is React SPA deployed on S3 with cloudfront for static hosting. There is an API layer in between that interacts with the backend. The entire stack is on AWS
Maxim not sure what endpoint is being hit when a new user request is sent and you get an error, but if your clubs hit this endpoint - https://docs.kinde.com/kinde-apis/management/#tag/organizations/post/api/v1/organizations/{org_code}/users
And passes their org code, this should add the user to the org (and create the record in Kinde if there is not one)
Kinde docs
Kinde Management API
The management API is for managing your Kinde account. Most things that can be done via the Kinde admin UI can be done with this API
@Peteswah can you verify?
Kinde docs
Kinde Management API
The management API is for managing your Kinde account. Most things that can be done via the Kinde admin UI can be done with this API
With the endpoint that you have shared, the assumption is that the user is already created as you have to pass the user_id as the args to the endpoint
User id is a kp_xxxx id
My question is around how do I determine if a user (email) exists in the first place ?
You get user endpoint requires user id which is a kp_xxx id and not an email https://docs.kinde.com/kinde-apis/management/#tag/users/get/api/v1/user
Kinde docs
Kinde Management API
The management API is for managing your Kinde account. Most things that can be done via the Kinde admin UI can be done with this API
Let's wait for Peter
This works well if the user does not previously exist in Kinde. It creates user and adds to org
My bad, you are right.
The issue comes when the user already exist in Kinde
Can you use GET /api/v1/[email protected] to check if a user exists and then if a response includes a user id, use
post/api/v1/organizations/{org_code}/users (user exists, add to org)
And if a user ID is not returned, use post/api/v1/user and include the org code in the request body
Kinde docs
Kinde Management API
The management API is for managing your Kinde account. Most things that can be done via the Kinde admin UI can be done with this API
Id is a required parameter
No, you can use an email I think
I was going through the API spec. I have shared the link. Can you please confirm?
Id is mandatory which is a kp_xxx id according to your API spec
The expand arg: Specify additional data to retrieve. Use "organizations" and/or "identities".
You cannot provide email as an arg to this API
What about using this endpoint GET /api/v1/users
And I could not find any other API to retrieve user details based on email. But looking at the api responses, I believe email is a PK in your database hence it is not allowing duplicate emails for users
I could give this a try but is this the most efficient way to do it ?
It feels it is expensive operation from a compute standpoint
It does what you need it to do - search users and filter by email
Peter may have a better idea. I am out of ideas
I’m also looking at application performance so I’m trying to avoid API’s calls with functionality like select * and then filter. Not sure about your backend implementation but I have noticed that API’s like get users have a higher response time compared to get user
And I have to keep in mind that I need to chain this get users api call with another api call to effectively do what I’m trying to do
Hi @maxom, I'm catching-up on your use-case, let me describe the data model Kinde uses to manage multi-tenancy first.
In Kinde a user has a primary ID, starts with
kp_
, which is unique across your environment.
A user can be associated starting from zero to many identities
which are used for authentication. As an example user A
can have an email identity and a Google social identity associated with them. Both those identities are uniquely identifying the user and cannot be attached to any other users.
Then a user could belong to zero up to many organizations
, which control multi-tenancy and user authorization.
When you are referring to creating a user in the organization, it's more like adding an existing user to an organization.
Ideally, you would have a record of the Kinde user ID in the database, and when inviting you could add that user to a separate organization.
It is possible to filter users by email address via the API, here's the endpoint https://docs.kinde.com/kinde-apis/management/#tag/users/get/api/v1/users
Hi @ev_kinde, as each org is like its own tenant, emails would be the primary mode to add users. My main question was around does Kinde have a built in mechanism is do this checks or do I have to do it manually in my backend logic
And is using the Get users API call the most efficient way to do this ?
As if I go straight to create user with org code, it throws errors
Generally speaking Kinde operates with user ID as a unique identifier, as emails could change and are not very reliable as IDs. When you call the API to create a user and an existing user with the same email identity already exists, you'd get an error back.
Kinde doesn't yet have a hosted user invite flow, it needs to be done via the API at the moment.
Ok thanks for confirming
So just to summarise.
When we click on an add user button in UI and tries to add user with email:
Make the following Kinde API calls:
1. get users with filter on email
2. If user does not exist, create user with org code as an argument
3. If user exists, add user to org
Am I understanding this correctly?
Yes, that's correct, the other option you could record Kinde user IDs in the database and know which user to add to an organization right away without calling the API.
A sidenote, it's possible to directly switch an active user session between organization without re-authenticating or showing the organization switcher, you'd need to provide the
org_code
and if user is already authenticated, Kinde will switch their session and tokens to the new organization (doc https://docs.kinde.com/authenticate/manage-authentication/navigate-between-organizations/)Yup, that was the other thing… I need to ensure my users db table is in sync with Kinde
As I populate my db using webhooks, I’m just afraid there could be scenarios where my db is out of sync sometimes with Kinde as interacting with Kinde is mainly apis and populating my db with users is using webhooks. So that is why I was trying to rely on Kinde apis to do my checks and balances
I’ll probably do a db interaction first and then do kinde api checks as fallback
The access token includes the
sub
claim, which will be the Kinde user ID, you could see an example in the JWT decoder https://kinde.com/tools/online-jwt-decoder/
Our SDKs contain helper methods on getting information from the tokens.Kinde
Online JWT decoder
Leverage this tool to ensure that your JWT has the specific metadata and claims you anticipate or to analyze JWTs generated by a 3rd party.
The access token will also include the currently authorized organization code and the user permissions assigned to the user related to that organization
Sorry I’m a bit confused with this response. How does it relate to the issue in this thread ? The sub in the token would be of the user who is trying to add members right and not of the users we want to add
are you referring to how to login a user to a different org ?
Not really, I'm assuming your application operates based on the email addresses, while Kinde operates based on the unique user IDs. I was referring to the way of getting that user ID.
I think Maxim is looking to grab the user based on an inputted email address
so something like detecting if an email address is already in use
I think in this case you can use https://docs.kinde.com/kinde-apis/management/#tag/search to grab a user via their email if they exist
I think in this case you can use https://docs.kinde.com/kinde-apis/management/#tag/search to grab a user via their email if they exist
I’m still confused by your last couple responses but all good. I understand what I need to do to cater to my scenario.
Thanks you all with the support
This or get users
Then if the user needs to be added to an org you can use this API endpoint https://docs.kinde.com/kinde-apis/management/#tag/organizations/post/api/v1/organizations/{org_code}/users
Yeah, I think with getting users you would then have to search through to see if a user with that email exists, which could be a problem if the number of users gets too large
I think it might be best to go with search on email, which should then return the user id you need to add to the specific org
Thanks Peter