Getting Started with Auth Connect
Generate the Application
Before we explore the use of Auth Connect, we need to scaffold an application. In this section, we will generate an @ionic/angular
tabs based application, perform some basic configuration, and add the iOS
and Android
platforms.
Use the Ionic CLI to generate the application.
Change directory into the newly generated project.
Change the appId
to be something unique. The appId
is used as the bundle ID / application ID. Therefore it should be a string that is unique to your organization and application. We will use io.ionic.gettingstartedac
for this application.
It is best to do this before adding the iOS
and Android
platforms to ensure they are setup properly from the start.
Build the application and install the platforms.
We should do a cap sync
with each build and ensure that our application is served on port 8100
when we run the development server. Change the scripts in package.json
to do this.
Use the Ionic CLI to generate the application.
Change directory into the newly generated project.
Change the appId
to be something unique. The appId
is used as the bundle ID / application ID. Therefore it should be a string that is unique to your organization and application. We will use io.ionic.gettingstartedac
for this application.
It is best to do this before adding the iOS
and Android
platforms to ensure they are setup properly from the start.
Build the application and install the platforms.
We should do a cap sync
with each build and ensure that our application is served on port 8100
when we run the development server. Change the scripts in package.json
to do this.
Install Auth Connect
In order to install Auth Connect, you will need to use ionic enterprise register
to register your product key. This will create a .npmrc
file containing the product key.
If you have already performed that step for your production application, you can just copy the .npmrc
file from your production project. Since this application is for learning purposes only, you don't need to obtain another key.
You can now install Auth Connect and sync the platforms:
Create the AuthenticationService
All interaction with Auth Connect will be abstracted into an AuthenticationService
. Generate that now.
Setup and Initialization
Before we use Auth Connect, we need to make sure that it is properly set up and initialized.
We will build this service up to perform the setup and initialization required by Auth Connect.
Auth Connect needs a slightly different configuration between mobile and web, so we need to know in which context we are currently running.
For this tutorial, we are using Auth0 as the authentication vendor. We need to create an Auth0Provider
to help Auth Connect with the communication with Auth0.
Auth Connect needs to know how to communicate with our authentication vendor. You will likely need to get this information from the team that manages your cloud infrastructure.
We need to perform a one-time setup with Auth Connect. Please refer to the documentation if you have any questions about the individual properties. We will start here with a simple set up that is good for development.
The promise returned by AuthConnect.setup()
is stored in our service so we can ensure the setup has completed before we execute code in methods we will add later.
We will build this service up to perform the setup and initialization required by Auth Connect.
Auth Connect needs a slightly different configuration between mobile and web, so we need to know in which context we are currently running.
For this tutorial, we are using Auth0 as the authentication vendor. We need to create an Auth0Provider
to help Auth Connect with the communication with Auth0.
Auth Connect needs to know how to communicate with our authentication vendor. You will likely need to get this information from the team that manages your cloud infrastructure.
We need to perform a one-time setup with Auth Connect. Please refer to the documentation if you have any questions about the individual properties. We will start here with a simple set up that is good for development.
The promise returned by AuthConnect.setup()
is stored in our service so we can ensure the setup has completed before we execute code in methods we will add later.
Create the auth-action-complete
Page
Note that the logoutUrl
and redirectUri
properties are using the /auth-action-complete
route. Generate a page for the route.
This page does not need to do anything. When running on the web, the authentication provider will navigate to this route within the OIDC authentication tab. We can just show a blank page.
Handling the Authentication Flow
Auth Connect is now properly set up and initialized. We can move on to creating the basic log in and log out flow. Within this flow, an AuthResult
is obtained during log in that represents our authentication session. So long as we have an AuthResult
object, we have an authentication session. The AuthResult
is no longer valid after the user logs out.
Login and Logout
We begin by creating the login()
and logout()
methods.
The AuthConnect.login()
call resolves an AuthResult
if the operation succeeds. The AuthResult
contains the auth tokens as well as some other information. This object needs to be passed to almost all other Auth Connect functions. As such, it needs to be saved. We will store it in our service for now.
For the login()
, we need to pass both the provider
and the options
we established earlier. Note that we wait for the setup()
call to resolve and that we store the result in our session variable.
For the logout()
, when we call Auth Connect we need to pass the provider
as well as the AuthResult
we established with the login()
.
The AuthConnect.login()
call resolves an AuthResult
if the operation succeeds. The AuthResult
contains the auth tokens as well as some other information. This object needs to be passed to almost all other Auth Connect functions. As such, it needs to be saved. We will store it in our service for now.
For the login()
, we need to pass both the provider
and the options
we established earlier. Note that we wait for the setup()
call to resolve and that we store the result in our session variable.
For the logout()
, when we call Auth Connect we need to pass the provider
as well as the AuthResult
we established with the login()
.
Hook Up the Login and Logout
We can use the first tab of our application to test the login()
and logout()
methods.
Currently, the Tab1Page
contains the default skeleton code.
Inject our AuthenticationService
and import IonButton
which we will use shortly.
Create login()
and logout()
methods that we can bind to in our template.
The app-explore-container
component is no longer needed.
Replace it with a couple of buttons.
You can also remove any references to ExploreContainerComponent
in tabs1.page.ts
.
Currently, the Tab1Page
contains the default skeleton code.
Inject our AuthenticationService
and import IonButton
which we will use shortly.
Create login()
and logout()
methods that we can bind to in our template.
The app-explore-container
component is no longer needed.
Replace it with a couple of buttons.
You can also remove any references to ExploreContainerComponent
in tabs1.page.ts
.
Test this in the web using the following credentials:
- email:
test@ionic.io
- password:
Ion54321
At this point if we press the Login button, a tab should open where we can log in using Auth0. This tab will close after we log in. When we press the logout button a tab will briefly open to perform the logout and then automatically close.
Note that if you press the Login button while already logged in the login tab is closed immediately. This is expected behavior.
Configure the Native Projects
Login and logout are working in your web browser. Build your application for mobile and try to run them there. You can use an emulator or an actual device for this test.
On Android, you get an error like this one:
_10Manifest merger failed : Attribute data@scheme at AndroidManifest.xml requires a placeholder substitution but no value for <AUTH_URL_SCHEME> is provided.
On iOS, the application runs, but you get an invalid URL error after successfully logging in on Auth0.
The problem is that on mobile we are deep-linking back into our application using io.ionic.acdemo://auth-action-complete
. We have not registered that scheme with the OS so it does not know to deep-link back to our application. We will set that up now.
For Android, modify the android
section of the android/app/build.gradle
file to include the AUTH_URL_SCHEME
:
For iOS, add a CFBundleURLTypes
section to the ios/App/App/Info.plist
file:
Re-run the application from Xcode and Android Studio. You should now be able to perform the authentication properly on the mobile applications.
Managing the Authentication Session
Determine if Authenticated
We can log in and we can log out, but it is hard to tell what our current authentication state is. Let's fix that now.
If we have an AuthResult
with an access token we assume that we are authenticated. The authentication session could be expired or otherwise invalid, but we will work on handling that in other tutorials.
Create an authenticated
property in the Tab1Page
class. Recheck the status after a login and logout actions complete.
To ensure that the value is initialized properly, the page should also check on initialization.
Import the CommonModule
so ngIf
can be used in the page's template.
Render the logout button if the user is authenticated. Render the login button if the user is not authenticated.
If we have an AuthResult
with an access token we assume that we are authenticated. The authentication session could be expired or otherwise invalid, but we will work on handling that in other tutorials.
Create an authenticated
property in the Tab1Page
class. Recheck the status after a login and logout actions complete.
To ensure that the value is initialized properly, the page should also check on initialization.
Import the CommonModule
so ngIf
can be used in the page's template.
Render the logout button if the user is authenticated. Render the login button if the user is not authenticated.
Which button is shown on the Tab1Page
is now determined by the current authentication state.
Persist the AuthResult
The user can perform login and logout operations, but if the browser is refreshed, the application loses the AuthResult
. This value needs to be persisted between sessions of the application. To fix this, create a session
service that uses the Preferences plugin to persist the AuthResult
. In a production application, we should store the result securely using Identity Vault. However, setting up Identity Vault is beyond the scope of this tutorial.
First build out the SessionService
.
The SessionService
starts with the basic service skeleton.
Import the Preferences
and AuthResult
classes.
Create methods to get, set, and clear the session.
Inject the SessionService
into the AuthenticationService
.
Create methods to get and save the AuthResult
.
Use the new methods instead of the authResult
class property, which can be removed now.
The SessionService
starts with the basic service skeleton.
Import the Preferences
and AuthResult
classes.
Create methods to get, set, and clear the session.
Inject the SessionService
into the AuthenticationService
.
Create methods to get and save the AuthResult
.
Use the new methods instead of the authResult
class property, which can be removed now.
If the user logs in and refreshes the browser or restarts the application the authentication state is preserved.
Next Steps
Explore the specific topics that are of interest to you at this time. This application is used as the foundation to build upon as those topics are explored.
Happy coding!! 🤓