Analyzing the Ionic AWS Full-Stack Starter: Configuration and Providers

I have used both Ionic and AWS for years now. Both technologies are (mostly) free and awesome.

Ionic is the badass framework to build cross-platform mobile applications and AWS gives us the tools to host, cache, manipulate files with authentication and many more services in the cloud.

So what’s the result if both companies allied together to create a project: the Ionic AWS Starter!

Until now, I have only used the S3 service so this stack gave me a new look at AWS potential. 

The AWS Mobile Hub

Instead of creating the backend in Java, Ruby or Node.js, AWS offers some services that can be easily configured by clicking some buttons.

Those services are centered in one place: the Mobile Hub.

AWS mobile hubAs you can see from this picture, there are nine types of services. Only five are used in our stack:

  1. Authentication
  2. NoSQL Database
  3. User Data Storage
  4. User Engagement
  5. Hosting and Streaming

Subscribe to my mailing list to get access to a Free 7-day Ionic 3 introduction email course!
100% Privacy. I'll never spam you!

As I said before, most of those services can be activated with just one click:

AWS mobile hub add serviceWe can start from zero, add the services one by one or import them, which brings us back to the starter project.

The installation instructions are available there. (You might have to configure your AWS credentials, to avoid this, I manually downloaded the aws-config.js file)

The Ionic project already have a mobile-hub-project.zip file that contains a configuration for the Mobile Hub, so most of the work is already done for us.

If we unzip the file, we can have a look at the yaml configuration:

This configuration is very concise. We only need 60 lines to create five features. Not bad right?

Let’s focus on the sign-in feature, the attributes will specify the type of authentication (ex: email), how strong the password should be or if signing in is optional or required.

Taking a step back, the authentication is designed on the backend (the Mobile Hub) to be optional.

When launching our app:

This doesn’t look optional 🤔.

Aside from that, what does the mobile app do?

In a nutshell, it allows a user to create an account, connect, add some tasks, change its profile picture and disconnect.

Those actions cover a good spectrum of use cases showcasing the use of:

  1. AWS S3 for stocking the profile picture
  2. Cognito for authentication
  3. DynamoDB for stocking the tasks details
  4. Ionic Native for the use of the camera

The architecture is as follow:

Ionic Aws stack architectureNothing new about the pages, each feature is separated in its own folders.
Provider wise, every AWS Services are available in the providers folder: Cognito, DynamoDb and User.

The providers.ts file exports those services:

Special mention to the assets folder which contains the AWS libraries:

Ionic Aws stack assets folder

Why not using the package.json to acquire those files?

Two possible reasons:

  1. They use a custom AWS version, different from the public one
  2. They want AWS to be loaded before other Angular and Ionic files, in the index.html file:

Index.html load

Aside from the AWS core libraries, the aws.config.js file is very important, this file sets multiple global constants that will be used for configuration like the region, the bucket, etc.

Those constants are then acquired in the app.config.ts file:

Note the:

We will encounter this again and again and again in this project.

Typically, this could have been placed once and for all in a declaration.d.ts file in order to be available everywhere.

The app.module.ts file is just business as usual, except:

All our previous configurations are merged with Ionic’s Config.

Moving on to the Providers.

Providers

Starting with the simplest one: DynamoDB.

Located in the aws.dynamodb.ts file:

This Service creates the document client and an accessor.
The document client is our god object that will allow us to manipulate the database.
The documentation is there, with every traditional db commands: put, delete, get, query…

Followed by the Cognito service.

Located in the aws.cognito.ts file:

Which starts with some imports and declarations.

In the constructor, we setup AWSCognito with the configuration we talked about earlier:

  1. The region where the endpoints are located (ex: us-east-1)
  2. The IdentityPoolId: A unique identifier pointing to the Cognito Service
  3. The CustomUserAgent: In order to avoid user agent filters (ex: bot defense), the user agent is set to “MobileHub v0.1”

Followed by the getUserPool method:

Setting up the access to AWSCognito’s user pool.

Important workaround here, the this object is stocked in another variable named self in order to keep it available in the CognitoUserPool method.

Let’s avoid the confusion!

The UserPoolId represents where the clients are stocked whereas the ClientId authenticates applications that connect to this user pool:

Ionic Aws stack client ids

Those ids are available in the mobile-hub-project.yml configuration file and on the AWS Mobile Hub webpage.

Once we have access to the user pool, we can:

  • Access a user from the pool:
  • Get the current user:
  • Create authentication data:
  • Create a user attribute:

We are now done with the Cognito Service.

Moving on to the last one: the User Service.

This Service will use the Cognito Service’s methods.

Two interesting properties here:

  1. user: Will stock the Cognito user once logged in
  2. loggedId: A simple flag (not yet used)

Some accessors:

The registration part:

When a user registers, its attributes (name, address, etc.) must go through some transformations in the makeAttribute method.

A Promise is returned so the flow can progress.
Then the user is signed up to the user pool. Finally, if everything is good, the user is returned.

If the user forgot its registration code:

Using the username, the makeUser method is used to grab the matching user then the built-in resendConfirmationCode method is used (we didn’t code this one, many methods come from the Cognito user object #profit).

Once the user has the code:

Same as before, the makeUser method gives us the Cognito user and we check if the code is good by using the confirmRegistration method.

More code in the login method:

The login method will get the user matching the username.
It will compare it to the information from authDetails using the authenticateUser method.

If everything is good, we receive a result that contains a token.

The loginKey string can be scary, but in the end it’s just a path to the user pool located in our region.
This path is associated to the token we received. Using this path and our Cognito’s IdentityPoolId, we can now set the credentials for AWS.
Those credentials will automatically be added to our future requests.

The final touch is the isAuthenticated method:

First we grab the current user, if he does exist, we look if we can get a session.
Once again the loginKey variable is created. This time the token comes from the session itself.

Finally, the user is stocked in the user property of the User Class.

Remember, this one:

Let’s not forget the logout method!

Cleaning up our local user and signing out the user from Cognito’s user pool.

And Voila we are done with our Providers!

Conclusion

In this tutorial we have seen the most complex parts of the application: AWS configuration and Providers creation.
The rest of the application will use those parts in order to communicate with the AWS Services to handle the users, the tasks and the profile pictures.

The AWS Mobile Hub is super cool to use!

It’s the first time that I can configure so many complex services by only using a few clicks.
In the next tutorial we will have a look at how the Providers are integrated into the application’s business logic.

Until next time.

5 Comments

  1. Guillermo Rodriguez Guillermo Rodriguez
    June 26, 2017    

    Hi Matthieu, great article!

    I was wondering if you have experience with PinPoint and Ionic for push notifications.

    We are trying to use AWS PinPoint to deliver direct (push) messages to an Ionic app. We successfully configured our back-end (Java) to deliver the messages, which are correctly delivered to the Ionic app when the app is in foreground. When the app is in background, it does not get notified of the push messages. We tried the same approach delivering the message using a different Push Notification provider and we saw the push message delivered by PinPoint is different (like it is wrapping the message in its own data element). Any advice?

    Thanks in advance!

    • Matthieu Drula Matthieu Drula
      June 26, 2017    

      Hi Guillermo,
      Never used it, I generally used OneSignal for this task since it’s totally free and very well documented.
      You should give it a try.

    • Devon Devon
      December 6, 2017    

      Hi Guillermo, I’m struggling with exactly the same PinPoint problem at the moment. Did you ever find a solution?

  2. everything 2040 everything 2040
    August 19, 2017    

    Hi,

    I cannot locate the file “declaration.d.ts”, is it a file created by ionic AWS template?
    if yes may be the new ionic template is not using it anymore

    • Matthieu Drula Matthieu Drula
      August 19, 2017    

      Hi,
      Back in the day a declaration.d.ts was added to Angular projects, I was only making a reference.

Leave a Reply

Your email address will not be published. Required fields are marked *

5 Shares