5

I have an application with a session that expires after 20 minutes of inactivity. The users of this application are quite lazy, so I suppose they will continue working with the application after their morning coffee and be surprised by the errors the communication with the web API will throw. My idea is to intercept the redirection to the login page the server may provoke with the next access to the web API after the session expiration.

So I wrote an interceptor:

@Injectable()
export class SessionEndInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    {
      const initialUrl = req.url;

      return next.handle(req).pipe(
        map((event: HttpEvent<any>) => {
          const res = (event instanceof HttpResponse) && event as HttpResponse<any>;

          if (res && this.checkIfSessionEnd(initialUrl, res.url)) {
            window.location.href = this.replaceRedirectionWithCurrentLocation(
              res.url
            );
          } else {
            return event;
          }
        })
      );
    }
  }

  private checkIfSessionEnd(initialUrl: string, currentUrl: string): boolean {
    const isInitialUrlLogin = this.isLoginUrl(initialUrl);
    const isResponseUrlLogin = this.isLoginUrl(currentUrl);
    const isRedirectionToLogin = !isInitialUrlLogin && isResponseUrlLogin;
    return isRedirectionToLogin;
  }
  ...
}

But the problem is that this part (event instanceof HttpResponse) is never true, so I can't do res.url and compare the URLs. I would like to know how I can obtain the URL of the response (or any other idea).

UPDATE

Let's suppose the session has expired.

1 - The client (Angular), after pressing a button, makes a GET request to the server.

2 - The server (concretely FormsAuthetication), detects that the session has expired, and sends a 302 code and the URL of the login page.

3 - The client sees it and follows it (there's no way to prevent the browser from following a redirection), and then makes another GET request to the server asking for the login page.

4 - Now the client is receiving the HTML of the login page, and throws an error, because it's waiting for data as JSON.

Well, what I want is, by comparing the URL of the initial request with the current URL and, if they are different and one of them happens to be the login page, redirect the client with window.location.href to the login page, so he has no option other than login again if he wants to continue working.

UPDATE II

I know 302 redirections aren't possible to detect. So what I want is compare the URL of the 200 response of the login page with the initial one (the one that triggered the redirection to the login page).

amedina
  • 2,838
  • 3
  • 19
  • 40
  • Could you explain what you mean by `intercept the redirection to the login page the server may provoke` ? Is your server redirecting your users to a unrelated login page, or does your app have a login page to which you are redirected on HTTP errors of type 400 ? –  Nov 20 '18 at 10:50
  • You can only intercept HttpRequest, not redirections. – Roberto Zvjerković Nov 20 '18 at 10:52
  • But this is how you "intercept" responses: https://stackoverflow.com/questions/45566944/angular-4-3-httpclient-intercept-response – Roberto Zvjerković Nov 20 '18 at 10:54
  • @trichetriche The security is based on FormsAuthentication, when the session expires, it redirects the client to the login page, which happens to be a normal MVC action inside a normal MVC controller. – amedina Nov 20 '18 at 10:59
  • Seems like a .NET library right ? In this case, you can't intercept the request. In case it isn't clear enough, interceptors are only there to handle requests made from Angular. Requests made from the server are handled by your browser itself, meaning Angular has no access to it. –  Nov 20 '18 at 11:01
  • @ritaj Yes, and that's what I have done, but `event` happens to be `{}`. – amedina Nov 20 '18 at 11:02
  • @trichetriche I don't think so. I had a similar problem with jQuery time ago and I managed to solve it. The request is made by Angular, and it knows it, but `event` happens to be `{}`. – amedina Nov 20 '18 at 11:03
  • So it's not the server redirecting you, it's your own application ? Please be specific ... –  Nov 20 '18 at 11:04
  • @trichetriche It's the server, concretely, FormsAuthentication what's redirecting the client. I don't have control over it, when the session expires, it redirects the client to the login page. – amedina Nov 20 '18 at 11:05
  • Okay then Angular has no access to it. Angular make requests on demand (when calling http.get for instance) : if your server makes a redirection, Angular has no control over it, only your server has. –  Nov 20 '18 at 11:06
  • @trichetriche I updated the question with more information, please, check it. – amedina Nov 20 '18 at 11:13
  • Not sure your HTTP error code is the right one, but as you can see in [this question](https://stackoverflow.com/questions/36885556/angular2-watch-for-302-redirect-when-fetching-resource), Angular isn't able to see a redirection, hence making the interceptor useless. If you make a second request and don't get a redirection code, then Angular will be able to process the answer. –  Nov 20 '18 at 11:17
  • (And to complete my first statement, your error code should be 401 -Unauthorized- or 403 -Forbidden-) –  Nov 20 '18 at 11:17
  • @trichetriche Yes, that's why I compare the initial and the current URLs. And, I don't have control over the status codes, because FormsAuthetication manages them. – amedina Nov 20 '18 at 11:20
  • No, you don't understand : your 302 answers never comes to you, your browser handles that for you. You can't compare anything because your page is redirected or refreshed. And if it's that so, then maybe you're using the wrong library to handle your backend. Expired sessions aren't supposed to be redirections, but errors. –  Nov 20 '18 at 11:23
  • @trichetriche XmlHttpRequest object can do that. As I said before, I solved it time ago with jQuery. And no, I don't expect to catch the 302 response, but I expect to catch a 200 response with the URL and HTML code of the login page, that's the URL I compare with the initial one. – amedina Nov 20 '18 at 11:27
  • So now you use a SPA framework, but your server sends you HTML to display ... Look, I tried my best, but it's getting out of hand for me. You're not clear enough for me to understand, and it seems you don't rely on best practices for your application. It's getting way too complicated to follow you, so I'll just wish you good luck with your issue and hope you find a solution. If you do so, please keep me updated, as I'm curious to see the result ! –  Nov 20 '18 at 11:29
  • 1
    @trichetriche Ok, thanks for your efforts :) – amedina Nov 20 '18 at 11:33

0 Answers0