Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-wtih-vscode-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- master

jobs:
build:
build-with-vscode-build:
strategy:
matrix:
os: [macos-14]
Expand Down
14 changes: 10 additions & 4 deletions functions/api/github-auth-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ const createResponseHtml = (text: string, script: string) => `

// return the data to the opener window by postMessage API,
// and close current window if successfully connected
const createAuthorizeResultHtml = (data: Record<any, any>, origins: string) => {
const createAuthorizeResultHtml = (data: Record<any, any>, state: string, origins: string) => {
const errorText = 'Failed! You can close this window and retry.';
const successText = 'Connected! You can now close this window.';
const resultStr = `{ type: 'authorizing', payload: ${JSON.stringify(data)} }`;
const resultStr = JSON.stringify({
type: 'authorizing',
payload: data,
state: state.replace(/[^a-zA-Z0-9]/g, ''),
}).replace(/</g, '\\u003c');
const script = `
'${origins}'.split(',').forEach(function(allowedOrigin) {
window.opener.postMessage(${resultStr}, allowedOrigin);
Expand All @@ -44,10 +48,12 @@ export const onRequest: PagesFunction<{
GITHUB_OAUTH_SECRET: string;
GITHUB1S_ALLOWED_ORIGINS: string;
}> = async ({ request, env }) => {
const code = new URL(request.url).searchParams.get('code');
const searchParams = new URL(request.url).searchParams;
const code = searchParams.get('code');

const createResponse = (status, data) => {
const body = createAuthorizeResultHtml(data, env.GITHUB1S_ALLOWED_ORIGINS);
const state = searchParams.get('state') || '';
const body = createAuthorizeResultHtml(data, state, env.GITHUB1S_ALLOWED_ORIGINS);
return new Response(body, { status, headers: { 'content-type': 'text/html' } });
};

Expand Down
19 changes: 12 additions & 7 deletions functions/api/gitlab-auth-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
* @author netcon
*/

const AUTH_REDIRECT_URI = 'https://auth.gitlab1s.com/api/gitlab-auth-callback';

const createResponseHtml = (text: string, script: string) => `
<!DOCTYPE html>
<html lang="en">
Expand All @@ -20,10 +18,14 @@ const createResponseHtml = (text: string, script: string) => `

// return the data to the opener window by postMessage API,
// and close current window if successfully connected
const createAuthorizeResultHtml = (data: Record<any, any>, origins: string) => {
const createAuthorizeResultHtml = (data: Record<any, any>, state: string, origins: string) => {
const errorText = 'Failed! You can close this window and retry.';
const successText = 'Connected! You can now close this window.';
const resultStr = `{ type: 'authorizing', payload: ${JSON.stringify(data)} }`;
const resultStr = JSON.stringify({
type: 'authorizing',
payload: data,
state: state.replace(/[^a-zA-Z0-9]/g, ''),
}).replace(/</g, '\\u003c');
const script = `
'${origins}'.split(',').forEach(function(allowedOrigin) {
window.opener.postMessage(${resultStr}, allowedOrigin);
Expand All @@ -45,11 +47,14 @@ export const onRequest: PagesFunction<{
GITLAB_OAUTH_ID: string;
GITLAB_OAUTH_SECRET: string;
GITLAB1S_ALLOWED_ORIGINS: string;
GITLAB_OAUTH_REDIRECT_URI: string;
}> = async ({ request, env }) => {
const code = new URL(request.url).searchParams.get('code');
const searchParams = new URL(request.url).searchParams;
const code = searchParams.get('code');

const createResponse = (status, data) => {
const body = createAuthorizeResultHtml(data, env.GITLAB1S_ALLOWED_ORIGINS);
const state = searchParams.get('state') || '';
const body = createAuthorizeResultHtml(data, state, env.GITLAB1S_ALLOWED_ORIGINS);
return new Response(body, { status, headers: { 'content-type': 'text/html' } });
};

Expand All @@ -65,7 +70,7 @@ export const onRequest: PagesFunction<{
code,
client_id: env.GITLAB_OAUTH_ID,
client_secret: env.GITLAB_OAUTH_SECRET,
redirect_uri: AUTH_REDIRECT_URI,
redirect_uri: env.GITLAB_OAUTH_REDIRECT_URI,
grant_type: 'authorization_code',
}),
headers: { accept: 'application/json', 'content-type': 'application/json' },
Expand Down
1 change: 0 additions & 1 deletion scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import path from 'path';
import fs from 'fs-extra';
import cp from 'child_process';
import { executeCommand, PROJECT_ROOT } from './utils.js';

const main = () => {
Expand Down
22 changes: 11 additions & 11 deletions src/github-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,30 @@
*/

const GITHUB_ORIGIN = 'https://github.com';
const AUTH_PAGE_ORIGIN = 'https://auth.github1s.com';
const AUTH_REDIRECT_URI = `${AUTH_PAGE_ORIGIN}/api/github-auth-callback`;
const CLIENT_ID = 'eae6621348403ea49103';
const OAUTH_REDIRECT_URI = `${location.origin}/api/github-auth-callback`;
const OPEN_WINDOW_FEATURES =
'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=800,height=520,top=150,left=150';

export const createRandomString = (length: number) => {
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
return Array.from({ length }, () => charset.charAt(Math.floor(Math.random() * charset.length))).join('');
export const createOAuthState = () => {
const bytes = new Uint8Array(16);
window.crypto.getRandomValues(bytes);
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
};

const createAuthorizeUrl = (state: string) => {
const parameters = Object.entries({
state,
scope: 'repo,user:email',
client_id: CLIENT_ID,
redirect_uri: AUTH_REDIRECT_URI,
client_id: GITHUB_OAUTH_ID,
redirect_uri: OAUTH_REDIRECT_URI,
}).map(([key, value]) => `${key}=${encodeURIComponent(value)}`);
return `${GITHUB_ORIGIN}/login/oauth/authorize?${parameters.join('&')}`;
};

export const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export const ConnectToGitHub = () => {
const STATE = createRandomString(32);
const STATE = createOAuthState();
const opener = window.open(createAuthorizeUrl(STATE), '_blank', OPEN_WINDOW_FEATURES);

return new Promise((resolve) => {
Expand All @@ -37,9 +36,10 @@ export const ConnectToGitHub = () => {
// the user can be still open it from the tip. In this case, the `opener`
// is null, and we should still process the authorizing message
const isValidOpener = !!(opener && event.source === opener);
const isValidOrigin = event.origin === AUTH_PAGE_ORIGIN;
const isValidOrigin = event.origin === location.origin;
const isValidResponse = event.data ? event.data.type === 'authorizing' : false;
if (!isValidOpener || !isValidOrigin || !isValidResponse) {
const isValidState = event.data ? event.data.state === STATE : false;
if (!isValidOpener || !isValidOrigin || !isValidResponse || !isValidState) {
return;
}
window.removeEventListener('message', handleAuthMessage);
Expand Down
17 changes: 8 additions & 9 deletions src/gitlab-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
* @author netcon
*/

import { timeout, createRandomString } from './github-auth';
import { timeout, createOAuthState } from './github-auth';

const GITLAB_ORIGIN = 'https://gitlab.com';
const AUTH_PAGE_ORIGIN = 'https://auth.gitlab1s.com';
const AUTH_REDIRECT_URI = 'https://auth.gitlab1s.com/api/gitlab-auth-callback';
const CLIENT_ID = '5ef142320efe9d2e8caeb0185771bb126d3035dc0a325c6ad5bab567f320d564';
const OAUTH_REDIRECT_URI = `${location.origin}/api/gitlab-auth-callback`;
const OPEN_WINDOW_FEATURES =
'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=800,height=520,top=150,left=150';

Expand All @@ -17,15 +15,15 @@ const createAuthorizeUrl = (state: string) => {
state,
scope: 'read_api',
response_type: 'code',
client_id: CLIENT_ID,
redirect_uri: AUTH_REDIRECT_URI,
client_id: GITLAB_OAUTH_ID,
redirect_uri: OAUTH_REDIRECT_URI,
}).map(([key, value]) => `${key}=${encodeURIComponent(value)}`);
return `${GITLAB_ORIGIN}/oauth/authorize?${parameters.join('&')}`;
};

// https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
export const ConnectToGitLab = async () => {
const STATE = createRandomString(32);
const STATE = createOAuthState();
const opener = window.open(createAuthorizeUrl(STATE), '_blank', OPEN_WINDOW_FEATURES);

return new Promise((resolve) => {
Expand All @@ -34,9 +32,10 @@ export const ConnectToGitLab = async () => {
// the user can be still open it from the tip. In this case, the `opener`
// is null, and we should still process the authorizing message
const isValidOpener = !!(opener && event.source === opener);
const isValidOrigin = event.origin === AUTH_PAGE_ORIGIN;
const isValidOrigin = event.origin === location.origin;
const isValidResponse = event.data ? event.data.type === 'authorizing' : false;
if (!isValidOpener || !isValidOrigin || !isValidResponse) {
const isValidState = event.data ? event.data.state === STATE : false;
if (!isValidOpener || !isValidOrigin || !isValidResponse || !isValidState) {
return;
}
window.removeEventListener('message', handleAuthMessage);
Expand Down
2 changes: 2 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ declare const GITHUB_ORIGIN: string;
declare const GITLAB_ORIGIN: string;
declare const GITHUB1S_EXTENSIONS: string;
declare const AVAILABLE_LANGUAGES: string[];
declare const GITHUB_OAUTH_ID: string;
declare const GITLAB_OAUTH_ID: string;

/* eslint-disable no-var */
declare var dynamicImport: (url: string) => Promise<any>;
Expand Down
2 changes: 2 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export default (env, argv) => {
GITLAB_ORIGIN: JSON.stringify(process.env.GITLAB_DOMAIN || 'https://gitlab.com'),
GITHUB1S_EXTENSIONS: JSON.stringify(packUtils.getBuiltinExtensions(devVscode)),
AVAILABLE_LANGUAGES: JSON.stringify(availableLanguages),
GITHUB_OAUTH_ID: JSON.stringify(process.env.GITHUB_OAUTH_ID || ''),
GITLAB_OAUTH_ID: JSON.stringify(process.env.GITLAB_OAUTH_ID || ''),
}),
],
performance: false,
Expand Down
Loading