Ionic 2+ authentication without using auth0-cordova

I would like to create a custom-login form for my Ionic 2+ application.
Currently the only recommended way to do that is the use of the auth0 cordova library.

I have to admit, that I’m not at all fan of this solution: I wan’t to use an integrated custom form in my application and I don’t want to use a browser based authentication. The user experience using a browser based authentication is poor, it doesn’t look good and it’s known to cause problems and it’s confusing my users. Also it’s not compatible with native Facebook login, which I wan’t to add later.

Sadly it seems auth0 is trying to make the use of alternative methods as difficult as possible. For example - using auth0.js in Ionic does only work in a very limited way:

   auth0.client.login({
        realm: 'Username-Password-Authentication',
        username,
        password
      }, (err, authResult) => resolve(this.handleAuthenticationResponse(err, authResult)));
    });

Does not return a refresh_token, even if you added “offline_access” to the scope.
auth0.renewAuth most likely does not work, as it’s intended to use a callback (which is most likely not working).

So which options do I have if I wan’t to integrate auth0 into my Ionic app without using auth0-cordova and without having to write everything from scratch to get it done?

Given the underlying protocols being used, OpenID Connect and OAuth2, the use of browser redirect-based mechanisms is almost unavoidable and it’s also the option that will likely result in a more generic implementation; one that can be used in a very similar way with most authentication providers.

However, if you have different requirements then there’s other options depending on your exact scenario. For example, if you use Auth0 to manage users accounts and credentials (aka database connections) then you can directly exchange those credentials at the token endpoint through a resource owner password credentials (ROPC) grant. This means your client application has to directly process user credentials so there may be additional security considerations, but it will allow you complete flexibility in terms of UI. The Auth0.js client.login method does use this grant and I was not able to reproduce the situation you mentioned about not being able to retrieve a refresh token through this method. Can you update your question with the exact configuration you use for Auth0.js and also any client and/or API settings that you think are relevant.

In conclusion, the ROPC grant would allow you total control of the UI for users that have their credentials directly managed by Auth0 although at the extra cost that your client application now has to process user credentials. For external/social authentication providers it would depend on what they support.

For example, some social authentication providers may not support anything else than a browser-based flow; Facebook does seem to have a native SDK that could be used, but others will likely only allow a redirect-based approach.

I’m not seeing the problem either, I am getting the refresh token back using that call. Maybe its your client setup in auth0? Advanced settings has area for grant types that has a setting for refresh grant. Might want to check that is enabled.

I’m with you on the implicit and PKCE flows and redirect, its not a good UX and adds another place to maintain UI (assuming your using auth0). I’ll roll my own identity provider before I use the flows here, likely using IdentityServer4 in .NET.

Hello jmangelo, hello dan.kellett,

sorry for the late reply. That’s weird, the auth0.client never returned a refresh token.
I used the following configuration:

private auth0 = new auth0.WebAuth({
    domain: 'DOMAIN.eu.auth0.com',
    clientID: 'CLIENTID',
    audience: 'https://DOMAIN.eu.auth0.com/userinfo',
    scope: 'openid offline_access profile e-mail',
    device: 'dev app'
  });

I now used the /oauth/ro endpoint to implement authentication:

  public login(username: string, password: string): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      const credentials = {
        client_id: environment.auth0.clientID,
        username: username,
        password: password,
        connection: 'Username-Password-Authentication',
        scope: environment.auth0.scope,
        device: environment.auth0.device
      };

      this.http.post(`https://${environment.auth0.domain}/oauth/ro`, credentials)
        .map(response => response.json())
        .subscribe(
          (authResult) => resolve(this.handleAuthenticationResponse(authResult)),
          (err) => {
            this.apiService.handleAuthError(err);
            reject();
          }
        );
    });
  }

And used the cordova facebook plugin together with /oauth/access_token endpoint for facebook auth:

  public facebookLogin(): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      this.facebook.login('public_profile', 'email'])
        .then((res: FacebookLoginResponse) => {
            const credentials = {
              client_id: environment.auth0.clientID,
              access_token: res.authResponse.accessToken,
              scope: environment.auth0.scope,
              connection: 'facebook',
              device: environment.auth0.device
            };
            this.http.post(`https://${environment.auth0.domain}/oauth/access_token`, credentials)
              .map(response => response.json())
              .subscribe(
                (authResult) => resolve(this.handleAuthenticationResponse(authResult)),
                (err) => {
                  this.apiService.handleAuthError(err);
                  reject();
                }
              );
        })
        .catch(e => {
          console.error('Error logging into Facebook', e);
          reject();
        });
    });
  }
1 Like