Auth Connect

Ionic Auth Connect handles logging in and/or registering a user with an authentication provider (such as Auth0, Azure AD, AWS Cognito, or Okta) using industry standard OAuth/OpenId Connect on iOS, Android, or on the web.

When used with Ionic Identity Vault, it provides a complete security solution for authentication and storage of logged-in credentials.

Auth Connect also allows your app to support multiple authentication providers. Should you need to change providers, easily switch between them without having to develop a new solution. Learn more.

Demo Apps#

We have a demo app available that demonstrates that demonstrates the configuration required for several of the supported OIDC provides. We suggest starting with this demo in order to establish the configuration for your provider. To do this:

  • Update the appropriate configuration in the environment files to match the configuration of your OIDC provider.
  • Update the appHost in the environment files to match the custom scheme you plan on using for your app. We suggest using something based on your bundle ID.
  • Update the AndroidManifest.xml and Info.plist files accordingly (see below where the Capacitor configuration is discussed).
  • The demo app uses callback routes such as msauth://login. If the portion you are using after the protocol differs, update the appropriate service accordingly.

Note: the providers demo covers the "big four" providers. However, if you are using something else you should still be able to use the application as a model to add your own provider by following the same basic pattern or by modifying one of the existing configurations to use something else.

We also have a demo app available that shows the complete login/logout experience using Azure. This demo uses Ionic Identity Vault in order to securely store the tokens returned from Azure.

Both of these demo applications use Capacitor for the native layer. While we suggest using Capacitor in your application as well, the logic contined within the applications themselves remains the same if you are using Cordova.

Installation#

If you have not already setup Ionic Enterprise in your app, follow the one-time setup steps.

Next, install the plugin:

npm install @ionic-enterprise/auth
npx cap sync

Capacitor users will need to manually update the native project config files.

For Android, update the manifest file located at android/app/src/main/AndroidManifest.xml by adding the following intents next to the other intents in the main activity node:

