401没有捕获刷新令牌失败事件 [英] 401 is not catching on refresh token failure event

查看:72
本文介绍了401没有捕获刷新令牌失败事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

身份验证服务未注销刷新令牌401错误.而是转到catchError.ts.应用程序如何处理此问题.

Auth Service is not logging out on refresh token 401 error occurred. Instead it goes to catchError.ts. How can the application handle this.

场景1.最初使用基本授权标头获取访问令牌.2.使用访问令牌拨打服务器电话.3.访问权过期后,请调用刷新令牌服务.4.刷新令牌调用成功后,将新令牌用于其余的服务调用.5.在刷新令牌失败时,将返回401错误,但应用程序无法捕获该错误,并且永远不会注销.

Scenarios 1. Initially get access token using Basic Authorization header. 2. Make server call with access token. 3. Once access toekn is expired, call the refresh token service. 4. On refresh token call is success, use the new token for rest of the service call. 5. On refresh toeken failure, 401 error will be returned, but the application is not able to catch the error and its never logging out.

使用Angular 4 Http拦截器

Using Angular 4 Http Interceptor

这是拦截器

import { Injectable, Injector } from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse, HttpClient} from '@angular/common/http';
import * as AppUtils from '../common/app.utils';
import { AuthService } from './auth.service';
import {Observable} from 'rxjs/Rx';
import { 
    Router,
    Event, 
    NavigationStart, RoutesRecognized, NavigationEnd, NavigationCancel, NavigationError
} from '@angular/router'
import { LoaderService } from '../loader/loader.service'
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { EmptyObservable } from 'rxjs/observable/EmptyObservable';
import { catchError, filter, take, switchMap, finalize } from "rxjs/operators";
import { SharedService } from '../common/services/shared.service';

declare var swal: any;

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

 isRefreshingToken: boolean = true;
 tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
 constructor(private inj: Injector, private router: Router) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     const auth = this.inj.get(AuthService)  
       return next.handle(this.addToken(request))
      .pipe(
      catchError((error, ca) => {
        if (error instanceof HttpErrorResponse) {
          switch ((<HttpErrorResponse>error).status) {
            case 401:
              return this.handle401Error(request, next, auth)
            default:
              return ErrorObservable.create(error);
          }
        } else {
          return ErrorObservable.create(error);
        }
      })
      )
  }

addToken(req: HttpRequest<any>): HttpRequest<any> {

    let customReq: any;
    let client_id = 'test'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    if(req.url.indexOf("token?grant_type") < 0 || req.url.indexOf("token?grant_type") == 0){
            customReq = req.clone({
                headers: req.headers.set('Content-Type', 'application/json')
                                    .set('Authorization','Bearer '+ localStorage.getItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN))
            })
                //Set estCode and perscode for Alshif Users
                if(localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)!=null && localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)==="Y"){
                    req.headers.append(AppUtils.ALSHIFA_USER_INFO, localStorage.getItem(AppUtils.DEFAULT_INSTITUTE) +":"+
                    localStorage.getItem(AppUtils.PERSON_CODE));
                }

      }else{
        customReq = req.clone({
          headers: req.headers.set('Authorization','Basic '+ basicheader)
      })
      }
        return customReq;

    }

     handle400Error(error) {
         console.log("400 error");
        if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
            // If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
            return this.logoutUser();
        }

        return EmptyObservable.create();
    }


    handle401Error(req: HttpRequest<any>, next: HttpHandler, auth : any) {
        if (this.isRefreshingToken) {
            this.isRefreshingToken = false;


    let customReq: any;
    let client_id = 'test'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    auth.refreshToken().subscribe((token) => {

                    console.log("token " +JSON.stringify(token));
                    if (token instanceof HttpErrorResponse) {
      if (token.status === 401) {
console.log("error");
      }
                    }
                    if (token) {
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN, token["access_token"]);
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN, token["refresh_token"]);
                        localStorage.setItem(AppUtils.STORAGE_ACCOUNT_EXPIRES_IN, token["expires_in"]);
                        this.tokenSubject.next(token["access_token"]);
                        return next.handle(this.addToken(req));
                    }

                    console.log("refresh failed");
                    // If we don't get a new token, we are in trouble so logout.
                     this.logoutUser();
                     return EmptyObservable.create();

              }, (err) => {
                    console.log("error  2" +err);
                    // If there is an exception calling 'refreshToken', bad news so logout.
                     this.logoutUser();
                      return EmptyObservable.create();
              },() => { 
                    console.log("token finally)");
                    this.isRefreshingToken = true;
                });

              //  )
        } else {
            console.log("this.tokenSubject "+ this.tokenSubject);
            console.log("this.tokenSubjec2 "+ this.tokenSubject.filter(token => token != null));
            return this.tokenSubject
                .filter(token => token != null)
                .take(1)
                .switchMap(token => {
                    return next.handle(this.addToken(req));
                });


        }

    }



 logoutUser(){
     swal({
            title: 'Session Expired',
            text: 'your session has been expired please re login',

            timer: 5000,
            onOpen: () => {
              swal.showLoading()
            }
          }).then((result) => {
            if (result.dismiss === 'timer') {
              this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
              window.location.reload();
            }
          })
   localStorage.clear();
   this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
  // window.location.reload();
   //return Observable.throw("");
 }

