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

Supporting multiple domains in the SDK #747

Closed
6 tasks done
chrisbruford opened this issue Oct 2, 2023 · 11 comments
Closed
6 tasks done

Supporting multiple domains in the SDK #747

chrisbruford opened this issue Oct 2, 2023 · 11 comments
Labels
feature request A feature has been asked for or suggested by the community

Comments

@chrisbruford
Copy link

Checklist

Description

Create a new Auth0Provider with a different domain prop still results in directing users to the initial domain when using the authorize method provided by useAuth0 hook.

Worked on 2.17.4

Reproduction

  1. Initialise the Auth0Provider with any valid domain prop
  2. Initialise a new Auth0Provider with a new valid domain prop
  3. Observe that the login function provided by useAuth0 still directs the browser to the initial domain

Additional context

We use multiple Auth0 Tenants to isolate users from different customers and in our React Native app we allow the user to select which customer they are from and thus we dynamically change the domain being sent to the Auth0 SDK.

This worked well up until we upgraded to v3 and now it fails to change the domain. I have traced it through the auth0 SDK and found the domain change is successfully being propogated all the way to the NativeModule import; but the SDK still directs the browser window to the previously set domain. Seems like the domain gets cached somewhere (perhaps the useAuth0 hook using the old object?)

I understand that Organisations is the recommended approach to this use case now; but the use of auth0 tenenants is still listed as a supported method - and thus I believe this change to be a bug.

Note: this has already been asked on the forums but no answer has been given for over a year

react-native-auth0 version

3.0.1

React Native version

0.72.5

Expo version

49.0.0

Platform

Android

Platform version(s)

13

@chrisbruford chrisbruford added the bug This points to a verified bug in the code label Oct 2, 2023
@poovamraj
Copy link
Contributor

@chrisbruford This can be achieved by using 2 instances of auth0 class instance rather than hooks which can be initialized like this

import Auth0 from 'react-native-auth0';

const auth0 = new Auth0({
  domain: 'YOUR_AUTH0_DOMAIN',
  clientId: 'YOUR_AUTH0_CLIENT_ID',
});

However using you have to be careful using the credentials manager as we can store only 1 access token and using both the instances alternatively will definitely result in an error.

So i'd suggest limiting this use case just for authentication purpose and not credentials management.

@poovamraj poovamraj added question and removed bug This points to a verified bug in the code labels Oct 6, 2023
@chrisbruford
Copy link
Author

@poovamraj does the fact that this behaviour is not consistent across iOS and Android (as this only happens on Android) not constitute this being a bug? it seems odd to me that the "solution" is to not use the hooks functionality...that seems more like a workaround to achieve the same behaviour on Android as we already get for free on iOS...and as you pointed out, has undocumented pitfalls to doing so?

@chrisbruford
Copy link
Author

@poovamraj I tried your approach which ended up looking like this:

const auth0 = useMemo(() => {
  if (!workspace) return;
  return new Auth0({
    domain: workspace?.variables.AUTH0_DOMAIN,
    clientId: workspace?.variables.AUTH0_CLIENT_ID,
  });
}, [workspace]);

I then tried to login like this:

console.log({ domain: auth0?.auth.domain });
auth0?.webAuth
  .authorize({
    audience: workspace?.variables.AUTH0_AUDIENCE || 'https://inbanx/api',
  })
  .then((credentials) => {
     ...
  })

The console.log shows me the domain has changed, but the call to authorize still directs me to the domain for the first workspace, regardless.

As I mentioned in my earlier comment, this doesn't behave like this on iOS even when using hooks.

@poovamraj
Copy link
Contributor

@chrisbruford You are right! As you mentioned we only have 1 instance of Auth0 object in the native module. We have a hasValidAuth0Instance check that will avoid initializeAuth0 if there is already an existing instance.

I have to check why the iOS native module is not performing this check properly as it would mean creating a new instance of the SDK each time a web authentication or credentials management call is made.

The proper way to support this would be is to have a list of auth0 instances in the native module and use the right one depending on the client id making the request. Or we should provide a method to invalidate the existing instance of Auth0 client.

@poovamraj poovamraj added feature request A feature has been asked for or suggested by the community and removed question labels Nov 6, 2023
@poovamraj poovamraj changed the title Unable to create a new Auth0Provider with a different domain Supporting multiple domains in the SDK Nov 6, 2023
@mrbrentkelly
Copy link

On a similar note it would be good if the hasValidAuth0Instance was smart enough to realise that the domain/clientID has changed and allow the initializeAuth0 to be made. Our App only has a single Auth0Provider at a time but before logging in you can switch from a production environment to a dev environment. This used to work fine in older versions of react-native-auth0 but now we're having to restart the entire App when there's an environment change.

