[英]How to implement auto refresh token in graphql for jwt based authentication?
I am trying to figure out this scenario for my JWT based authentication in Apollo based graphql server (2.0) . 我试图在基于Apollo的graphql server (2.0)中为基于JWT的身份验证找出这种情况。
Basically after login a user gets accessToken and refreshToken from server. 基本上在登录后,用户从服务器获取accessToken和refreshToken。
AccessToken gets expired after certain period of time and server sends an error message indicating that token expired ( TokenExpiredError ) and then client need to communicate with server for new accessToken via passing refreshToken. AccessToken在一段时间后过期,服务器发送一条错误消息,表明令牌已过期( TokenExpiredError ),然后客户端需要通过传递refreshToken与服务器进行新的accessToken通信。
Flow is as following - 流量如下 -
I have already implemented refreshToken mutation on client side but can't figure out about when error occurs stop all requests -> request new token -> make all pending request again and if refresh token is expired logout user. 我已经在客户端实现了refreshToken变异但是无法弄清楚何时发生错误停止所有请求 - >请求新令牌 - >再次进行所有待处理请求以及刷新令牌是否已过期注销用户。
I followed this approach to solve my problem finally 我按照这种方法最终解决了我的问题
Posting my approach for others 向别人发布我的方法
// @flow
import { ApolloLink, Observable } from 'apollo-link';
import type { ApolloClient } from 'apollo-client';
import type { Operation, NextLink } from 'apollo-link';
import { refreshToken2, getToken } from './token-service';
import { GraphQLError } from 'graphql';
export class AuthLink extends ApolloLink {
tokenRefreshingPromise: Promise<boolean> | null;
injectClient = (client: ApolloClient): void => {
this.client = client;
};
refreshToken = (): Promise<boolean> => {
//if (!this.tokenRefreshingPromise) this.tokenRefreshingPromise = refreshToken(this.client);
if (!this.tokenRefreshingPromise) this.tokenRefreshingPromise = refreshToken2();
return this.tokenRefreshingPromise;
};
setTokenHeader = (operation: Operation): void => {
const token = getToken();
if (token) operation.setContext({ headers: { authorization: `Bearer ${token}` } });
};
request(operation: Operation, forward: NextLink) {
// set token in header
this.setTokenHeader(operation);
// try refreshing token once if it has expired
return new Observable(observer => {
let subscription, innerSubscription, inner2Subscription;
try {
subscription = forward(operation).subscribe({
next: result => {
if (result.errors) {
console.log("---->", JSON.stringify(result.errors))
for (let err of result.errors) {
switch (err.extensions.code) {
case 'E140':
console.log('E140', result)
observer.error(result.errors)
break;
case 'G130':
this.refreshToken().then(response => {
if (response.data && !response.errors) {
this.setTokenHeader(operation);
innerSubscription = forward(operation).subscribe(observer);
} else {
console.log("After refresh token", JSON.stringify(response));
observer.next(response)
}
}).catch(console.log);
break;
}
}
}
observer.next(result)
},
complete: observer.complete.bind(observer),
error: netowrkError => {
observer.error(netowrkError);
}
},
});
} catch (e) {
observer.error(e);
}
return () => {
if (subscription) subscription.unsubscribe();
if (innerSubscription) innerSubscription.unsubscribe();
if (inner2Subscription) inner2Subscription.unsubscribe();
};
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.