Ionic Angular: Auth0 JWT не отправляет токен в заголовках

#angular #typescript #ionic-framework #jwt

#angular #typescript #ionic-framework #jwt

Вопрос:

Я работаю над своим первым приложением Ionic и уже выполнил часть аутентификации.

Но после аутентификации, когда я выполняю запрос с использованием HttpClientModule, в заголовке нет токена, и я получаю 401 из моего API, созданного в .net Core.

Я прочитал много сообщений по этой теме, но, похоже, никакое решение не устраняет проблему.

Я не думаю, что проблема в API, потому что он работает на postman, если у вас есть токен на предъявителя в заголовках.

Это моя конфигурация app.module.ts:

 import { AuthModule } from './auth/auth.module';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';


import { IonicStorageModule, Storage } from '@ionic/storage';
import { JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt';

export function getAuthScheme(request) {
  return 'Bearer ';
}

export function jwtOptionsFactory(storage) {
  return {
      tokenGetter: () => {
      return storage.get('ACCESS_TOKEN');
    },
    authScheme: getAuthScheme,
    whitelistedDomains: ['localhost:44326', 'https://localhost:44326', 'https://localhost:44326/', 'localhost']
  };
}

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    AuthModule,
    IonicStorageModule.forRoot(),
    JwtModule.forRoot({
      jwtOptionsProvider: {
        provide: JWT_OPTIONS,
        useFactory: jwtOptionsFactory,
        deps: [Storage],
      },
    }),
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

  

Я не проверял параметр использовать cordova при создании приложения. Может быть, это как-то связано с этим?


ОБНОВЛЕНИЕ: Итак, я внедрил перехватчик, как сказал Ронни, но заголовок авторизации по-прежнему не отображается.

app.mmodule.ts такой же, как и раньше, но с этими поставщиками:

   providers: [
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptorProvider, multi: true },
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    StatusBar,
    SplashScreen,
  ],
  

и это мой класс перехватчика:

 import { Storage } from '@ionic/storage';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class JwtInterceptorProvider implements HttpInterceptor {
  constructor(private storage: Storage) {
    console.log(`Hello from JwtInterceptor`);
  }

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    this.storage.get('ACCESS_TOKEN').then((token) => {
      if (token) {
        const clonedRequest = this.addToken(request, token);
        return next.handle(clonedRequest);
      }
    });

    return next.handle(request);
  }

  private addToken(request: HttpRequest<any>, token: any) {

    if (token) {

      console.log(`*******************************************************`);
      console.log(`Bearer ${token}`);

      const headers = {
        Authorization: `Bearer ${token}`,
      };
      if (request.responseType === 'json') {
        console.log('Json request.');
        headers['Content-Type'] = 'application/json';
      }

      console.log('Header added.');

      console.log(`*******************************************************`);
      return request;

    }

  }

}
  

В консоли написано «Добавлен заголовок». таким образом, он достигает кода. Но заголовок не отображается в конечном запросе. Я чувствую, что что-то в приложении перезаписывает заголовки после этого.
Я сейчас действительно в замешательстве. Я ценю любые идеи.

Ответ №1:

Вы должны добавлять токен к каждому запросу. Создайте перехватчик, подтвердите, что у пользователя есть токен, и добавьте его в запрос. Это пример:

 // JWT interceptor
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from 
'@angular/common/http';
import { Observable } from 'rxjs';

import { AuthenticationService } from '../services/authentication.service';


@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    const currentAuthToken = this.authenticationService.currentAuthTokenValue;
    if (currentAuthToken amp;amp; currentAuthToken.token) {
        const headers = {
            'Authorization': `Bearer ${currentAuthToken.token}`,
        };
        if (request.responseType === 'json') {
            headers['Content-Type'] = 'application/json';
        }
        request = request.clone({
            setHeaders: headers
        });
    }

    return next.handle(request);
    }
}
  

Вам нужна служба аутентификации для управления вашими пользовательскими данными. В этом примере для этого используется субъект поведения. Обратитесь к этой ссылке для получения дополнительной информации:https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial

Комментарии:

1. Спасибо за ответ! Я внедрил перехватчик, как вы сказали, и проверил все в примере руководства. Но авторизация по-прежнему не отображается в заголовках. Я действительно запутался здесь. Я обновляю код в исходном сообщении.

2. Я думаю, вам не хватает этой строки: request = request.clone({ setHeaders: headers }); Именно здесь заголовок добавляется к запросу.

Ответ №2:

Мне удалось это решить. Проблема была здесь:

this.storage.get('ACCESS_TOKEN').then(...)

Перехватчик игнорировал это обещание и возвращал запрос до того, как .get() был завершен для добавления заголовка.

Я просто сохранил токен в своем классе аутентификации, поэтому он у меня есть в памяти. Я думаю, что перехватчик должен ждать .get(), чтобы сработать.