<intent-filter>
<data android:scheme="$AUTH_URL_SCHEME"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/*"/>
</intent-filter>

For iOS, update the file located at ios/App/App/Info.plist by adding the following inside the existing CFBundleURLTypes node:

<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>$AUTH_URL_SCHEME</string>
</array>
</dict>
note

You will need to update the $AUTH_URL_SCHEME placeholder with the bundle id of your app in both files when using Capacitor.

Configuring Auth Connect#

The main entry point into Auth Connect is done via the IonicAuth class. To configure IonicAuth, you pass in a configuration object when creating a new instance of the class.

This is done by passing in an instance of IonicAuthOptions to the IonicAuth class. The IonicAuth class is the main interface exposed by the Auth Connect plugin, and is expected to be subclassed for specific behaviors and/or events.

Auth Scheme Naming Consideration#

It is recommended to replace $AUTH_URL_SCHEME with your application's bundle id (com.company.myapp), or another value unique from other custom URL schemes (such as myapp://) registered with your app.

This prevents plugins that handle deep linking from intercepting callbacks made by authentication providers that Auth Connect relies on to complete login/logout functionality.

Supported Providers#

Leveraging the OAuth/OpenId Connect protocols, Auth Connect supports:

Workflow#

The typical Auth Connect workflow consists of:

  1. Your client app instantiates the Auth Connect Plugin, passing in the IonicAuthOptions object. Configure it based on the chosen auth provider.
  2. On app load, the hosting app calls IsAuthenticated to check if the user is logged in already.
  3. If the user isn't logged in, redirect the app to a Login page and call the Login method. Auth Connect loads the chosen auth provider's login page.
  4. The app user enters their username and password and taps the provider's login button.
  5. On success, Auth Connect automatically retrieves and stores the user's access token. The onLoginSuccess method is fired, and the app can redirect to the desired protected homepage.
  6. The IsAuthenticated method can be called at any point to refresh the access token.
  7. Use GetAccessToken to retrieve the access token if making any API requests to the auth provider.
note

Web apps using the current mode need to implement callback handlers on login and logout

Web Configuration Options#

When using Auth Connect in a web app, you have two options on how the login window will appear for your users. The window can either pop up in a new window/tab (known as "POPUP" mode), or it can occur in the current window ("CURRENT" mode).

Here's a visual comparison:

 

Popup Mode#

Popup mode will pop open a new window/tab to the authentication provider, and after the user authenticates, the window will close and the user will be back at your app.

Popup mode is the default, but you can explicitly specify it by setting the implicitLogin option to "POPUP" in the IonicAuthOptions configuraiton.

When using popup mode, you don't want to do any type of logic or page redirection in your redirectUri or logoutUrl pages. Once the user is done authenticating, the auth provider will redirect back to these pages, and Auth Connect will detect this and close the window.

Since these pages might briefly appear to your users, we recommend either keeping the page blank or have a simple branded page that they will see before the window closes.

Current Mode#

Current mode redirects the user to the authentication provider in their current window, so they will temporarily leave your app and be returned to the redirectUri after authentication is done.

To use current mode, set impliciLogin to "CURRENT" in the IonicAuthOptions configuration.

When using current mode, you need to finish handling the login/logout process in the redirectUri and logoutUrl pages. This is required because in current mode, the user leaves your app completely, and Auth Connect needs to know when the user is done authenticating. To do so, use the handleLoginCallback, and handleLogoutCallback methods respectively:

await this.ionicAuth.handleLoginCallback();
// User authed, so redirect to home page
await this.ionicAuth.handleLogoutCallback();
// User logged out, so redirect to login page

Testing Locally#

To test an Ionic app using Auth Connect locally, configure IonicAuthOptions to use http://localhost:8100/ as the base URL for properties such as redirectUri and logoutUrl. Then, run the ionic serve command.

Checking Authentication Status#

Auth Connect provides the isAuthenticated() convenience method for checking if there is a current session and refreshing that session if it is already expired. However, there are cases where you may want to implement your own method for checking if the user is authenticated. An example of needing to do this would be to handle checking the authentication status when the device is offline.

The isAuthenticated() method relies on the application having a connection to the internet because if the access token is expired, it will automatically attempt to refresh that token with the authentication provider. If the device is not connected to the network during this check, the refresh attempt will fail and the method will report back that the user is not currently authenticated.

Auth Connect provides access to the various building blocks necessary to create your own method for checking authentication status. A simple example for gracefully handling offline might look like the following:

async function isUserAuthenticated(): Promise<boolean> {
if (!(await myAuth.isAccessTokenAvailable())) {
// No token available, not logged in
return false;
}
if (await myAuth.isAccessTokenExpired()) {
if (navigator.onLine) {
// Token is expired, but we have a connection so we will attempt to refresh the token
try {
await myAuth.refreshSession();
return true;
} catch (e) {
// Refresh failed, clear the storage
await myAuth.clearStorage();
return false;
}
} else {
// Token is expired, but no connection. We will check for the presence
// of a refresh token, and if it exists, we will assume the login is still valid
return !!(await myAuth.getRefreshToken());
}
} else {
// Access token is not expired, authentication is valid
return true;
}
}

Microsoft Edge (Pre-Chromium) Support#

Due to a bug in the pre-Chromium version of Edge, you cannot overide a method in a subclass.

For instance, it is common to create a class that extends IonicAuth like this:

export class AuthenticationService extends IonicAuth {
private vaultService: VaultService;
...
async isAuthenticated(): Promise<boolean> {
const isVaultLocked = await this.vaultService.isLocked();
return !isVaultLocked && (await super.isAuthenticated());
}
...
}

If you need to support the pre-Chromium version of Edge, you will need to write your own method in the subclass that calls into the base class as follows:

export class AuthenticationService extends IonicAuth {
private vaultService: VaultService;
...
async myAppIsAuthenticated(): Promise<boolean> {
const isVaultLocked = await this.vaultService.isLocked();
return !isVaultLocked && (await super.isAuthenticated());
}
...
}

You will then need to change external references from this.authentication.isAuthenticated() to this.authentication.myAppIsAuthenticated() (the name is not important so much as the fact that you are not overriding the base class method, pick a name that makes sense to you).

You will also need to use the CURRENT behavior for implicitLogin on Edge.

Note: this is only required if you need to support pre-Chromium Edge browsers. If you are creating a pure hybrid-native app or otherwise have no reason to support pre-Chromium Edge, then you can override methods like isAuthenticated() in the usual manner.