How to use firebase auth for login with custom rest API?

Viewed 258

I am preparing a website which is using Firebase for login Facebook, Google, and Twitter. This part is working properly also.

I have a rest API that is linked to my amazon Cognito. I tried to follow this example to (here) rewrite the user object of firebase.

The code is working fine with google authentication but when I try to login with Cognito, everything is successful but my username does not appear in bs-navbar.component.html.

Can you help me did I miss anything?

import { AngularFireAuth } from '@angular/fire/auth';
import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import {  Observable, from } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, mapTo, tap } from 'rxjs/operators';
import { CUser } from '../app/shared/services/user'
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import 'rxjs/add/operator/switchMap'
import { of } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  private readonly apiUrl = 'https://api.site.com/v2';
  private readonly JWT_TOKEN = 'JWT_TOKEN';
  private readonly REFRESH_TOKEN = 'REFRESH_TOKEN';
  private loggedUser: string;

  cuser$: Observable<CUser>; // Save logged in user data

  constructor(private afAuth: AngularFireAuth, private httpClient: HttpClient, private afs: AngularFirestore) {
    this.cuser$ = this.afAuth.authState;
  }

  private updateUserData(user){
    const userRef : AngularFirestoreDocument<CUser> = this.afs.doc(`users/${user.uid}`);
    
    const data = {
      uid: user.uid,
      email: user.email,
      displayName : user.displayName,
      photoURL : user.photoURL,
      emailVerified: user.emailVerified 
    }
    return userRef.set(data, { merge: true });
  }

  doCognitoLogin(email, password){
    const payload = {
      "poolData": {
        "UserPoolId": "UserPoolId",
        "ClientId": "ClientId",
        "Paranoia": "34"
      },
      "params": {
        "username": email,
        "password": password
      }
    };

    return this.httpClient.post(this.apiUrl + '/signin', payload).pipe(
      map((response: any) => {
        const res = response;
        if (!res.error) { 
          console.log('signin'); 
          this.updateUserData({uid:email,email:email,displayName:email,photoURL:"",emailVerified:true});
          return true; 
      }
        else { 
          console.log('wrong password'); 
          return false; 
        }
      })
    );
  }

  async doGoogleLogin() {
      let provider = new firebase.auth.GoogleAuthProvider();
      provider.addScope('profile');
      provider.addScope('email');
      const credential = await this.afAuth.signInWithPopup(provider);
      return this.updateUserData(credential.user);
  }

  logout() {
    this.afAuth.signOut();
  }
}

------------------login.component.ts-----------------

export class LoginComponent {
  constructor(public auth: AuthService) { }

  doCognitoLogin(email, password){

    const myObservable = {
      next: x => {
                  console.log('User logged in:'+ x);
                  const login_spinner = document.getElementById("login_spinner");
                  login_spinner.classList.add('sr-only');
                  login_spinner.style.display = 'none';
                },
      error: err => console.log(err) 
    };

    this.auth.doCognitoLogin(email,password).subscribe(myObservable);
  }

  doGoogleLogin() {
    this.auth.doGoogleLogin();
  }


  async loginBtClicked(event) {
    event.preventDefault();
    this.doCognitoLogin(_inputEmail.value,_inputPassword.value);
  }
}

--------bs-navbar.component.html------

<ng-template #anonymousUser>
          <li class="nav-item">
            <a class="nav-link" routerLink="/login">Login</a>
          </li>
        </ng-template>
        <!-- <li class="nav-item">
          <a class="nav-link active" routerLink="/" style="background: rgb(245, 162, 208)">Home</a>
        </li> -->
        <!-- auth.user$ | async as user; else anonymousUser -->
        <li ngbDropdown *ngIf="auth.user$ | async as user; else anonymousUser" class="nav-item dropdown">
          <a ngbDropdownToggle class="nav-link dropdown-toggle" id="dropdownBasic1" data-toggle="dropdown" aria-haspopup="true">
            {{ user.displayName }}
          </a>
          <div ngbDropdownMenu class="ngbDropdownMenu" aria-labelledby="dropdownBasic1">
            <a class="dropdown-item" routerLink="/my/orders">My Orders</a>
            <a class="dropdown-item" routerLink="/admin/admin-orders">Manage Orders</a>
            <a class="dropdown-item" routerLink="/admin/admin-products">Manage Products</a>
            <a class="dropdown-item" (click)="logout()">Log out</a>
          </div>
        </li>
1 Answers

My problem was due to not updating "user" parameter which is defined in my AuthService.

I changed my code as below in doCognitoLogin:

 return this.httpClient.post<any>(this.apiUrl + '/signin', payload)
    .map((res:any) => {
      res.displayName = user.email.replace(/@.*$/,"");
      this.doLoginUser(user.email,{ refreshToken: res.refreshToken, accessToken: res.accessToken});
      return res
    });

So now I can have my firebase and cognito together and they are functioning similarly and simultaneously.

Related