Angular Как использовать перехватчик для обновления токена авторизации
У меня есть два токена, token_a длится очень долго. token_a используется для генерации token_b. token_b длится недолго. token_b используется для большинства вызовов API. Тем не менее, мне нужен автоматический способ регенерировать этот токен, когда он истек.
Я пытаюсь использовать для этого перехватчик, который добавит заголовок авторизации ко всем http-вызовам. Однако, если он находит, что токен истек, он пытается восстановить токен и установить заголовок.
auth.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/observable';
import 'rxjs/add/operator/do';
import { AuthService } from './../services/auth/auth.service';
import { JwtService } from './../services/jwt/jwt.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService, private jwt: JwtService) {
console.log('Interceptor Init');
}
setHeader(req) {
const authToken = this.auth.getProfileToken();
const authReq = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + authToken)
});
return authReq;
}
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('Intercepting');
const InterceptorSkipHeader = 'X-Skip-Interceptor';
console.log(req);
if (req.headers.has(InterceptorSkipHeader)) {
console.log('Skipping');
const headers = req.headers.delete(InterceptorSkipHeader);
return next.handle(req.clone({ headers }));
}
if (this.auth.hasProfileToken() && this.auth.isProfileTokenExpired()) {
console.log('Intercepter Refreshing Token Here');
const t = localStorage.getItem('token');
this.jwt.generate(t).subscribe((res) => {
if (res) {
localStorage.setItem('profile_token', res.token);
const auth_req = this.setHeader(req);
console.log('here1');
return next.handle(auth_req);
}
}, (err) => {
console.log(err);
});
}
console.log('end');
const authReq = this.setHeader(req);
console.log('end interceptor');
return next.handle(authReq);
}
}
Тем не менее, я заметил, что мои вызовы API, такие как следующий, который запускается при нажатии кнопки и получает данные, используя источник данных из внутреннего ресурса. Кажется, его вызывают до того, как перехватчик завершит восстановление нового токена и установит заголовок.
jobs.datasource.ts
this.jobService.all(params).pipe(
catchError(() => of([])),
finalize(() => {
this.page = params.offset / 15 + 1;
this.offset = params.offset;
})
)
.subscribe((jobs) => {
console.log('here 2');
console.log(jobs);
this.loadingSubject.next(false);
this.jobsSubject.next(jobs.data);
(jobs.next) ? this.nextSubject.next(true) : this.nextSubject.next(false);
});
Я только это происходит, потому что я добавил 2 отдельных журнала консоли в каждом файле. console.log("here 2")
в jobs.datasource вызывается раньше console.log("here 1")
в аут.интерцепторе.
Я полагаю, потому что у службы jwt.generate есть флаг пропуска перехватчика, это вызывает у меня проблему. К сожалению, я не знаю, как справиться с этим. Jwt.generate внутри перехватчика вызывает перехватчик.