0
Fork 0
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:
Darcy Ye 2024-05-29 12:24:04 +08:00 committed by GitHub
parent 3f910af825
commit c95755502d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 3 deletions

View 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.

View file

@ -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,

View file

@ -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);