mirror of
https://github.com/snowball-tools/snowballtools-base
synced 2025-01-24 07:59:05 +00:00
Delete GitHub OAuth app authorization to force re-login
This commit is contained in:
parent
ab72bbb03f
commit
05ee1876a1
@ -34,12 +34,6 @@
|
|||||||
mv environments/local.toml.example environments/local.toml
|
mv environments/local.toml.example environments/local.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
- Set `gitHub.oAuth.clientId` and `gitHub.oAuth.clientSecret` in backend [config file](packages/backend/environments/local.toml)
|
|
||||||
- Client ID and secret will be available after [creating an OAuth app](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app)
|
|
||||||
- In "Homepage URL", type `http://localhost:3000`
|
|
||||||
- In "Authorization callback URL", type `http://localhost:3000/organization/projects/create`
|
|
||||||
- Generate a new client secret after app is created
|
|
||||||
|
|
||||||
### Backend Production
|
### Backend Production
|
||||||
|
|
||||||
- Let us assume the following domains for backend and frontend
|
- Let us assume the following domains for backend and frontend
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
"luxon": "^3.4.4",
|
"luxon": "^3.4.4",
|
||||||
"nanoid": "3",
|
"nanoid": "3",
|
||||||
"nanoid-dictionary": "^5.0.0-beta.1",
|
"nanoid-dictionary": "^5.0.0-beta.1",
|
||||||
|
"node-fetch": "2",
|
||||||
"octokit": "^3.1.2",
|
"octokit": "^3.1.2",
|
||||||
"reflect-metadata": "^0.2.1",
|
"reflect-metadata": "^0.2.1",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
@ -46,6 +47,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express-session": "^1.17.10",
|
"@types/express-session": "^1.17.10",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
|
"@types/node-fetch": "^2.6.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||||
"@typescript-eslint/parser": "^6.18.1",
|
"@typescript-eslint/parser": "^6.18.1",
|
||||||
"better-sqlite3": "^9.2.2",
|
"better-sqlite3": "^9.2.2",
|
||||||
|
@ -294,7 +294,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
unauthenticateGitHub: async (_: any, __: object, context: any) => {
|
unauthenticateGitHub: async (_: any, __: object, context: any) => {
|
||||||
try {
|
try {
|
||||||
return service.unauthenticateGitHub(context.user, { gitHubToken: null });
|
return service.unauthenticateGitHub(context.user);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2,6 +2,7 @@ import assert from 'assert';
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { DeepPartial, FindOptionsWhere } from 'typeorm';
|
import { DeepPartial, FindOptionsWhere } from 'typeorm';
|
||||||
import { Octokit, RequestError } from 'octokit';
|
import { Octokit, RequestError } from 'octokit';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
import { OAuthApp } from '@octokit/oauth-app';
|
import { OAuthApp } from '@octokit/oauth-app';
|
||||||
|
|
||||||
@ -792,7 +793,30 @@ export class Service {
|
|||||||
return { token };
|
return { token };
|
||||||
}
|
}
|
||||||
|
|
||||||
async unauthenticateGitHub (user: User, data: DeepPartial<User>): Promise<boolean> {
|
async unauthenticateGitHub (user: User): Promise<boolean> {
|
||||||
return this.db.updateUser(user, data);
|
const clientId = this.config.gitHubConfig.oAuth.clientId;
|
||||||
|
const clientSecret = this.config.gitHubConfig.oAuth.clientSecret;
|
||||||
|
assert(user.gitHubToken, `GitHub access token is not set for user ${user.ethAddress}`);
|
||||||
|
|
||||||
|
// https://docs.github.com/en/rest/apps/oauth-applications#delete-an-app-authorization
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.github.com/applications/${clientId}/grant`,
|
||||||
|
{
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
// Basic authentication with client ID & secret is needed for OAuth app REST API
|
||||||
|
Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,
|
||||||
|
Accept: 'application/vnd.github.v3+json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
access_token: user.gitHubToken
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(response.ok, Error(response.statusText));
|
||||||
|
|
||||||
|
return this.db.updateUser(user, { gitHubToken: null });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { Organization } from 'gql-client';
|
|||||||
import { Option } from '@material-tailwind/react';
|
import { Option } from '@material-tailwind/react';
|
||||||
import { useDisconnect } from 'wagmi';
|
import { useDisconnect } from 'wagmi';
|
||||||
|
|
||||||
import { useGQLClient } from '../context/GQLClientContext';
|
import { useGQLClient } from 'context/GQLClientContext';
|
||||||
import AsyncSelect from './shared/AsyncSelect';
|
import AsyncSelect from './shared/AsyncSelect';
|
||||||
import {
|
import {
|
||||||
ChevronGrabberHorizontal,
|
ChevronGrabberHorizontal,
|
||||||
@ -36,10 +36,12 @@ const Sidebar = () => {
|
|||||||
setSelectedOrgSlug(orgSlug);
|
setSelectedOrgSlug(orgSlug);
|
||||||
}, [orgSlug]);
|
}, [orgSlug]);
|
||||||
|
|
||||||
const handleLogOut = useCallback(() => {
|
const handleLogOut = useCallback(async () => {
|
||||||
disconnect();
|
disconnect();
|
||||||
|
await client.unauthenticateGithub();
|
||||||
|
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
}, [disconnect, navigate]);
|
}, [disconnect, navigate, client]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full p-4 pt-10">
|
<div className="flex flex-col h-full p-4 pt-10">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import OauthPopup from 'react-oauth-popup';
|
import OauthPopup from 'react-oauth-popup';
|
||||||
|
|
||||||
import { useGQLClient } from '../../../context/GQLClientContext';
|
import { useGQLClient } from 'context/GQLClientContext';
|
||||||
import { Button } from 'components/shared/Button';
|
import { Button } from 'components/shared/Button';
|
||||||
import {
|
import {
|
||||||
GitIcon,
|
GitIcon,
|
||||||
|
@ -7,19 +7,17 @@ import { OctokitProvider } from '../context/OctokitContext';
|
|||||||
const OrgSlug = () => {
|
const OrgSlug = () => {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-5 h-screen bg-snowball-50">
|
<div className="grid grid-cols-5 h-screen bg-snowball-50">
|
||||||
<>
|
<OctokitProvider>
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-4 h-full p-3 overflow-y-hidden">
|
<div className="col-span-4 h-full p-3 overflow-y-hidden">
|
||||||
<div className="bg-white rounded-3xl h-full overflow-y-auto shadow-sm">
|
<div className="bg-white rounded-3xl h-full overflow-y-auto shadow-sm">
|
||||||
<OctokitProvider>
|
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</OctokitProvider>
|
</OctokitProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
24
yarn.lock
24
yarn.lock
@ -5075,6 +5075,14 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
||||||
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
||||||
|
|
||||||
|
"@types/node-fetch@^2.6.11":
|
||||||
|
version "2.6.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24"
|
||||||
|
integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
form-data "^4.0.0"
|
||||||
|
|
||||||
"@types/node-forge@^1.3.0":
|
"@types/node-forge@^1.3.0":
|
||||||
version "1.3.11"
|
version "1.3.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
|
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
|
||||||
@ -8756,7 +8764,7 @@ dotenv@~16.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f"
|
||||||
integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==
|
integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==
|
||||||
|
|
||||||
downshift@^8.2.3:
|
downshift@^8.3.2:
|
||||||
version "8.3.2"
|
version "8.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/downshift/-/downshift-8.3.2.tgz#35cccfdadfe183a9e6bceb1dca68a6a592bb5602"
|
resolved "https://registry.yarnpkg.com/downshift/-/downshift-8.3.2.tgz#35cccfdadfe183a9e6bceb1dca68a6a592bb5602"
|
||||||
integrity sha512-kO5mnwMbWB1OIPgIO4wxK0HtSJbaPzx3XTOcnN36I6i08iVc4C2Fftye3UZYVN+W03b13o1kEmN2118G5vcgeQ==
|
integrity sha512-kO5mnwMbWB1OIPgIO4wxK0HtSJbaPzx3XTOcnN36I6i08iVc4C2Fftye3UZYVN+W03b13o1kEmN2118G5vcgeQ==
|
||||||
@ -13627,6 +13635,13 @@ node-fetch-native@^1.4.0, node-fetch-native@^1.4.1, node-fetch-native@^1.6.1:
|
|||||||
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.2.tgz#f439000d972eb0c8a741b65dcda412322955e1c6"
|
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.2.tgz#f439000d972eb0c8a741b65dcda412322955e1c6"
|
||||||
integrity sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==
|
integrity sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==
|
||||||
|
|
||||||
|
node-fetch@2, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7:
|
||||||
|
version "2.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||||
|
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url "^5.0.0"
|
||||||
|
|
||||||
node-fetch@2.6.7:
|
node-fetch@2.6.7:
|
||||||
version "2.6.7"
|
version "2.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||||
@ -13634,13 +13649,6 @@ node-fetch@2.6.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url "^5.0.0"
|
whatwg-url "^5.0.0"
|
||||||
|
|
||||||
node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7:
|
|
||||||
version "2.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
|
||||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
|
||||||
dependencies:
|
|
||||||
whatwg-url "^5.0.0"
|
|
||||||
|
|
||||||
node-forge@^1, node-forge@^1.3.1:
|
node-forge@^1, node-forge@^1.3.1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
||||||
|
Loading…
Reference in New Issue
Block a user