Issue
I am using firebase in angular 8 to authenticate the user both in frontend and backend. To authenticate the user in the backend I need to send user Id token.
I am using firebase getIdToken to get the token and it works but partially. The error "TypeError: Cannot read property 'getIdToken' of null" occurs when I refresh the page.
I have tried to hard code the token to the getToken() method and it works even on refresh but that is not feasible, so I made the getToken method to return Observable.
That observable is fetched in Http interceptor TokenInterceptorService, to add the token to all the requests.
export class AuthService {
constructor(
public afs: AngularFirestore, // Inject Firestore service
public afAuth: AngularFireAuth, // Inject Firebase auth service
public router: Router,
public ngZone: NgZone // NgZone service to remove outside scope warning
) {}
// Other authentication methods for sign up etc.
// removed here for readability
getToken(): Observable<string> {
// getIdToken() returns promise so using 'from' to
// convert it to an Observable
const result = from(this.afAuth.auth.currentUser.getIdToken()
.then( token => {
console.log(token);
return token;
})
);
return result;
}
}
export class TokenInterceptorService implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.authService.getToken()
.pipe(
switchMap(token => {
const newRequest = request.clone({
setHeaders: {Authorization: `JWT ${token}`}
});
return next.handle(newRequest);
})
);
}
}
I have seen similar questions and I am using that solution with some modification.
I have even tried returning promise from getToken() method but that too doesn't work.
Solution
getting the currentUser
is asynchronous, so it would be expected that initially it will be null
. Like mentioned in documentation:
Note:
currentUser
might also be null because theauth
object has not finished initializing.
Instead you should be using authState
to get the current user. Then from the user you get from there, you can call getIdToken()
, which returns a promise. You can use from
there to convert it to an observable:
getToken(): Observable<string | null> {
return this.afAuth.authState.pipe(
take(1),
switchMap((user) => {
if (user) {
return from(user.getIdToken())
}
return of(null);
})
)
}
Then in your interceptor, also do a check if token exists. If there is no user, it will return null
Answered By - AT82
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.