I am using firebase to authenticate a sign in and then send a request to my backend to create a custom session token for the logged in user. For this, I send in a function call from my component.ts to service.ts.
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken }).pipe(
catchError(err=>{
return throwError("FailedLogin") // ** NOT USEFUL ERROR
})
)
.subscribe((response) => {
this.router.navigate(["/signup"]); // ** IF SIGN IN IS SUCCESSFUL
}
// , (err) => {
// throw new Error("Failed Login"). // ** NOT USEFUL ERROR
// }
)
return { loggedIn: false, message: "Failed Login" } // ** INCASE MY BACKEND THROWS ERROR
}).catch(err => {
return { loggedIn: false, message: err.message }. // ** INCASE FIREBASE THROWS ERROR
});
}
The component.ts code is
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
const response = await this.authenticationService.SignIn(email, password)
if(!response.loggedIn){
// my error handling code for flash messages
}
}
Now, the above code does the job, but I know that it's one of the worst ways of error handling as I am not using the observables to their fullest potential. I want to know how to use the catchError or perhaps try-catch blocks to not manually send and check a custom { loggedIn: false, message: err.message } like object to my component.
The catchErrors above are basically useless as they are not being forwarded to my component. If I return the this.http.post.., it says it is a subscription and I can't do a .then() on it + it says the response in my frontend would then either be of the type Subscription or of the type { loggedIn: false, message: err.message }
I have broken down the two things : signing in using firebase and then sending a request to backend for token into two different parts. It looks like a much more elegant solution for it doesn't involve any manual response object creation.
** component.ts**
async signIn(loginF: NgForm) {
const email = loginF.value.email
const password = loginF.value.password
let idToken
try{
idToken = await this.authenticationService.SignIn(email, password)
}catch(err){
idToken = null; // ** INCASE FIREBASE FAILS
// error handling for flash messages
}
if(idToken!= null){
this.authenticationService.SignInBackend(idToken).subscribe((response) => {
this.router.navigate(["/signup"]);
}
, (err) => {
// error handling for flash messages // ** INCASE BACKEND FAILS
}
)
}
}
** service.ts**
SignIn(email: string, password: string) {
return this.angularFireAuth
.signInWithEmailAndPassword(email, password)
.then(async res => {
const idToken = await res.user.getIdToken()
return idToken;
}).catch(err => {
throw new Error(err.message). // ** ERROR GETS CHAINED
});
}
SignInBackend(idToken){
return this.http.post(environment.baseURL + "auth/sessionLogin", { idToken: idToken })
}