User Authentication and Data Storage
Building Real Features — Alright, you've got the basic structure of your Ionic app set up and ready to go. You've created some pages, added a little interactivity, and even hooked it up to a simple Node.js backend. But now it’s time to step up your game by adding some real-world features. We’re talking about user authentication (because you know every app needs some kind of login system) and data storage (because what’s an app without storing user info somewhere?).
In this tutorial, we're going to:
- Set up user authentication: We’ll build a simple user registration and login system.
- Store user data: We’ll introduce MongoDB, a NoSQL database, to save user info like passwords (hashed, of course) and any other data your app might need.
- Connect the dots: Once the backend is ready, we’ll wire everything up in your Ionic app so users can sign up, log in, and interact with their data.
By the end, you’ll have a fully functional user login system with data storage!
Setting Up Authentication: Let’s Build Logins and Signups
First things first, let’s get the login and signup forms in place. If you've ever signed up for an account on any website, you know the drill: users provide their email and password, then they can log in to access personalized data.
Step 1: Create the Sign-Up Page
We’ll start by creating a new Sign-Up page in your Ionic app. Open your terminal and run:
ionic generate page SignUp
This will create a new folder called signup
with three files inside it (signup.page.html
, signup.page.scss
, and signup.page.ts
).
Now, open signup.page.html
and add the following code:
<ion-header>
<ion-toolbar>
<ion-title>Sign Up</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<form (submit)="onSubmit()">
<ion-item>
<ion-label position="floating">Email</ion-label>
<ion-input type="email" [(ngModel)]="email"></ion-input>
</ion-item>
<ion-item>
<ion-label position="floating">Password</ion-label>
<ion-input type="password" [(ngModel)]="password"></ion-input>
</ion-item>
<ion-button expand="block" type="submit">Sign Up</ion-button>
</form>
</ion-content>
Let’s break it down:
- Form: We’ve got a simple form with two fields—one for the user’s email and one for their password. The
[(ngModel)]
directive binds the input values to our component’s properties, which we’ll define in a minute. - Button: When the user clicks the "Sign Up" button, the form submits, and the
onSubmit()
method gets called.
Step 2: Add Logic to the Sign-Up Page
Now, open signup.page.ts
and add the following code:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { NavController } from '@ionic/angular';
@Component({
selector: 'app-signup',
templateUrl: './signup.page.html',
styleUrls: ['./signup.page.scss'],
})
export class SignUpPage {
email: string = '';
password: string = '';
constructor(private http: HttpClient, private navCtrl: NavController) {}
onSubmit() {
const user = { email: this.email, password: this.password };
this.http.post('http://localhost:3000/api/signup', user).subscribe(response => {
console.log('User signed up:', response);
this.navCtrl.navigateRoot('/login'); // Navigate to login page after successful signup
});
}
}
Here’s what’s going on:
- We’re using HttpClient to send a POST request to our backend when the user submits the form. We’re sending the user’s email and password to a route (
/api/signup
) that we’ll set up in the backend next. - NavController: After the user successfully signs up, we navigate them to the login page.
Building the Backend: Setting Up User Registration with Node.js
Now that we have our signup form ready on the frontend, we need to create the corresponding backend route to handle user registration.
Step 1: Install Required Packages
In your backend folder (where server.js
is located), install the necessary packages:
npm install bcryptjs mongoose
- bcryptjs: This package will help us hash user passwords before saving them to the database.
- mongoose: This is an Object Data Modeling (ODM) library for MongoDB, which we’ll use to interact with our database.
Step 2: Set Up MongoDB
If you don’t already have MongoDB installed, you can install it from here. Once it’s installed, run the following command to start MongoDB:
mongod
This will start the MongoDB server on your machine. If you’re using a cloud service like MongoDB Atlas, just make sure to get the connection string from there.
Step 3: Create a User Model
Now, let’s create a User model for MongoDB. In your backend
folder, create a new folder called models and inside it, create a file called User.js
. Add the following code:
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) {
return next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
const User = mongoose.model('User', userSchema);
module.exports = User;
This defines our user model with two fields: email
and password
. The pre('save')
hook ensures that the password gets hashed before it’s saved to the database.
Step 4: Create the Signup Route
Next, we’ll create a route for handling user registration. In server.js
, add the following code:
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const User = require('./models/User');
const app = express();
const port = 3000;
app.use(cors());
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/ionicApp', { useNewUrlParser: true, useUnifiedTopology: true });
app.post('/api/signup', async (req, res) => {
const { email, password } = req.body;
try {
const user = new User({ email, password });
await user.save();
res.status(201).json({ message: 'User registered successfully!' });
} catch (error) {
res.status(400).json({ error: 'Error registering user' });
}
});
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
This route handles incoming POST requests to /api/signup
, creates a new user in the database, and returns a success message if everything goes well.
Creating the Login Page
Now that we’ve got the signup process sorted, let’s move on to the Login Page.
Step 1: Create the Login Page
In your Ionic project, generate a login page:
ionic generate page Login
Open up login.page.html
and add the following code:
<ion-header>
<ion-toolbar>
<ion-title>Login</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<form (submit)="onLogin()">
<ion-item>
<ion-label position="floating">Email</ion-label>
<ion-input type="email" [(ngModel)]="email"></ion-input>
</ion-item>
<ion-item>
<ion-label position="floating">Password</ion-label>
<ion-input type="password" [(ngModel)]="password"></ion-input>
</ion-item>
<ion-button expand="block" type="submit">Login</ion-button>
</form>
</ion-content>
Step 2: Add Login Logic
Now, open login.page.ts
and add this code:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { NavController } from '@ionic/angular';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage {
email: string = '';
password: string = '';
constructor(private http: HttpClient, private navCtrl: NavController) {}
onLogin() {
const user = { email: this.email, password: this.password };
this.http.post('http://localhost:3000/api/login', user).subscribe(response => {
console.log('User logged in:', response);
this.navCtrl.navigateRoot('/home'); // Redirect to home page after login
});
}
}
When the user submits the form, we send their email and password to the /api/login
endpoint (which we’ll create in the backend next).
Handling User Login on the Backend
Now, let’s handle the login request on the backend.
Step 1: Add Login Route
In server.js
, add this code:
const bcrypt = require('bcryptjs');
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ error: 'Invalid credentials' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ error: 'Invalid credentials' });
}
res.json({ message: 'Logged in successfully' });
} catch (error) {
res.status(500).json({ error: 'Server error' });
}
});
This route checks if the user exists, then compares the submitted password with the hashed password stored in the database. If everything matches, the user is logged in.
Wrapping Up
Congratulations, you’ve just added user authentication and data storage to your app! Your users can now sign up, log in, and have their data saved securely in a MongoDB database.
For now, give yourself a pat on the back—you’re building some serious app functionality!