使用graphql和apollo客户端刷新用于角度的令牌 [英] refresh token for angular using graphql and apollo client

查看:78
本文介绍了使用graphql和apollo客户端刷新用于角度的令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置刷新令牌策略,以在我的第一个请求返回401时使用GraphQL和apollo客户端刷新angular 9中的JWT.

我为我创建我的apolloclient的graphql设置了一个新的angular模块.即使通过身份验证的请求,一切也都很好,但是我还需要正常的刷新令牌策略正常工作(刷新令牌周期完成后重新制作并返回原始请求).我发现只有很少的资源可以帮助解决此问题,而且我已经非常接近了-我唯一缺少的是从刷新令牌observable中返回observable.

以下是应该起作用的代码:

 从'@ angular/core'导入{NgModule};从'apollo-angular-link-http'导入{HttpLinkModule,HttpLink};从"./authentication/services/authentication.service"导入{AuthenticationService};从"apollo-link"导入{ApolloLink};从"apollo-cache-inmemory"导入{InMemoryCache};从'apollo-angular'导入{ApolloModule,APOLLO_OPTIONS};从"apollo-link-error"导入{onError};导出函数createApollo(httpLink:HttpLink,authenticationService:AuthenticationService){const authLink = new ApolloLink((operation,forward)=> {operation.setContext({标头:{授权:'Bearer'+ localStorage.getItem('auth_token')}});向前返回(操作);});const errorLink = onError(({{forward,graphQLErrors,networkError,operation})=> {如果(graphQLErrors){graphQLErrors.map(({{message,location,path})=>{如果(message.toLowerCase()==='未经授权'){authenticationService.refreshToken().subscribe(()=> {向前返回(操作);});}});}});返回 {链接:errorLink.concat(authLink.concat(httpLink.create({uri:'http://localhost:3000/graphql'})))),缓存:新的InMemoryCache(),};}@NgModule({导出:[ApolloModule,HttpLinkModule],提供者:[{提供:APOLLO_OPTIONS,useFactory:createApollo,deps:[HttpLink,AuthenticationService]}]})导出类GraphqlModule {} 

我知道我的请求第二次正常工作,因为如果我从authenticationService订阅中可观察到的forward(operation)中注销结果,那么我会在最初的401失败后看到结果.

  if(message.toLowerCase()==='未经授权'){authenticationService.refreshToken().subscribe(()=> {return forward(operation).subscribe(result => {console.log(result);});});} 

上面的代码向我显示了原始请求中的数据,但没有将其传递给最初称为graphql的组件.

我距离可观察性专家还很远,但是我想我需要做一些地图(flatmap,mergemap等)才能使此返回正常工作,但是我不知道.

任何帮助将不胜感激

TIA

编辑#1:这使我更加接近,因为它实际上是在AuthenticationService中订阅我的方法(我在tap()中看到结果)

  const errorLink = onError(({{forward,graphQLErrors,networkError,operation})=> {如果(graphQLErrors){如果(graphQLErrors [0] .message.toLowerCase()==='未经授权'){返回authenticationService.refreshToken().管道(switchMap(()=>转发(操作)));}}}); 

我现在看到抛出此错误:

core.js:6210错误TypeError:您提供了一个无效对象,该对象应用于流.您可以提供一个Observable,Promise,Array或Iterable.

编辑#2:包括onError()函数签名的屏幕截图:

编辑#3这是最终的工作解决方案,以防其他人遇到此问题并需要其倾斜.我不喜欢必须更新我的服务方法以返回一个承诺,然后将该承诺转换为一个Observable-但是正如@AndreiGătej为我发现的那样,该Observable来自另一个命名空间.

 从'@ angular/core'导入{NgModule};从'apollo-angular-link-http'导入{HttpLinkModule,HttpLink};从"./authentication/services/authentication.service"导入{AuthenticationService};从"apollo-link"导入{ApolloLink};从"apollo-cache-inmemory"导入{InMemoryCache};从'apollo-angular'导入{ApolloModule,APOLLO_OPTIONS};从"apollo-link-error"导入{onError};从'apollo-link'导入{Observable};导出函数createApollo(httpLink:HttpLink,authenticationService:AuthenticationService){const authLink = new ApolloLink((operation,forward)=> {operation.setContext({标头:{授权:'Bearer'+ localStorage.getItem('auth_token')}});向前返回(操作);});const errorLink = onError(({{forward,graphQLErrors,networkError,operation})=> {如果(graphQLErrors){如果(graphQLErrors.some(x => x.message.toLowerCase()==='未经授权')){返回promiseToObservable(authenticationService.refreshToken().toPromise()).flatMap(()=> forward(operation));}}});返回 {链接:errorLink.concat(authLink.concat(httpLink.create({uri:'/graphql'}))),缓存:新的InMemoryCache(),};}const promiseToObservable =(promise:Promise< any>)=>new Observable((subscriber:any)=> {然后答应值=>{如果(subscriber.closed){返回;}Subscriber.next(value);Subscriber.complete();},err =>subscription.error(err));});@NgModule({导出:[ApolloModule,HttpLinkModule],提供者:[{提供:APOLLO_OPTIONS,useFactory:createApollo,deps:[HttpLink,AuthenticationService]}]})导出类GraphqlModule {} 

解决方案

我对GraphQL不太熟悉,但是我认为这应该可以工作:

  if(message.toLowerCase()==='未经授权'){返回authenticationService.refreshToken().管道(switchMap(()=>转发(操作)));} 

此外,如果您想了解 mergeMap (和 concatMap )的工作方式,可以看看 解决方案

I'm not quite familiar with GraphQL, but I think this should work fine:

if (message.toLowerCase() === 'unauthorized') {
return authenticationService.refreshToken()
  .pipe(
    switchMap(() => forward(operation))
  );
}

Also, if you'd like to know about how mergeMap(and concatMap) work, you can have a look at this answer.

switchMap keeps only one active inner observable and as soon as an outer value comes in, the current inner observable will be unsubscribed and a new one will be created, based on the newly arrived outer value and the provided function.

这篇关于使用graphql和apollo客户端刷新用于角度的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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