Janik Spies
Janik Spies

Reputation: 427

Ionic: 401 when using Safari only

I've got an Ionic/Angular app with the following code:

Login(username: string, password: string) {
    this.isLoading = true;
    this.authService.getToken(username, password).subscribe(
        (data: any) => {
          this.loadingCtrl.create({keyboardClose: true, message: 'Logging in...'})
          .then(async loadingEl => {
              loadingEl.present();
              await this.moviesService.fetchMovies(data.access).toPromise(); // <-- Here comes the 401
              this.seriesService.fetchSeries(data.access).subscribe(
                () => {
                  this.authService.login(username, password);
                  this.isLoading = false;
                  loadingEl.dismiss();
                  this.router.navigateByUrl('/tabs/dashboard');
                }
              );
          });
        }
      );
  }
fetchMovies(token: string){

    this.httpOptions = {
      headers: new HttpHeaders({
        'Authorization': 'Bearer ' + token,
        'Content-Type': 'application/json',
      })
    };

    return this.http.get<{[key: string]: MovieData}>(this.url, this.httpOptions).pipe(
      map(async res => {
        for (const key in res) {
          if (res.hasOwnProperty(key)) {
            let t: any;
            t = await this.http.get(res[key].genre, this.httpOptions).toPromise();
            this._movies.push(
              new Movie(
                key,
                res[key].title,
                res[key].desc,
                res[key].year,
                t.title,
                res[key].thumbnail,
                res[key].movie,
                res[key].createdUser,
                res[key].premium,
                res[key].hd_quality,
                res[key].audio_quality));
          }
        }
      })
    );
  } 

When I try it in any browser except safari everything works fine. As soon as I try it in Safari I get an 401 Error on my reqeust.

Does anyone of you had this problem aswell?

Upvotes: 1

Views: 256

Answers (3)

Timothy
Timothy

Reputation: 3593

Its not an answer. Its just code recommendations, coz it can be massively improved, you don't need to mix Observables with Promises, particularly nested subscriptions are gonna cause immense memory leak

this.authService.getToken(username, password).pipe(
    tap(_ => { this.loadingCtrl.create({keyboardClose: true, message: 'Logging in...'}) }),
    switchMap(_ => this.authService.login(username, password).pipe(
            catchErrors(err => {
                // Handle quth errors here, i.e. this.router.navigateByUrl('incorrect-login');
                return EMPTY; // Complete observable if user unauthenticated
                // so next operator will not beached
            })
        )),
    switchMap(data => combineLatest([
        this.moviesService.fetchMovies(data.access),
        this.seriesService.fetchSeries(data.access),
    ])),
    tap(([ movies, series ]) => {
        this.isLoading = false;
        loadingEl.dismiss();
        this.router.navigateByUrl('/tabs/dashboard');
    }),
).subscribe()

this approach faster, coz it executes fetchMovies and fetchSeries in parallel.

Upvotes: 0

Janik Spies
Janik Spies

Reputation: 427

Make sure your URL has a / at the end.

Example: www.myawsomeapi/books/

Hope I can help someone with that :)

Upvotes: 1

Adams Jhonson
Adams Jhonson

Reputation: 51

for some reason Safari does not sent the authentication for scripts with 'type="module"'. The way to solve this is to add 'crossorigin="use-credentials"' to the script tag.

When using Angular 8 you can let Angular add this to the script tags by updating the angular.json file:

{
   ...,
   "build": {
     "builder": ...,
     "options": {
        ...
        "crossOrigin": "use-credentials"
     }
   }
}

Upvotes: 4

Related Questions