这是auth服务类

 import { Injectable, Component, EventEmitter } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpClient, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/retry';
import * as AppUtils from '../common/app.utils';
import { Router } from '@angular/router';
import { SharedService } from '../common/services/shared.service';
import 'rxjs/add/operator/catch';

declare var swal: any;

@Injectable()
export class AuthService {

  cachedRequests: Array<HttpRequest<any>> = [];

  constructor(private router: Router, private http : HttpClient) {

  }

  refreshToken(): Observable<any>{

    let client_id = 'irsauth'; 
    let client_secret= 'secret';
    let basicheader = btoa(client_id +':'+ client_secret);
    let headers = new HttpHeaders();
    headers.set('Authorization', 'Basic ' + basicheader);
    return this.http.get(AppUtils.REFRESH_TOKEN + localStorage.getItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN), { headers: headers })
    .catch((e: any) => Observable.throw(this.errorHandler(e)))


  }

 errorHandler(error: any): void {
   console.log("auth error")
   Observable.throw("");

  }


 logoutUser(){
       localStorage.clear();
   this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
  // window.location.reload();
   //return Observable.throw("");
 }
}


}

推荐答案

这对我有用.检查是否有帮助.基本上,它是Angular Http服务的包装器.

This works for me. Check if this helps. Basically it's a wrapper on Angular Http service.

callHttpGet(url: string) {
  let headers = new Headers({ 
          "Content-Type": "application/json", 
          "Authorization": "Bearer " + 
          localStorage.getItem("accessToken") 
  });
  let options = new RequestOptions({ headers: headers });

  var me = this;
  return this.http.get(url, options)
    .catch(initialError => {
      if (initialError && 
            initialError.status === 401 && 
            initialError.json()["message"] === "Token expired") {
        // token might be expired, try to refresh token
        var tokenObject = new Object();
        tokenObject["token"] = localStorage.getItem("refreshToken");
        return me.authenticatorService.authenticate(tokenObject)
          .flatMap(res => {
            return me.http.get(url, me.options);
          })
          .catch(error => {
            if (error && 
                    error.status === 401 && 
                    (error.json()["message"] === "Refresh token expired" || 
                    error.json()["message"] === "Token expired")) {
              localStorage.clear();
              this.router.navigate(['/login']);
              return Observable.throw(error);
            }
            else {
              return Observable.throw(error);
            }
          });
      }
      else {
        return Observable.throw(initialError);
      }
    });
}

这篇关于401没有捕获刷新令牌失败事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