Приложение на Ionic 5 / Angular 9.
Для хранения данных используется
Ionic Data Storage.
auth.guard выглядит так:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthService } from '@app/_services'
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthService
) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const accessToken = this.authService.currentTokenValue;
if(accessToken) {
return true;
}
this.router.navigate(['/login'])
return false;
}
}
auth.service:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Storage } from '@ionic/storage'
import { BehaviorSubject, Observable, from } from 'rxjs'
import { map } from 'rxjs/operators';
import { Token } from '@app/_models'
import { environment } from '@env/environment';
@Injectable({
providedIn: 'root'
})
export class AuthService {
currentTokenSubject = new BehaviorSubject(null)
constructor(
private http: HttpClient,
private storage: Storage,
) {
this.getToken()
}
getToken() {
this.storage.get('accessToken').then(res => {
if (res) {
this.currentTokenSubject.next(res)
}
})
}
public get currentTokenValue(): string {
return this.currentTokenSubject.value;
}
login(username: string, password: string) {
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic ' + btoa(username + ':' + unescape(encodeURIComponent(password)))
})
return this.http.post<Token>(`${environment.apiUrl}/auth/signin`, { }, { headers })
.pipe(map((res: Token) => {
let token = res.token
// store user details and jwt token in local storage to keep user logged in between page refreshes
this.storage.set('accessToken', token);
return token;
}));
}
logout() {
// remove user from local storage to log user out
this.storage.remove('accessToken');
this.currentTokenSubject.next(null);
}
}
ну и jwt.interceptor:
import { Injectable } from '@angular/core'
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'
import { Observable } from 'rxjs'
import { AuthService } from '@app/_services'
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
const currentToken = this.authService.currentTokenValue;
if (currentToken) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentToken}`
}
});
}
return next.handle(request);
}
}
Суть проблемы:
Метод get() Ionic Data Storage
возвращает промис и мне нужно дождаться резолва. Но вся остальная структура работает на Observable.
Получаю что:
Инитициализируется приложение, проходит проверка auth.guard и currentTokenValue() возвращает null. Проверка не проходит и происходит редирект на страницу логина, но промис то реализован и token получен и пользователь может дальше использовать приложение, так как проверка auth.guard возвращает true.
Как правильно все это подружить?