angular - Interceptor med Firebase-autentisering
Jeg har problemer med min Angular 6-interceptor. Jeg har migrert koden fra Angular 5.x til 6.0 og rxjs 5.x til 6.x. Når jeg prøver å opprette en ny brukerkonto, ser det ut til at forespørselen blir kalt to ganger. Jeg vet dette fordi jeg logger feilen til konsollen. Jeg har lagt merke til at jeg får denne dupliseringen når jeg prøver å hente Id-tokenet fra Firebase Auth. Se kodesnutten nedenfor.
intercept (request: HttpRequest<any>, next: HttpHandler): observable<HttpEvent<any>> {
return this.auth.getIdToken().pipe(
mergeMap((token: any) => {
if (token) {
request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
}
return next.handle(request).pipe(
tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if ((err.status === 401) || (err.status === 403)) {
this.router.navigate([WellknownRoutesConstants.SIGN_IN], { queryParams: { returnUrl: this.router.routerState.snapshot.url }});
}
}
})
);
}));
}
getIdToken (): Observable<any> {
return ngFireAuth.authState.pipe(
tap((user) => {
if (user) {
return observableOf(user.getIdToken());
} else {
return observableOf;
}
}),
catchError(observableOf)
);
}
Svar #1
Grants svar er godt, men det er et problem.
Hvis brukeren logger ut, sender auth.idToken Observable en verdi fordi tokenverdien endres til null. Forespørselsobjektet forblir uendret (men fortsatt initialisert), og dermed gjentas HTTP-forespørselen.
Jeg brukte take(1) for å ta bare den første verdien som ble sendt ut av auth.idToken Observable. Jeg byttet også til switchMap (se take):
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.auth.idToken.pipe(
take(1), // <-------------- Only emit the first value!
switchMap((token: any) => {
if (token) {
request = request.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
}
return next.handle(request);
})
);
}
Svar #2
Dette fungerer for meg siden oppgraderingen til Angular 6/RxJS 6. Her er min interceptor:
import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(
private auth: AngularFireAuth
) {
console.log('token interceptor constructor');
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.auth.idToken.pipe(
mergeMap((token: any) => {
console.log(token);
if (token) {
request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
}
return next.handle(request);
}));
}
}
