Samuel Clay
Samuel Clay

Reputation: 41

Interceptor for 401, Renew and Retry Angular 2

ANGULAR 2 - RC5, ADAL.js


Problem

So I'm working on authenticating with Microsoft AD using adal.js and angular 2. I've got the hang of adal.js and can login, refresh tokens, logout, get users, etc etc.

My problem right now has to deal with extending Http and creating a custom class that on a 401 will retry the request that just failed.

Here is basically what I have right now:

export class HttpInterceptor extends Http {
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router, private adal: IgAdal) {
       super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
       return this.intercept(super.request(url, this.getRequestOptionArgs(options)));
    } 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
       return this.intercept(super.get(url, this.getRequestOptionArgs(options)));
    }

    intercept(observable: Observable<Response>): Observable<Response> {
       return observable.catch((err, source) => {
         if (err.status  == 401) {   
            this.adal.acquireTokenObservable().flatMap(data=>{
                // NOT SURE WHAT TO DO HERE...
                return Observable.throw(err);
            })
         } else {
            return Observable.throw(err);
         }
      });
    }
}

This works great when its not a 401, throws the error like it should. Now when I try to call super.get() after a 401 and a new token has been acquired... It doesn't try the request again, instead I get an error like so...

Cannot read property 'subscribe' of undefined

^^^ I think this has something to do with the subscription to request after all has been returned.

I think it's also worth pointing out that I have the main.ts setup just fine as the interceptors are at least working.


My questions are:


Edit 1

    intercept(observable: Observable<Response>): Observable<Response> {
    return observable.catch((err, source) => {
        if (err.status  == 401) {   
            return this.adal.acquireTokenObservable().flatMap(data=>{
               return observable.retry(3);
            })
        } else {
            return Observable.throw(err);
        }
    });
}

Just tried the "retry" rxjs operator.. seems to be doing what I'd like it to do. Now my question is... How do I send someone to the login page after the retry fails?


This is my first stackoverflow question so I appologize if its not the best layout

Thank you!!

Upvotes: 3

Views: 2422

Answers (2)

Samuel Clay
Samuel Clay

Reputation: 41

For anyone looking into this... I ending up doing this.

intercept(observable: Observable<Response>): any {
    return observable.catch((err, source) => {
        if (err.status == 401) {
            return this.adal.acquireTokenObservable().flatMap(data=>{
                if (data === 'User login is required') {
                    this.adal.login();
                }
                return observable;
            })
        } else {
            return Observable.throw(err);
        }
    });
}

Returning the observable stream itself instead of .retry() seems to do the exact same thing and also just retrys 1 time. Otherwise .retry(1) will actually throw 3 seperate errors for some reason.

The

this.adal.acquireTokenObservable()

Is an observable I did using the adal.js library to return a stream with the new token. Still working on a couple other issues regarding retrying certain requests, but this is a good start.

Upvotes: 1

abhishek58g
abhishek58g

Reputation: 145

  1. 401 is unauthorized and hence we do not retry in interceptor and the request is rejected. If you want to retry you can call the acquiretoken API again.
  2. Letting the user decide would be better. Unless the server is down(http resopnses 500,503 and 504) or if there is a network timeout and you don't receive a http response.In these scenarios a retry at developers end would be preferred.
  3. There is no retry function in adal.js library. If you want to retry you need to call the AcquireToken API again.

Upvotes: 0

Related Questions