mirror of
https://github.com/supabase/supabase.git
synced 2026-06-04 03:41:38 +08:00
ref: Use local state to improve GitHub integration security (#29321)
This commit is contained in:
@@ -3,12 +3,25 @@ import { toast } from 'sonner'
|
||||
|
||||
import { handleError, post } from 'data/fetchers'
|
||||
import type { ResponseError } from 'types'
|
||||
import { LOCAL_STORAGE_KEYS } from 'lib/constants'
|
||||
|
||||
export type GitHubAuthorizationCreateVariables = {
|
||||
code: string
|
||||
state: string
|
||||
}
|
||||
|
||||
export async function createGitHubAuthorization({ code }: GitHubAuthorizationCreateVariables) {
|
||||
export async function createGitHubAuthorization({
|
||||
code,
|
||||
state,
|
||||
}: GitHubAuthorizationCreateVariables) {
|
||||
const localState = localStorage.getItem(LOCAL_STORAGE_KEYS.GITHUB_AUTHORIZATION_STATE)
|
||||
|
||||
if (state !== localState) {
|
||||
throw new Error('GitHub authorization state mismatch')
|
||||
} else {
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEYS.GITHUB_AUTHORIZATION_STATE)
|
||||
}
|
||||
|
||||
const { data, error } = await post('/platform/integrations/github/authorization', {
|
||||
body: { code },
|
||||
})
|
||||
@@ -31,21 +44,12 @@ export const useGitHubAuthorizationCreateMutation = ({
|
||||
>,
|
||||
'mutationFn'
|
||||
> = {}) => {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation<
|
||||
GitHubAuthorizationCreateData,
|
||||
ResponseError,
|
||||
GitHubAuthorizationCreateVariables
|
||||
>((vars) => createGitHubAuthorization(vars), {
|
||||
async onSuccess(data, variables, context) {
|
||||
// const { projectRef, id } = variables
|
||||
|
||||
// await Promise.all([
|
||||
// queryClient.invalidateQueries(githubAuthorizationKeys.list(projectRef)),
|
||||
// queryClient.invalidateQueries(githubAuthorizationKeys.githubAuthorization(projectRef, id)),
|
||||
// ])
|
||||
|
||||
await onSuccess?.(data, variables, context)
|
||||
},
|
||||
async onError(data, variables, context) {
|
||||
|
||||
@@ -68,6 +68,7 @@ export const LOCAL_STORAGE_KEYS = {
|
||||
// Track position of nodes for schema visualizer
|
||||
SCHEMA_VISUALIZER_POSITIONS: (ref: string, schemaId: number) =>
|
||||
`schema-visualizer-positions-${ref}-${schemaId}`,
|
||||
GITHUB_AUTHORIZATION_STATE: 'supabase-github-authorization-state',
|
||||
}
|
||||
|
||||
export const OPT_IN_TAGS = {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { LOCAL_STORAGE_KEYS } from './constants'
|
||||
import { makeRandomString } from './helpers'
|
||||
|
||||
const GITHUB_INTEGRATION_APP_NAME =
|
||||
process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod'
|
||||
? `supabase`
|
||||
@@ -34,8 +37,15 @@ export function openInstallGitHubIntegrationWindow(type: 'install' | 'authorize'
|
||||
? document.documentElement.clientHeight
|
||||
: screen.height
|
||||
|
||||
const windowUrl =
|
||||
type === 'install' ? GITHUB_INTEGRATION_INSTALLATION_URL : GITHUB_INTEGRATION_AUTHORIZATION_URL
|
||||
let windowUrl
|
||||
if (type === 'install') {
|
||||
windowUrl = GITHUB_INTEGRATION_INSTALLATION_URL
|
||||
} else if (type === 'authorize') {
|
||||
const state = makeRandomString(32)
|
||||
localStorage.setItem(LOCAL_STORAGE_KEYS.GITHUB_AUTHORIZATION_STATE, state)
|
||||
windowUrl = `${GITHUB_INTEGRATION_AUTHORIZATION_URL}&state=${state}`
|
||||
}
|
||||
|
||||
const systemZoom = width / window.screen.availWidth
|
||||
const left = (width - w) / 2 / systemZoom + dualScreenLeft
|
||||
const top = (height - h) / 2 / systemZoom + dualScreenTop
|
||||
|
||||
@@ -4,25 +4,29 @@ import { useParams } from 'common'
|
||||
import { useGitHubAuthorizationCreateMutation } from 'data/integrations/github-authorization-create-mutation'
|
||||
|
||||
const GitHubIntegrationAuthorize = () => {
|
||||
const { code } = useParams()
|
||||
const { code, state } = useParams()
|
||||
|
||||
const { mutate, isSuccess } = useGitHubAuthorizationCreateMutation({
|
||||
const { mutate, isSuccess, isError } = useGitHubAuthorizationCreateMutation({
|
||||
onSuccess() {
|
||||
window.close()
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (code) {
|
||||
mutate({ code })
|
||||
if (code && state) {
|
||||
mutate({ code, state })
|
||||
}
|
||||
}, [code, mutate])
|
||||
}, [code, state, mutate])
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col justify-center items-center gap-4">
|
||||
<h2 className="text-xl">Completing GitHub Authorization...</h2>
|
||||
|
||||
{isSuccess ? <p>You can now close this window.</p> : <p />}
|
||||
{isSuccess ? (
|
||||
<p>You can now close this window.</p>
|
||||
) : (
|
||||
<p>Unable to authorize. Please try again.</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user