User switch between Organization

Auth0 Organization fits perfect for my use case. However, after going through the docs on Organization, and looked at the implementation here [Authentication services for SaaS companies] . I have a couple questions.

  1. The claims (i.e. role and permission) are specific to the organization that the user auth against, so does that mean when a user switches between organizations, that user needs to sign out and sign back in or auth0 does some silent auth in the background to re-generate the access_token? What’s the recommended way to accomplish a seamless switch between organizations?

  2. In the article, the author uses localStorage to persist the org_id that the user is auth against… without that refresh would kick the user off. Is this a temporary fix or intended to be the implementation (i.e. this functionality will be taken care of by the react-sdk)?

  3. Is there a limit to number of organizations?

2 Likes

Answering some questions that I posed after some digging around for an implentation.

Using the React-sdk, we can use the getAccessTokenSilently from the auth0 hook and pass in organization (similar to the same prop on the Auth0Provider) with the new org_id when a user wants to switch organization.

To do this, we have to pass in the ignoreCache flag when we get the access token (otherwise you’d get the same access token for the same organization.

Drawback is obvious, if a user switches back and forth between organizations, without some caching locally, we are making multiple calls to the API.

2 Likes

Another issue came up is idToken… even we can use the getAccessTokenSilently, we are not re-fetching the idToken… that means when we injected the role to the idToken, when a user switch between organization, they are not getting the new idToken that has the new role.

Work Around aka Hack
use jwt-decode on the front end to decode the token → no need to verify, and just get whatever you need from the access token

1 Like

Talked to a solutions engineer from Auth0, if you’re not on the enterprise plan, the cap of number of organization is 100

1 Like

Thanks for sharing that with the rest of community!

I’m trying to implement something similar in my app. I can’t see an option to pass in organization to getAccessTokenSilently . Not documented either on the API reference: https://auth0.github.io/auth0-react/interfaces/index.gettokensilentlyoptions.html. How did you manage to do this? Unless I’ve completely misunderstood what you meant.

My main issue is if you’re not passing in the organization parameter in the Auth0Provider, the org_id doesn’t appear in the user object. So I’m not sure how I can get a user to login and switch between the tenants they belong to.

1 Like

It’s not in the docs yet, you just have to pass it, and the sdk will append it to the /authorize request. You have to make sure you do ignoreCache: true so it’s not returning the same access token.

You have to make sure the application user is auth against enables organization (it’ll ask if it’s organization only or personal use or both), if your application does not enabled for organization, then when you pass in organization parameter it’ll return an error. Also, if you don’t pass in authorization, the user is authenticating against the general connection, which wouldn’t have the org_id because auth0 wouldn’t know which org upon login.

It looks something like this

      const token = await getAccessTokenSilently({
        organization: auth0OrgId,
        ignoreCache: true,
      })

      const decodedToken: AccessToken = decode(token)
2 Likes

Thanks for sharing it with the rest of community!

Hi Bryan,
Have you tried this? It did not work for me. I have the latest version of Auth0 sdk for react.
@auth0/auth0-react": "^1.5.0

I lose the organization context whenever I reload the page (and thus the roles and permissions of the user specific to an organization) and need a way to retain the organization context on reload. Any help would be much appreciated :slight_smile:

@mherle96 we need to store organization_id in localStorage, and use that field in your auth0 provider. The reason is, auth0 is saving organization related session in memory, and when you refresh your browser, all the stuff is gone… so you need some way to persist the org_id.

Hoping the sdk will be updated and we don’t have to manually do that step in the future.

Relaying that feedback to appropriate team!

This works, Thanks! Saved me a lot of trouble.

2 Likes

Perfect! Glad to hear that!

Is anyone able to get this to work in next.js? I have the org id saved on local storage but the authentication does not persist on refresh. Not sure what I’m doing wrong, it worked perfectly fine when using CRA but maybe next.js is doing something different behind the scenes ? :thinking:

1 Like

Here is another attempt to switch organizations

In my use case when a user has logged in, I list all the organizations the user belongs to, so you can switch organizations via buttons (The button for each organization should call a function that receives the org_id).

You can get all the organizations via management api /api/v2/users/{id}/organizations

As users don’t have the same roles across all organizations, we need to update the session in order to get the new roles, so you can use the loginWithPopup function and pass in the organization you want to switch here’s an example code to do that

const { user, isAuthenticated, isLoading, loginWithPopup } = useAuth0();
  const [organizations, setOrganizations] = useState([]);
  const switchOrganization = async (org_id) => {
    loginWithPopup({
      organization: org_id
    })
  }
  
  useEffect(() => {
    if (isAuthenticated) {
      const sub = user.sub;
      try {
        fetch(`https://YOUR-AUTH0-API/api/v2/users/${sub}/organizations`, {
          method: 'GET',
          headers: {
            'Authorization': 'Bearer YOU CAN GET A TESTING TOKEN FROM A M2M APPLICATION'
          }
        }).then((d) => d.json()).then((d) => {
          setOrganizations(d)
        });
      } catch (error) {

      }
    }
  }, [isAuthenticated, user])

This is to map over organizations state and render the buttons

{
          organizations.length ? organizations.map(o => (
            <button style={{ background: o.branding.colors.primary }} onClick={()=>{
              switchOrganization(o.id)
            }}>
              <img src={o.branding.logo_url} width='25' height='25' alt='' />
              Go to {o.display_name}
            </button>
          )) : null
        }

The user object provided by useAuth will be updated and the new roles will appear, you can console log the user to appreciate the change

Would also love to know if there is a way to easily accomplish this using Next.js.
The next.js auth0 library is very limited in comparison to the auth0-react library. It only has a few functions that can be called.

Trying to figure out if I need to ditch the nextjs library and use the pure react library instead to obtain this functionality.

Using getAccessTokenSilently as described below doesn’t work if you’ve configured the Auth0Client to use refresh tokens (useRefreshTokens: true). Instead, you just get back an access token for the same organization as the last access token.

It looks like using loginWithPopup like jp.olvera mentioned works, but then we have to deal with a popup.

Is there a solution to this that doesn’t involve disabling refresh tokens entirely or using a popup?

I have the exact same problem as @aaron.hardy (ty for the useRefreshTokens hint). I have to disable refresh tokens if I want to switch orgs silently, or have them log in every time they switch, which is a no-go for my use case since there are users in this system who can belong to tens of orgs and need to switch between them all the time. Is there anyone in Auth0 who can confirm that this is a bug?

Update: We need to have useRefreshTokens={true} because otherwise login doesn’t work with Safari as mentioned in this thread: 'Login Required' in Safari in accordance with "Error: Login required" for getAccessTokenSlienlty in `auth0-react` in Safari and Incognito windows.
So basically we have to choose between not being able to log in with Safari or having users log in with UI every time they switch organization.

Hey Eric, you may want to follow this Github issue: Unable to get access token silently for a different organization while refresh tokens are enabled · Issue #1055 · auth0/auth0-spa-js · GitHub

I wasn’t aware of the Safari issue. You may want to mention that in the Github issue.

1 Like