简体   繁体   中英

Ionic + Angular: Auth0 JWT not sending token on headers

I'm working on my first Ionic application and already made the authentication part.

But after authenticating, when I do a request using HttpClientModule, it does't have the token on the header and I get 401 from my API made in .net Core.

I've read a lot of post about this topic but no solution seems to fix the problem.

I don't think the problem is in the API because it's works on postman if you have the bearer token on headers.

This is my app.module.ts configuration:

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 {}

I dint checked the use cordova option when creating the app. Maybe it has something to do with it?


UPDATE: So, I've implemented an interceptor like Ronny said but the authorization header still don't appear.

app.mmodule.ts is like before but with this providers:

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

and this is my interceptor class:

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;

    }

  }

}

It says in the console 'Header added.' so its reaching the code. But the header don't show up on the final request. I feel like something in the app is overwriting the headers after this. I'm really confused right now. I appreciate any ideas.

You have to add the token to each request. Create an interceptor, validate that the user has a token, and added it to the request. This is an example:

// 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 && 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);
    }
}

You need an authentication service to manage your user data. In this example, a behavior subject is used for that. Refer to this link for more info: https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial

I managed to solve it. The problem was here:

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

The interceptor was ignoring this promise and returning the request before the .get() was finished to add the header.

I just stored the token in my authentication class so I have it in memory. I guess making the Interceptor wait for the .get() should work to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM