Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Building Secure Authentication in Angular with Supabase
Kingsley Amankwah
Kingsley Amankwah

Posted on

     

Building Secure Authentication in Angular with Supabase

Hey Angular developers! 🅰️ It's about that time again for yet another article. In this guide, we're going to dive into how to integrateSupabase, with Angular to build a secure authentication application. We’ll set up signup, and login authentication with Supabase in Angular and protect routes of some pages. Let’s get started

Prerequisites

Before we dive in, make sure you've got:

Step 1: Set Up a Supabase Project

Create a New Project:

  • Log in to Supabase and click New Project.

Supabase Create New Project Image

  • Enter a project name, and database password, and choose a region.

Supabase New Project Form Image

  • Wait a few minutes for the project to provision.

Retrieve API Credentials:
On the project overview section, Copy theProject URL andanon public (API Key).

Supabase Project Overview Image

Step 2: Create an Angular Project

  • Generate a New Angular App:
ng new supabase-auth-app
Enter fullscreen modeExit fullscreen mode

Choose your preferred styling when prompted.

  • Install Dependencies: Install the Supabase JavaScript client:
npminstall @supabase/supabase-js
Enter fullscreen modeExit fullscreen mode

Step 3: Configure Supabase in Angular

  • Set Up Environment Variables: Store the Supabase credentials securely in Angular’s environment files.

Opensrc/environments/environment.ts and add:

exportconst environment={  production:false,  supabaseUrl:'SUPABASE_URL',  supabaseKey:'SUPABASE_ANON_KEY'};
Enter fullscreen modeExit fullscreen mode

ReplaceSUPABASE_URL andSUPABASE_ANON_KEY with values from the Supabase dashboard.

  • Create Type Definitions: Insrc/app/types/user.type.ts, define types for user data and payloads:
export typeUser={id: string;  email?: string;  phone?: string;  user_metadata:{    displayName?: string;};};export typeSignupPayload={  name: string;  email: string;  password: string;};export typeLoginPayload={  email: string;  password: string;};
Enter fullscreen modeExit fullscreen mode
  • Create a Supabase Service: Generate a service to manage Supabase interactions:
ng generate service services/supabase
Enter fullscreen modeExit fullscreen mode

Updatesrc/app/services/supabase.service.ts to initialize the Supabase client and handle authentication:

import{ Injectable} from'@angular/core';import{ createClient, SupabaseClient} from'@supabase/supabase-js';import{ environment} from'../../environments/environment';import{ LoginPayload, SignupPayload} from'../types/user.type';@Injectable({  providedIn:'root',})exportclass SupabaseService{  privatereadonlysupabase: SupabaseClient;  constructor(){    this.supabase= createClient(      environment.supabaseUrl,      environment.supabaseKey);}  async signInWithEmail(payload: LoginPayload){returnawait this.supabase.auth.signInWithPassword({      email: payload.email,      password: payload.password,});}  async signUpWithEmail(payload: SignupPayload){returnawait this.supabase.auth.signUp({      email: payload.email,      password: payload.password,      options:{        data:{          displayName: payload.name,},},});}  async getUser(){returnawait this.supabase.auth.getUser();}  async signOut(){returnawait this.supabase.auth.signOut();}}
Enter fullscreen modeExit fullscreen mode

The SupabaseService centralizes authentication logic, making it reusable across components. It handles initialization, user state, and auth methods, ensuring clean and maintainable code.

Step 4: Set Up Authentication Components

  • We’ll create components for login, signup, and profile pages.

Generate Components:

ng generate component auth/loginng generate component auth/signup ng generate component profile
Enter fullscreen modeExit fullscreen mode
  • Login Component: Updatesrc/app/auth/login/login.component.ts to handle email/password login:
import{ Component, inject, signal} from'@angular/core';import{ SupabaseService} from'../../services/supabase.service';import{ Router} from'@angular/router';import{ FormsModule} from'@angular/forms';@Component({  selector:'app-login',  imports:[FormsModule],  templateUrl:'./login.component.html',  styleUrl:'./login.component.css',})exportclass LoginComponent{  email= signal('');  password= signal('');  privatereadonlysupabaseService= inject(SupabaseService);  privatereadonlyrouter= inject(Router);  async signInWithEmail(){    const{ error}= await this.supabaseService.signInWithEmail({      email: this.email(),      password: this.password(),});if(error){      alert('Error signing in: ' + error.message);}else{      this.router.navigate(['/profile']);}}  navigateToSignup(){    this.router.navigate(['/signup']);}}
Enter fullscreen modeExit fullscreen mode
  • Updatesrc/app/auth/login/login.component.html:
<divclass="container">  <h2>Login</h2>  <form>    <inputtype="email"[(ngModel)]="email"name="email"placeholder="Email"      required    />    <inputtype="password"[(ngModel)]="password"name="password"placeholder="Password"      required    />    <buttontype="button"(click)="signInWithEmail()">Sign In</button>  </form>  <p>Don't have an account? <a (click)="navigateToSignup()">Sign Up</a></p></div>
Enter fullscreen modeExit fullscreen mode
  • Add styling(optional), insrc/app/auth/login/login.component.css:
.container{  max-width: 400px;  margin: 50px auto;  padding: 20px;  border: 1px solid#ccc;  border-radius: 5px;}input, button{  display: block;  width: 100%;  margin: 10px 0;  padding: 10px;}button{  background-color:#007bff;  color: white;  border: none;  cursor: pointer;}button:hover{  background-color:#0056b3;}
Enter fullscreen modeExit fullscreen mode
  • Signup Component: Updatesrc/app/auth/signup/signup.component.ts:
import{ Component, inject, signal} from'@angular/core';import{ FormsModule} from'@angular/forms';import{ SupabaseService} from'../../services/supabase.service';import{ Router} from'@angular/router';@Component({  selector:'app-signup',  imports:[FormsModule],  templateUrl:'./signup.component.html',  styleUrl:'./signup.component.css',})exportclass SignupComponent{  name= signal('');  email= signal('');  password= signal('');  privatereadonlysupabaseService= inject(SupabaseService);  privatereadonlyrouter= inject(Router);  async signUp(){    const{ error}= await this.supabaseService.signUpWithEmail({      name: this.name(),      email: this.email(),      password: this.password(),});if(error){      alert('Error signing up: ' + error.message);}else{      alert('Check your email to confirm your account!');      this.router.navigate(['/login']);}}  navigateToLogin(){    this.router.navigate(['/login']);}}
Enter fullscreen modeExit fullscreen mode
  • Updatesrc/app/auth/signup/signup.component.html:
<divclass="container">  <h2>Sign Up</h2>  <form>    <inputtype="text"[(ngModel)]="name"name="name"placeholder="Full Name"      required    />    <inputtype="email"[(ngModel)]="email"name="email"placeholder="Email"      required    />    <inputtype="password"[(ngModel)]="password"name="password"placeholder="Password"      required    />    <buttontype="button"(click)="signUp()">Sign Up</button>  </form>  <p>Already have an account? <a(click)="navigateToLogin()">Log In</a></p></div>
Enter fullscreen modeExit fullscreen mode

Use the same CSS as the login component(signup.component.css).

  • Profile Component: Updatesrc/app/profile/profile.component.ts:
import{ Component, inject, OnInit} from'@angular/core';import{ SupabaseService} from'../services/supabase.service';import{ Router} from'@angular/router';import{ User} from'../types/user.type';@Component({  selector:'app-profile',  imports:[],  templateUrl:'./profile.component.html',  styleUrl:'./profile.component.css',})exportclass ProfileComponent implements OnInit{  user: User | null= null;  privatereadonlysupabaseService= inject(SupabaseService);  privatereadonlyrouter= inject(Router);  ngOnInit(){    this.fetchUser();}  async fetchUser(){    const{ data}= await this.supabaseService.getUser();    this.user= data.user;if(!this.user){      this.router.navigate(['/login']);}}  async signOut(){    await this.supabaseService.signOut();    this.router.navigate(['/login']);}}
Enter fullscreen modeExit fullscreen mode
  • Updatesrc/app/profile/profile.component.html:
<divclass="container">  <h2>User Profile</h2>  <p>    Congratulations! Welcome to secure auth with Angular + Supabase is running.    🎉  </p>  @if(user){  <p>User ID:{{ user.id}}</p>  <p>Email:{{ user.email}}</p>  <p>Display Name:{{ user.user_metadata.displayName}}</p>}  <button(click)="signOut()">Sign Out</button></div>
Enter fullscreen modeExit fullscreen mode

Step 5: Configure Routing and Route Protection

  • Create an Auth Guard: Generate a guard:
ng generate guard guards/auth
Enter fullscreen modeExit fullscreen mode
  • Updatesrc/app/guards/auth.guard.ts:
import{ inject} from'@angular/core';import{ CanActivateFn, Router} from'@angular/router';import{ SupabaseService} from'../services/supabase.service';exportconst authGuard: CanActivateFn= async(route, state)=>{  const supabaseService= inject(SupabaseService);  const router= inject(Router);  const user= await supabaseService.getUser();if(!user){    router.navigate(['/login'],{ queryParams:{ returnUrl: state.url}});returnfalse;}returntrue;};
Enter fullscreen modeExit fullscreen mode
  • Set Up Routes: Updatesrc/app/app.routes.ts to use lazy loading and protect the profile route:
import{ Routes} from'@angular/router';import{ authGuard} from'./guards/auth.guard';exportconst routes: Routes=[{ path:'', redirectTo:'/login', pathMatch:'full'},{    path:'login',    loadComponent:()=>      import('./auth/login/login.component').then((c)=> c.LoginComponent),},{    path:'signup',    loadComponent:()=>      import('./auth/signup/signup.component').then((c)=> c.SignupComponent),},{    path:'profile',    loadComponent:()=>      import('./profile/profile.component').then((c)=> c.ProfileComponent),    canActivate:[authGuard],},];
Enter fullscreen modeExit fullscreen mode

Run Application

Using the command:

ng serve -o
Enter fullscreen modeExit fullscreen mode

This will run and open the application in the default browser.

Angular+Suapbase+Successful+integration

After successful sign-in🎉🎉🎉

Supabase+Angular+Succesful+Login

Conclusion

We’ve just built a secure authentication system in Angular using Supabase, complete with email/password signup, login, and route protection.

This setup is a solid foundation for more advanced features like role-based access, password resets, or social logins, all supported by Supabase.

Access the full source code onGitHub.

For more customization and ideas, explore theSupabase Docs.

Happy coding! 🅰️⚡

Top comments(5)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
fawuzantech profile image
Ibrahim Fawuzan
love to code
  • Joined

okay seing Novu here means its actually goated, man I've got to buoils cool shit tonight

CollapseExpand
 
nevodavid profile image
Nevo David
Founder of Postiz, an open-source social media scheduling tool.Running Gitroom, the best place to learn how to grow open-source tools.
  • Education
    Didn't finish high school :(
  • Pronouns
    Nev/Nevo
  • Work
    OSS Chief @ Gitroom
  • Joined

Pretty cool seeing a real breakdown like this - makes me wanna roll up my sleeves and build something tonight.

CollapseExpand
 
kingsley profile image
Kingsley Amankwah
Software Engineering | Technical Writing | Tech Community Leader
  • Email
  • Location
    Remote
  • Education
    University Of Education
  • Pronouns
    He/Him/His
  • Work
    Software Engineer
  • Joined

@nevodavid roll up your sleeves and let me see what you're cooking tonight

CollapseExpand
 
georg-easiedu profile image
George Kwabena Asiedu
A result-oriented front-end developer passionate about creating seamless, responsive, visually stunning web experiences. With expertise in modern frameworks like Angular and React.
  • Email
  • Location
    Accra, Ghana
  • Education
    Takoradi Technical University
  • Joined

This is interesting work done Kingsley, I have been looking for this for awhile now, thanks for writting this article, I know it will help me.

CollapseExpand
 
kingsley profile image
Kingsley Amankwah
Software Engineering | Technical Writing | Tech Community Leader
  • Email
  • Location
    Remote
  • Education
    University Of Education
  • Pronouns
    He/Him/His
  • Work
    Software Engineer
  • Joined

You're welcome George

Some comments may only be visible to logged-in visitors.Sign in to view all comments.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software Engineering | Technical Writing | Tech Community Leader
  • Location
    Remote
  • Education
    University Of Education
  • Pronouns
    He/Him/His
  • Work
    Software Engineer
  • Joined

More fromKingsley Amankwah

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp