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.