Ionic5/Angular9 Mobile iOS auth0-spa-js Login Flow

I’m attempting to add an auth0 log-in to an ionic/angular cordova based application that is using the auth0-spa-js library with the universal login flow. I’ve read that this process (Authorization Code + PKCE) is clunky on mobile. It doesn’t help that I’m very new to mobile development.

For context, I was able to create a successful browser based SPA implementation. For local testing in the browser, I use a http://localhost:8100 redirect_uri when instantiating createAuth0Client . The lock widget loads, I can authenticate successfully and then be redirected to my homepage http://localhost:8100/home .

When I attempt to complete a similar workflow in a mobile implementation, the workflow breaks down. I am using redirect_uri of: <bundle_id>://<app_name>.us.auth0.com/cordova/<bundle_id>/callback (bundle ID from config.xml). For iOS, I open the app and my landing page shows up with a button to log-in. Pressing that button opens a browser to log-in. I enter my credentials and then get redirected back to the app, but I am stuck on the landing page. Trying to log-in again results in safari opening again with a pop-up stating “Open in {App Name}?” Checking the auth0 logs, it shows a successful log-in event from mobile. I believe I am generating a valid session, I just don’t know how to get my app to navigate through to actual pages. These are my main auth functions:

// Create an observable of Auth0 instance of client
auth0Client$ = (from(
  createAuth0Client({
    domain: AUTH.AUTH0_DOMAIN,
    client_id: AUTH.AUTH0_CLIENT_ID,
    redirect_uri: AUTH.AUTH0_REDIRECT_URI,
    audience: AUTH.AUTH0_AUDIENCE_ID,
    responseType: 'token id_token',
    scope: 'openid profile email',
    cacheLocation: 'localstorage',
    useRefreshTokens: true
  })
) as Observable<Auth0Client>).pipe(
  shareReplay(1), // Every subscription receives the same shared value
  catchError(err => throwError(err))
);
login(redirectPath: string = '/home') {
  // A desired redirect path can be passed to login method
  // Ensure Auth0 client instance exists
  this.auth0Client$.subscribe((client: Auth0Client) => {
    // Call method to log in
    client.loginWithRedirect({
      redirect_uri: AUTH.AUTH0_REDIRECT_URI,
      appState: { target: redirectPath }
    });
  });
}

Upon further searching, I found this post which sounds similar to my issues: Timeouts when trying to create auth client after initial authentication? · Issue #583 · auth0/auth0-spa-js · GitHub

Questions:

  1. What should I be using as the proper redirect_uri? Do I need to do I need to add that redirect_uri to the origin in the Auth0 settings?
  2. How do I get the app to navigate to the home page? Do I need to provide some sort of deep link as the redirectPath ?
  3. BONUS : Is there an easy way to configure a native flow vs browser flow? I know the browser flow is considered safer, I am just curious.

Thanks in advance.

I originally posted this on stackoverflow: angular - Ionic5/Angular9 Mobile iOS auth0-spa-js Login Flow - Stack Overflow

Hi, from what I gather you are having problems redirecting back to the app after the login?
Are you using the auth0-js API to do the redirect?

The app login flow redirect is handled by the auth0-cordova plugin which depends on the SafariViewController plugin and custom-url-scheme plugin. Note this is for mobile.

What this flow is the following. (Assuming not logged in.)

  1. Your app opens.
  2. Your auth0-cordova and auth0-js is initialized with base configs. (auth0-cordova uses the auth0-js underneath, will expand on this below)
  3. You hit login button.
  4. After the login screen is loaded(maybe before not 100% sure), the PKCE flow happens and creates the code challenge and it’s signature. Your other config like audience and redirect ui (the one goes back to the app) is used.
  5. You enter username and password and hit send. This is when the auth0-js library is used. The oauth/token endpoint is hit on the auth0 domain you set as a base config. A token session is created.
  6. If step 5 fails then you stay on the web login screen. Else you close the spawned web browser via SafariViewController or WebView plugin. Then you will be redirected back to your app via your bundle/ app Id callback that you set, with the token information.
  7. Then you should be logged in and your app should have the token.

This is based on my research of the library and the setup which may not 100% correct.

Note:
auth0-js will not follow the authorization response_type=code. This means that you will not get a refresh_token because it follows the implict flow.

It sounds like you are have problems between step 5 and 6, correct?

Thanks for the response mohammadz -

I am actually using the auth0-spa-js library found here: GitHub - auth0/auth0-spa-js: Auth0 authentication for Single Page Applications (SPA) with PKCE

My app will get through step 6 which you laid out below. I can create an active session with auth0 after logging in via the in-app browser. I can verify this in the auth0 logs. The issue I’m having is with step 7 - I am redirected back to the app, but I can’t navigate to the redirectPath /home. I’m stuck on the main page with the original log-in button.

I think the issue is in the way the callback is handled. It seems the library is using the wrong URL, so that the redirect fails. I am piecing this together from this post: Timeouts when trying to create auth client after initial authentication? · Issue #583 · auth0/auth0-spa-js · GitHub

I believe I need to adjust my callback handler and somehow include the origin as part of the redirect. As I (very roughly) understand it, auth0 requires <bundle_id>://<app_name>.us.auth0.com/cordova/<bundle_id>/callback as the allowed callback, but the origin is actually ionic://localhost (on iOS). In other words, <bundle_id>://<app_name>.us.auth0.com/cordova/<bundle_id>/callback/home doesn’t exist but ionic://localhost/home would. The problem is, the library isn’t aware of ionic://localhost. There may be other issues that I’m not aware of, but this seems like a starting point.

Am I understanding this correctly or am I completely off the mark? I’m not sure exactly how I fix this, but I feel as though I could rig something to work if I actually understand the issue.

Ok I see.

So do you get redirected back to the app with the session token in the ionic app(js/ts)? Can you access that? It should be similar to

   {   
       accessToken:"",
       expiresIn:"",
       idToken: "",
       scope: "openid profile",
       tokenType: "Bearer" 
    }

In general whether it’s ios or android, there is something called deeplinking where if you want to use another app from your you would need to use the <bundle_id> to open. This is in the OS level. For example, I could open the outlook app using ms-outlook://compose?to=john@example.com, this would start an email composition UI with the “to” address as john@example.com.

ionic://localhost is just custom url scheme that ionic uses explained here. It is it’s own world and level scope. You can change this link from within your app by using the angular Router module. You can conditionally do logic if you have the token inside your app to show authenticated pages, make guest app experiences and etc…