After starting a new application and implementing JWT for authentication, I encountered an unusual issue. The login button sends the request differently across different browsers. In Chrome and Firefox, it sends the request without the body, while in Edge, it submits twice - first without the body, then a second time immediately after with the body intact.
To troubleshoot, I hardcoded the login credentials directly into the post request to simplify the process.
The following code snippets illustrate the header component implementation:
<ul id="links">
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/census">Census</a>
</li>
<li>
<button (click)="login()">Login</button>
</li>
</ul>
Here is the corresponding TypeScript code snippet:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthenticationService } from '../_services/Authentication.Service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor(private _auth: AuthenticationService, private router: Router) { }
ngOnInit() {
}
login() {
this.loading = true;
this._auth.login(this.model.username, this.model.password)
.subscribe(result => {
});
}
}
And here is the Authentication Service implementation:
import { Injectable } from '@angular/core';
import { Http, Headers, Response, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'
@Injectable()
export class AuthenticationService {
public token: string;
constructor(private http: Http) {
// set token if saved in local storage
var currentUser = JSON.parse(localStorage.getItem('currentUser'));
this.token = currentUser && currentUser.token;
}
login(usn: string, psw: string): Observable<boolean> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://localhost:5000/auth', JSON.stringify({ username: "email-removed", password: "password-removed" }), options)
.map((response: Response) => { return true; });
}
}
This issue becomes more evident when examining the network requests in different browsers. Here is a comparison between Chrome and Edge:
Request URL: http://localhost:5000/auth
Request Method: OPTIONS
Status Code: 200 OK
[Chrome Request Details]
...Details of the empty response...
[Edge Request Details]
POST http://localhost:5000/auth HTTP/1.1
Accept: */*
content-type: application/json
...Details of the correct response containing access_token...
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...."
}
An interesting observation is that the backend is a Python/Flask rest. Requests marked as OPTIONS are seen as empty, while those labeled as POST contain the necessary data, as visible in the responses received.