Authorization bearer token Angular 5
Solution 1
I suggest to use HttpInterceptor
for setting default HTTP headers on outgoing requests rather than adding an additional HTTP header to each call.
HTTP Client - Setting default headers @ angular.io
In your example you can do the following:
import { Http, Headers, Response } from '@angular/http';
getLoggedInUser(auth_token): Observable<any> {
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth_token}`
})
return this.http.get(apiUrl, { headers: headers })
}
Solution 2
For get
requests, I used the following code and it works
import { HttpClient, HttpHeaders } from '@angular/common/http';
getServerList(){
var reqHeader = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem('mpManagerToken'))
});
return this.http.get<Server[]>(`${environment.apiUrl}/api/Servers/GetServerList`, { headers: reqHeader });
}
Solution 3
Two things:
headers.append(...)
does not mutate the headers object, so your authorization header is not being sent. You need to doheaders = headers.append(...)
Try
this.http.get<UserList[]>(this.mainUrl, { headers: headers });
Solution 4
In Angular 6 and 7, this method can be used to intercept all HTTP request and add the bearer token.
Implementation tutorial is available here. Youtube, this channel has all the tutorials.
Interceptor component
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpUserEvent,
HttpEvent
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { UserService } from '../shared/user.service';
import { tap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private router: Router) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (req.headers.get('No-Auth') === 'True') {
return next.handle(req.clone());
}
if (localStorage.getItem('userToken') != null) {
const clonedreq = req.clone({
headers: req.headers.set(
'Authorization',
'Bearer ' + localStorage.getItem('userToken')
)
});
return next.handle(clonedreq).pipe(
tap(
succ => {},
err => {
if (err.status === 401) {
// this.router.navigateByUrl('/login');
} else if ((err.status = 403)) {
// this.router.navigateByUrl('/forbidden');
// alert(err.localStorage.getItem('userToken'));
}
}
)
);
} else {
this.router.navigateByUrl('/login');
}
}
}
Guard component
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
Router
} from '@angular/router';
import { Observable } from 'rxjs';
import { UserService } from '../shared/user.service';
import { ToastrService } from 'ngx-toastr';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private router: Router,
private userService: UserService,
private toastr: ToastrService
) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean {
if (localStorage.getItem('userToken') != null) {
const roles = next.data['roles'] as Array<string>;
if (roles) {
const match = this.userService.roleMatch(roles);
if (match) {
return true;
} else {
// tslint:disable-next-line: quotemark
this.toastr.info("You don't have access to this page");
this.router.navigate(['/login']);
// this.router.navigate(['/forbidden']);
return false;
}
} else {
return true;
}
}
this.router.navigate(['/login']);
return false;
}
}
Add it to app.modules.ts
providers: [
ConfirmationDialogService,
UserService,
DoctorService,
{ provide: OwlDateTimeIntl, useClass: DefaultIntl },
{ provide: OWL_DATE_TIME_FORMATS, useValue: MY_MOMENT_FORMATS },
AuthGuard,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
],
Then the guard is added to route
{
path: 'adminPanel',
component: AdminPanelComponent,
canActivate: [AuthGuard],
data: { roles: ['Admin'] }
},
Solution 5
I am not very good at programming,but with a little of try and failure if found this:
getUserList(): Observable<UserList[]> {
let tokenParse = JSON.parse(this.token)
// let myHeaders = new Headers();
// myHeaders.set('Authorization', `Bearer ${tokenParse}`);
// let options = new RequestOptions({ headers: myHeaders});
const users = this.http.get<UserList[]>(this.mainUrl, { headers:new HttpHeaders().append('Authorization', `Bearer ${tokenParse}`)})
// const users = this.http.get<UserList[]>(this.mainUrl, options);
return users
.catch(this.handleError.handleError);
}
It doesn't really matter if I use .set
or .append
, at the end of the day, it works in both cases...
I don't really know what is happening, so, if someone wants to explain it in the comments, you are welcome...
ValRob
Tech Profile: FullStackDeveloper: { Frontend:() => React || Angular, Backend: () => Express || PHP, Database:() => Mongo || Mysql, DevOps: () => ([Docker, Jenkins, Git, Bitbucket]), CMS: () => Drupal || Wordpress } BIO: Hello, I am from Ecuador, currently working in München in Check24 as a Frontend developer. Happy to help!
Updated on January 20, 2022Comments
-
ValRob about 2 years
I am confused about how to create a good header for a simple Get request in Angular 5.
This is what I need to do in Angular:
This is what I have so far:
getUserList(): Observable<UserList[]> { const headers = new Headers(); let tokenParse = JSON.parse(this.token) headers.append('Authorization', `Bearer ${tokenParse}`); const opts = new RequestOptions({ headers: headers }); console.log(JSON.stringify(opts)); const users = this.http.get<UserList[]>(this.mainUrl, opts) return users .catch(this.handleError.handleError); }
This is the response in my console.log:
{"method":null,"headers":{"Authorization":["Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImYwODZlM2FiYTk0ZjVhMjVmNDhiNzlkYmI2YWUwOWY4YzE2MTUyMzg2N2I5MDZiY2MzNWQyNWJiYTZmYTE4YjEwZjA1MjZiNThkZjE2Y2FjIn0.eyJhdWQiOiJmMDExY2M1OC00MGNlLTQzYTktOGY3MS04NDI0OTRlM2E5OTciLCJqdGkiOiJmMDg2ZTNhYmE5NGY1YTI1ZjQ4Yjc5ZGJiNmFlMDlmOGMxNjE1MjM4NjdiOTA2YmNjMzVkMjViYmE2ZmExOGIxMGYwNTI2YjU4ZGYxNmNhYyIsImlhdCI6MTUyMzU1MTQ0NSwibmJmIjoxNTIzNTUxNDQ1LCJleHAiOjE1MjM1NTQ0NDUsInN1YiI6IjIiLCJzY29wZXMiOlsiYXV0aGVudGljYXRlZCIsImFuZ3VkcnUiXX0.E-WdQTl7nPDW0gj0rohfql-QgnAinzvDxPR-pySMrG07XFY9tA6Ex7IL23pDBmKDmQO8RcZKa0L5r6SRQq9_iqzMWzn5Zxp94J9TJrpZ2KGMoLR_FbK_tpC5G5q5vUnCe3q34sH7cPdT_2cI704OWWaYmIUKKpXWUIG0PJw_uKSJ_uOifPv59RZGQkoaQ9gPywDKe-uamm1Faug-Kk2YnFMoEJq7ou19zyxgdpX80ZTPUae67uB0PGLRuvxfGaqVsJ8k0NunAY3-pyUnBwR_3eeuOxf4TyfW2aiOJ9kuPgsfV4Z1JD7nMpNtTHMJaXEyNkBW8RlYHD1pj4dkdnsDmw"]},"body":null,"url":null,"withCredentials":null,"responseType":null}
It looks pretty. But gives me this error
GET http://druang.dd:8080/user-list?_format=json 403 (Forbidden)
There is another clue to solve this mystery. In Sublime text, If I put the mouse over
opts
it says something like:ERROR in src/app/services/userlist.service.ts(33,59): error TS2345: Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'. Types of property 'headers' are incompatible. Type 'Headers' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'. Type 'Headers' is not assignable to type '{ [header: string]: string | string[]; }'. Index signature is missing in type 'Headers'.
Any idea?? Here is the full Git repo THanks for your help!
-
ValRob about 6 years1)
headers = headers.append
gives me: Cannot assign Headers because it is a constant or a read-only property -
GreyBeardedGeek about 6 yearseither change the declaration from
const headers
to let headers` or doconst headers = new Headers().append('Authorization',
Bearer ${tokenParse}`); -
ValRob about 6 yearsWith
let
it said:Type void is not assignable to type 'Headers'
-
ValRob about 6 yearsAnd the other option, works, but when I Set
const opts = new RequestOptions({ headers: headers });
I got :ERROR in src/app/services/userlist.service.ts(33,37): error TS2345: Argument of type '{ headers: void; }' is not assignable to parameter of type 'RequestOptionsArgs'. Types of property 'headers' are incompatible. Type 'void' is not assignable to type 'Headers'.
-
ValRob about 6 yearsAlso, if i forgot about the options, and go straight to the
{headers:headers}
in the http get request, I got this:ERROR in src/app/services/userlist.service.ts(35,59): error TS2345: Argument of type '{ headers: void; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'. Types of property 'headers' are incompatible. Type 'void' is not assignable to type 'HttpHeaders | { [header: string]: string | string[]; }'.
-
ValRob about 6 yearsI found the solution... If you can explain me, thanks!.
const users = this.http.get<UserList[]>(this.mainUrl, { headers:new HttpHeaders().set('Authorization',
Bearer ${tokenParse})})
-
Alator almost 5 yearsJust to add, the token should be prepended by 'Bearer ', so in your example, it would be 'Authorization':
Bearer ${auth_token}
-
Jim over 3 yearsI needed to use HttpHeaders rather than Headers, but after that it all worked. 👍
-
Agung Kessawa over 2 yearsjust out of curiosity, is the use of ` symbol to combine text?
-
Lazar Đorđević over 2 yearsIn my opinion very important answer, I don't know why downvoted. In my case I had post method on server without parameters, so had
this.router.post<string>('https://localhost:5001/api/method', null, {headers: { 'Authorization': `Bearer ${localStorage.getItem('authToken')}`, }}) .subscribe(data => { //now use data window.location.href = data; });
Of course it is better to use interceptor, but I think that it is also important to see simple basic example like this with bothpost
andget
. -
Achala Dissanayake over 2 years@LazarĐorđević Thanks for your comment