mirror of
https://github.com/logto-io/logto.git
synced 2025-02-24 22:05:56 -05:00
chore(connector-wechat*): fix wechat connectors error handler, comments and UTs (#1020)
* fix(connector-wechat*): remove unnecessary comments * fix(connector-wechat*): fix wechat connectors error handler, comments and UTs
This commit is contained in:
parent
458602fd64
commit
5a5083e863
6 changed files with 55 additions and 62 deletions
|
@ -57,15 +57,25 @@ describe('getAccessToken', () => {
|
|||
expect(openid).toEqual('openid');
|
||||
});
|
||||
|
||||
it('throws SocialAuthCodeInvalid error if accessToken not found in response', async () => {
|
||||
it('throws SocialAuthCodeInvalid error if errcode is 40029', async () => {
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, {});
|
||||
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
|
||||
await expect(weChatNativeMethods.getAccessToken('code')).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
);
|
||||
});
|
||||
|
||||
it('throws error if errcode is neither 40029 nor undefined', async () => {
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(true)
|
||||
.reply(200, { errcode: 40_163, errmsg: 'invalid code' });
|
||||
await expect(weChatNativeMethods.getAccessToken('wrong_code')).rejects.toMatchError(
|
||||
new Error('invalid code')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateConfig', () => {
|
||||
|
@ -140,15 +150,16 @@ describe('getUserInfo', () => {
|
|||
});
|
||||
|
||||
it('throws error if `openid` is missing', async () => {
|
||||
nock.cleanAll();
|
||||
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(0, {
|
||||
unionid: 'this_is_an_arbitrary_wechat_union_id',
|
||||
headimgurl: 'https://github.com/images/error/octocat_happy.gif',
|
||||
nickname: 'wechat bot',
|
||||
});
|
||||
nockNoOpenIdAccessTokenResponse();
|
||||
nock(userInfoEndpointUrl.origin)
|
||||
.get(userInfoEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, {
|
||||
errcode: 41_009,
|
||||
errmsg: 'missing openid',
|
||||
});
|
||||
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
new Error('missing openid')
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -156,7 +167,7 @@ describe('getUserInfo', () => {
|
|||
nock(userInfoEndpointUrl.origin)
|
||||
.get(userInfoEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, { errcode: 40_001 });
|
||||
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
|
||||
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
|
||||
);
|
||||
|
|
|
@ -31,9 +31,6 @@ import {
|
|||
WeChatNativeConfig,
|
||||
} from './types';
|
||||
|
||||
// As creating a WeChat Web/Mobile application needs a real App or Website record, the real test is temporarily not finished.
|
||||
// TODO: test with our own wechat mobile/web application (LOG-1910), already tested with other verified wechat web application
|
||||
|
||||
export default class WeChatNativeConnector implements SocialConnector {
|
||||
public metadata: ConnectorMetadata = defaultMetadata;
|
||||
|
||||
|
@ -68,6 +65,7 @@ export default class WeChatNativeConnector implements SocialConnector {
|
|||
access_token: accessToken,
|
||||
openid,
|
||||
errcode,
|
||||
errmsg,
|
||||
} = await got
|
||||
.get(accessTokenEndpoint, {
|
||||
searchParams: { appid, secret, code, grant_type: 'authorization_code' },
|
||||
|
@ -75,10 +73,8 @@ export default class WeChatNativeConnector implements SocialConnector {
|
|||
})
|
||||
.json<AccessTokenResponse>();
|
||||
|
||||
assert(
|
||||
errcode !== 40_029 && accessToken && openid,
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
);
|
||||
assert(errcode !== 40_029, new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
|
||||
assert(!errcode && accessToken && openid, new Error(errmsg ?? ''));
|
||||
|
||||
return { accessToken, openid };
|
||||
};
|
||||
|
@ -87,15 +83,6 @@ export default class WeChatNativeConnector implements SocialConnector {
|
|||
const { code } = codeDataGuard.parse(data);
|
||||
const { accessToken, openid } = await this.getAccessToken(code);
|
||||
|
||||
// TO-DO: @Darcy refactor this
|
||||
// 'openid' is defined as a required input argument in WeChat API doc, but it does not necessarily have to
|
||||
// be the return value from getAccessToken per testing.
|
||||
// In other words, 'openid' is required but the response of getUserInfo is consistent as long as
|
||||
// access_token is valid.
|
||||
// We are expecting to get 41009 'missing openid' response according to the developers doc, but the
|
||||
// fact is that we still got 40001 'invalid credentials' response.
|
||||
assert(openid, new Error('`openid` is required by WeChat API.'));
|
||||
|
||||
try {
|
||||
const { unionid, headimgurl, nickname, errcode, errmsg } = await got
|
||||
.get(userInfoEndpoint, {
|
||||
|
|
|
@ -15,6 +15,7 @@ export type AccessTokenResponse = {
|
|||
refresh_token?: string;
|
||||
scope?: string;
|
||||
errcode?: number;
|
||||
errmsg?: string;
|
||||
};
|
||||
|
||||
export type UserInfoResponse = {
|
||||
|
|
|
@ -57,15 +57,25 @@ describe('getAccessToken', () => {
|
|||
expect(openid).toEqual('openid');
|
||||
});
|
||||
|
||||
it('throws SocialAuthCodeInvalid error if accessToken not found in response', async () => {
|
||||
it('throws SocialAuthCodeInvalid error if errcode is 40029', async () => {
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, {});
|
||||
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
|
||||
await expect(weChatMethods.getAccessToken('code')).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
);
|
||||
});
|
||||
|
||||
it('throws error if errcode is neither 40029 nor undefined', async () => {
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(true)
|
||||
.reply(200, { errcode: 40_163, errmsg: 'invalid code' });
|
||||
await expect(weChatMethods.getAccessToken('wrong_code')).rejects.toMatchError(
|
||||
new Error('invalid code')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateConfig', () => {
|
||||
|
@ -84,18 +94,9 @@ describe('validateConfig', () => {
|
|||
|
||||
const nockNoOpenIdAccessTokenResponse = () => {
|
||||
const accessTokenEndpointUrl = new URL(accessTokenEndpoint);
|
||||
const parameters = new URLSearchParams({
|
||||
appid: '<app-id>',
|
||||
secret: '<app-secret>',
|
||||
code: 'code',
|
||||
grant_type: 'authorization_code',
|
||||
nock(accessTokenEndpointUrl.origin).get(accessTokenEndpointUrl.pathname).query(true).reply(200, {
|
||||
access_token: 'access_token',
|
||||
});
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, {
|
||||
access_token: 'access_token',
|
||||
});
|
||||
};
|
||||
|
||||
describe('getUserInfo', () => {
|
||||
|
@ -107,6 +108,7 @@ describe('getUserInfo', () => {
|
|||
code: 'code',
|
||||
grant_type: 'authorization_code',
|
||||
});
|
||||
|
||||
nock(accessTokenEndpointUrl.origin)
|
||||
.get(accessTokenEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
|
@ -141,15 +143,16 @@ describe('getUserInfo', () => {
|
|||
});
|
||||
|
||||
it('throws error if `openid` is missing', async () => {
|
||||
nock.cleanAll();
|
||||
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(0, {
|
||||
unionid: 'this_is_an_arbitrary_wechat_union_id',
|
||||
headimgurl: 'https://github.com/images/error/octocat_happy.gif',
|
||||
nickname: 'wechat bot',
|
||||
});
|
||||
nockNoOpenIdAccessTokenResponse();
|
||||
nock(userInfoEndpointUrl.origin)
|
||||
.get(userInfoEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, {
|
||||
errcode: 41_009,
|
||||
errmsg: 'missing openid',
|
||||
});
|
||||
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
new Error('missing openid')
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -157,7 +160,7 @@ describe('getUserInfo', () => {
|
|||
nock(userInfoEndpointUrl.origin)
|
||||
.get(userInfoEndpointUrl.pathname)
|
||||
.query(parameters)
|
||||
.reply(200, { errcode: 40_001 });
|
||||
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
|
||||
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
|
||||
);
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
import { weChatConfigGuard, AccessTokenResponse, UserInfoResponse, WeChatConfig } from './types';
|
||||
|
||||
// As creating a WeChat Web/Mobile application needs a real App or Website record, the real test is temporarily not finished.
|
||||
// TODO: test with our own wechat mobile/web application (LOG-1910), already tested with other verified wechat web application
|
||||
// TODO: test with our own WeChat web application (LOG-2719), already tested with other verified WeChat web application
|
||||
|
||||
export default class WeChatConnector implements SocialConnector {
|
||||
public metadata: ConnectorMetadata = defaultMetadata;
|
||||
|
@ -64,6 +64,7 @@ export default class WeChatConnector implements SocialConnector {
|
|||
access_token: accessToken,
|
||||
openid,
|
||||
errcode,
|
||||
errmsg,
|
||||
} = await got
|
||||
.get(accessTokenEndpoint, {
|
||||
searchParams: { appid, secret, code, grant_type: 'authorization_code' },
|
||||
|
@ -71,10 +72,8 @@ export default class WeChatConnector implements SocialConnector {
|
|||
})
|
||||
.json<AccessTokenResponse>();
|
||||
|
||||
assert(
|
||||
errcode !== 40_029 && accessToken && openid,
|
||||
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
|
||||
);
|
||||
assert(errcode !== 40_029, new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
|
||||
assert(!errcode && accessToken && openid, new Error(errmsg ?? ''));
|
||||
|
||||
return { accessToken, openid };
|
||||
};
|
||||
|
@ -83,15 +82,6 @@ export default class WeChatConnector implements SocialConnector {
|
|||
const { code } = codeDataGuard.parse(data);
|
||||
const { accessToken, openid } = await this.getAccessToken(code);
|
||||
|
||||
// TO-DO: @Darcy refactor this
|
||||
// 'openid' is defined as a required input argument in WeChat API doc, but it does not necessarily have to
|
||||
// be the return value from getAccessToken per testing.
|
||||
// In other words, 'openid' is required but the response of getUserInfo is consistent as long as
|
||||
// access_token is valid.
|
||||
// We are expecting to get 41009 'missing openid' response according to the developers doc, but the
|
||||
// fact is that we still got 40001 'invalid credentials' response.
|
||||
assert(openid, new Error('`openid` is required by WeChat API.'));
|
||||
|
||||
try {
|
||||
const { unionid, headimgurl, nickname, errcode, errmsg } = await got
|
||||
.get(userInfoEndpoint, {
|
||||
|
@ -105,7 +95,7 @@ export default class WeChatConnector implements SocialConnector {
|
|||
// 'errmsg' and 'errcode' turn to non-empty values or empty values at the same time. Hence, if 'errmsg' is non-empty then 'errcode' should be non-empty.
|
||||
|
||||
assert(errcode !== 40_001, new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
|
||||
assert(!errcode, new Error(errmsg));
|
||||
assert(!errcode, new Error(errmsg ?? ''));
|
||||
|
||||
return { id: unionid ?? openid, avatar: headimgurl, name: nickname };
|
||||
} catch (error: unknown) {
|
||||
|
|
|
@ -11,6 +11,7 @@ export type AccessTokenResponse = {
|
|||
refresh_token?: string;
|
||||
scope?: string;
|
||||
errcode?: number;
|
||||
errmsg?: string;
|
||||
};
|
||||
|
||||
export type UserInfoResponse = {
|
||||
|
|
Loading…
Add table
Reference in a new issue