I am trying to write an Angular service that will wrap the regular Http service and automatically make authentication calls if Bearer token is not available or invalid.
Here's an illustration of a regular GET call made via the service:
this.httpWithAutomagicAuth
.get("http://localhost:5001/books")
.map(res => res.json())
.subscribe(
data => {
self.data = data;
}
);
And here's my very sloppy implementation for such service. Obviously, I'm not using the right ReactiveX idioms in the code.
As you can easily notice I am trying to build an observable (Observable.create) that is using another observable returned by this.login(). I am sure there is a better way of chaining/nesting observable for this scenario.
Please, suggest improvements that will make code:
- terse
easy to read and understand
@Injectable() export class HttpWebApiAuthService { constructor(private http: Http) { } // ... public get(url: string, options?: RequestOptionsArgs): Observable<Response> { // TODO this code is for test purpose only (basically, it required to enforce the jwtToken retrieval branch execution) // this.clearJwtToken(); if (!this.getJwtToken()) { return Observable.create( (result: Observer<Response>) => { this.login() .map(res => res.json()) .subscribe( data => { this.saveJwtToken(data.id_token); this.executeGet(url, options) .subscribe(authenticationResult => { result.next(authenticationResult); }); }, error => { console.error("Authentication error", error); }, () => { console.info("Authentication complete"); } ); }, error => { console.error("OBSERVABLE error: ", error); }, () => { console.info("OBSERVABLE complete"); } ); } else { return this.executeGet(url, options); } } private login() : Observable<Response> { const authBody = { "client_id": "...", "username": "...", "password": "...", // ... }; const headers = new Headers(); headers.append("Content-Type", "application/json"); return this.http.post("https://AUTH_URL", JSON.stringify(authBody), { headers: headers }); } // ... }