@tjensen
Copy link

tjensen commented May 8, 2024

I am also encountering this issue after upgrading from 2.x to 3.x. I used to be able to switch domain/clientId without having to restart the app and now, with 3.x, the app fails to authorize the user because the wrong domain/clientId is being used after creating a new instance of the default exported class.

@mrbrentkelly
Copy link

If it's of interest to others, we've been able to workaround this behavior by calling the underlying initializeAuth0 function when the clientID and/or domain changes...

  useEffect(() => {
    // There is a "feature" in the react-native-auth0 library where it will only initialize the native
    // layer once with the first clientID and domain it is given. Any changes to these values will have
    // no impact until the app is restarted.
    // See https://github.com/auth0/react-native-auth0/issues/747#issuecomment-1791128894
    //
    // This code works around that by calling the initializeAuth0 native function ourselves when the
    // clientID or domain changes
    NativeModules.A0Auth0.initializeAuth0(clientID, domain);
  }, [clientID, domain]);

@brth31
Copy link

brth31 commented May 28, 2024

thanks for sharing a workaround, @mrbrentkelly!

We are planning to address this issue along with other improvements in the next major release coming up this quarter. I'll share exact timelines by the mid of June.

@desusai7
Copy link
Contributor

Hi everyone,

We've fixed this issue as part of version 4.0.0-beta.0 and more details about it can be found here

Closing this issue for now, feel free to re-open it, if you run into any issues

@adammcarth
Copy link

adammcarth commented Oct 23, 2024

Hi @desusai7 et al,

I have installed 4.0.0-beta.0 to test if the issue has been resolved, and whilst iOS is working perfectly, I am still facing some issues on Android.

As per the V4 documentation, here is the value of my android/app/build.gradle:

android {
  defaultConfig {
    // Is this holding back multiple domain support on android? Can I add multiple here somehow?
    manifestPlaceholders = [auth0Domain: "tenant1.auth0.com", auth0Scheme: "${applicationId}.auth0"]
  }
}

Then, similar to @chrisbruford, in our JavaScript code we dynamically switch the Domain & Client ID based on a user's selection during the login process:

import Auth0 from 'react-native-auth0';

const doAuthorization = async (domain: string, clientId: string): Promise<void> => {
  const auth0 = new Auth0({ domain, clientId });
  await auth0.webAuth.authorize({});
};

Whenever we call doAuthorization with "tenant1.auth0.com", we see that the login works. However, whenever it is called with any other valid domain (not present in android/app/build.gradle), the CORRECT web URL opens in a browser, but upon authenticating successfully it just hangs in the in-app-browser and never redirects back into our app.

So it seems like we're getting closer now that that correct domain opens up for authentication, but on Android it still doesn't appear to allow you to sign in. Any ideas or suggestions @desusai7?

  • React Native Version: 0.73.9
  • Android: 14

@adammcarth
Copy link

Oh okay, I have found a solution to the above issue. It is documented in the pull request referenced above (#931).

In addition to implementing version 4.0.0-beta.0 of this library, I also had to modify my android/app/src/main/AndroidManifest.xml file to add the following:

  <manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
+   xmlns:tools="http://schemas.android.com/tools">
    <application ...>
      <activity
        android:name=".MainActivity" ...>
        ...
      </activity>
+     <activity
+       android:name="com.auth0.android.provider.RedirectActivity"
+       tools:node="replace"
+       android:exported="true">
+       <intent-filter>
+         <action android:name="android.intent.action.VIEW" />
+         <category android:name="android.intent.category.DEFAULT" />
+         <category android:name="android.intent.category.BROWSABLE" />
+         <data
+           android:host="tenant1.auth0.com"
+           android:pathPrefix="/android/${applicationId}/callback"
+           android:scheme="${applicationId}.auth0" />
+         <data
+           android:host="tenant2.auth0.com"
+           android:pathPrefix="/android/${applicationId}/callback"
+           android:scheme="${applicationId}.auth0" />
+       </intent-filter>
+     </activity>
    </application>
  </manifest>

I also removed the manifestPlaceholders option from my android/app/build.gradle file:

  android {
    defaultConfig {
-     manifestPlaceholders = [auth0Domain: "tenant1.auth0.com", auth0Scheme: "${applicationId}.auth0"]
    }
  }

Following the above steps, I was able to get our dynamic login across multiple tenants working again.

May I suggest putting this inside the installation documentation for your stable V4 release @desusai7, as it was quite confusing to implement given the differences to the latest installation instructions for Android.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request A feature has been asked for or suggested by the community
Projects
None yet
Development

No branches or pull requests

7 participants