mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
fix(connector): fix GitHub connector GET /emails forbidden error (#5925)
* fix(connector): fix GitHub connector GET /emails forbidden error * chore: adopt suggestion Co-authored-by: Gao Sun <gao@silverhand.io> --------- Co-authored-by: Gao Sun <gao@silverhand.io>
This commit is contained in:
parent
3f910af825
commit
c95755502d
3 changed files with 44 additions and 3 deletions
7
.changeset/olive-deers-wink.md
Normal file
7
.changeset/olive-deers-wink.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
"@logto/connector-github": patch
|
||||
---
|
||||
|
||||
fix `GET /users/emails` API requests break social sign-in flow error
|
||||
|
||||
Previously, the GET /users/emails API was returning a 403 Forbidden error when the endpoint is not accessible. This will break the social sign-in flow in previous version, so we handled this error and return an empty array instead. In this way, the social sign-in flow will continue but with `userEmails` as an empty array, and should provide enough information for further investigation.
|
|
@ -162,6 +162,33 @@ describe('getUserInfo', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should fallback to empty array when can not access to GET /users/emails endpoint', async () => {
|
||||
nock(userInfoEndpoint).get('').reply(200, {
|
||||
id: 1,
|
||||
avatar_url: 'https://github.com/images/error/octocat_happy.gif',
|
||||
name: 'monalisa octocat',
|
||||
foo: 'bar',
|
||||
});
|
||||
nock(userEmailsEndpoint).get('').reply(403, []);
|
||||
const connector = await createConnector({ getConfig });
|
||||
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, vi.fn());
|
||||
expect(socialUserInfo).toStrictEqual({
|
||||
id: '1',
|
||||
avatar: 'https://github.com/images/error/octocat_happy.gif',
|
||||
name: 'monalisa octocat',
|
||||
email: undefined,
|
||||
rawData: {
|
||||
userInfo: {
|
||||
id: 1,
|
||||
avatar_url: 'https://github.com/images/error/octocat_happy.gif',
|
||||
name: 'monalisa octocat',
|
||||
foo: 'bar',
|
||||
},
|
||||
userEmails: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert `null` to `undefined` in SocialUserInfo', async () => {
|
||||
nock(userInfoEndpoint).get('').reply(200, {
|
||||
id: 1,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { assert, conditional } from '@silverhand/essentials';
|
||||
import { assert, conditional, trySafe } from '@silverhand/essentials';
|
||||
|
||||
import {
|
||||
ConnectorError,
|
||||
|
@ -124,9 +124,16 @@ const getUserInfo =
|
|||
});
|
||||
|
||||
try {
|
||||
const [userInfo, userEmails] = await Promise.all([
|
||||
/**
|
||||
* If user(s) is using GitHub Apps (instead of OAuth Apps), they can customize
|
||||
* "Account permissions" and restrict the "email addresses" visibility, and GitHub
|
||||
* hence throws error instead of returning an empty array.
|
||||
*
|
||||
* We try catch the error and return an empty array instead.
|
||||
*/
|
||||
const [userInfo, userEmails = []] = await Promise.all([
|
||||
authedApi.get(userInfoEndpoint).json(),
|
||||
authedApi.get(userEmailsEndpoint).json(),
|
||||
trySafe(authedApi.get(userEmailsEndpoint).json()),
|
||||
]);
|
||||
|
||||
const userInfoResult = userInfoResponseGuard.safeParse(userInfo);
|
||||
|
|
Loading…
Reference in a new issue