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 package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vectorize-io/vectorize-connect",
"version": "0.3.7",
"version": "0.4.0",
"description": "A simple package for Google Drive authorization and file selection",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
7 changes: 4 additions & 3 deletions src/baseOAuth/core/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ export abstract class BaseOAuth {
/**
* Create an error response for the OAuth callback
* @param error The error to include in the response
* @param nonce Optional nonce for Content Security Policy
* @returns A Response object with the error
*/
protected static createErrorResponse(error: OAuthError): Response {
protected static createErrorResponse(error: OAuthError, nonce?: string): Response {
const htmlContent = `
<!DOCTYPE html>
<html>
Expand All @@ -122,15 +123,15 @@ export abstract class BaseOAuth {
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
.error { color: #f44336; }
</style>
<script>
<script${nonce ? ` nonce="${nonce}"` : ''}>
window.onload = function() {
if (window.opener && window.opener.__oauthHandler) {
const errorObj = ${JSON.stringify({
message: error.message,
code: error.code,
details: error.details
})};

window.opener.__oauthHandler.onError(
new window.opener.__oauthHandler.OAuthError(
errorObj.message,
Expand Down
1 change: 1 addition & 0 deletions src/baseOAuth/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class OAuthError extends Error {
export interface OAuthConfig {
redirectUri: string;
scopes?: string[];
nonce?: string;
onSuccess?: (selectedFields?: any) => void;
onError?: (error: OAuthError) => void;
}
Expand Down
7 changes: 4 additions & 3 deletions src/baseOAuth/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ export function validateConfig(config: OAuthConfig): void {
/**
* Creates an error response for OAuth callbacks
* @param error The error to include in the response
* @param nonce Optional nonce for Content Security Policy
* @returns A Response object with the error
*/
export function createErrorResponse(error: OAuthError): Response {
export function createErrorResponse(error: OAuthError, nonce?: string): Response {
const htmlContent = `
<!DOCTYPE html>
<html>
Expand All @@ -39,15 +40,15 @@ export function createErrorResponse(error: OAuthError): Response {
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
.error { color: #f44336; }
</style>
<script>
<script${nonce ? ` nonce="${nonce}"` : ''}>
window.onload = function() {
if (window.opener && window.opener.__oauthHandler) {
const errorObj = ${JSON.stringify({
message: error.message,
code: error.code,
details: error.details
})};

window.opener.__oauthHandler.onError(
new window.opener.__oauthHandler.OAuthError(
errorObj.message,
Expand Down
5 changes: 3 additions & 2 deletions src/dropBoxOAuth/core/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class DropboxOAuth extends BaseOAuth {
): Promise<Response> {
if (error) {
const errorObj = typeof error === 'string' ? new OAuthError(error, 'CALLBACK_ERROR') : error;
return this.createErrorResponse(errorObj);
return this.createErrorResponse(errorObj, nonce);
}

try {
Expand All @@ -116,7 +116,8 @@ export class DropboxOAuth extends BaseOAuth {
error instanceof Error ? error.message : 'Failed to create callback page',
'CALLBACK_ERROR',
error
)
),
nonce
);
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/dropBoxOAuth/core/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,16 @@ export class DropboxSelection extends BaseSelection {

// Generate the Dropbox file picker content
const content = DropboxPicker.createPickerHTML(
{
{
access_token: tokens.access_token,
refresh_token: refreshToken,
expires_in: tokens.expires_in,
token_type: tokens.token_type
},
config,
refreshToken,
selectedFiles
},
config,
refreshToken,
selectedFiles,
config.nonce
);

// Write content to the popup
Expand Down
1 change: 1 addition & 0 deletions src/dropBoxOAuth/ui/picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export class DropboxPicker extends BasePicker {
script.id = 'dropboxjs';
script.src = 'https://www.dropbox.com/static/api/2/dropins.js';
script.setAttribute('data-app-key', '${config.appKey}');
${nonce ? `script.setAttribute('nonce', '${nonce}');` : ''}
script.onload = () => {
if (isDropboxAvailable()) {
resolve(true);
Expand Down
5 changes: 3 additions & 2 deletions src/googleDriveOAuth/core/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class GoogleDriveOAuth extends BaseOAuth {
): Promise<Response> {
if (error) {
const errorObj = typeof error === 'string' ? new OAuthError(error, 'CALLBACK_ERROR') : error;
return this.createErrorResponse(errorObj);
return this.createErrorResponse(errorObj, nonce);
}

try {
Expand All @@ -121,7 +121,8 @@ export class GoogleDriveOAuth extends BaseOAuth {
error instanceof Error ? error.message : 'Failed to create callback page',
'CALLBACK_ERROR',
error
)
),
nonce
);
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/googleDriveOAuth/core/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ export class GoogleDriveSelection extends BaseSelection {

// Generate the Google Drive file picker content
const content = GoogleDrivePicker.createPickerHTML(
{
{
access_token: tokens.access_token,
refresh_token: refreshToken,
expires_in: tokens.expires_in,
token_type: tokens.token_type
},
config,
refreshToken,
selectedFiles
},
config,
refreshToken,
selectedFiles,
config.nonce
);

// Write content to the popup
Expand Down
4 changes: 2 additions & 2 deletions src/googleDriveOAuth/ui/picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ export class GoogleDrivePicker extends BasePicker {

// Google-specific head includes
const googleHead = `
<script src="https://apis.google.com/js/api.js"></script>
<script src="https://apis.google.com/js/platform.js"></script>
<script src="https://apis.google.com/js/api.js"${nonce ? ` nonce="${nonce}"` : ''}></script>
<script src="https://apis.google.com/js/platform.js"${nonce ? ` nonce="${nonce}"` : ''}></script>
`;

// Assemble the complete HTML
Expand Down
5 changes: 3 additions & 2 deletions src/googleDriveOAuth/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ export function validateConfig(config: OAuthConfig): void {
/**
* Creates an HTML error response for the OAuth popup
* @param error The error to embed in the response
* @param nonce Optional nonce for Content Security Policy
* @returns A Response object with the error handling HTML
*/
export function createErrorResponse(error: OAuthError): Response {
export function createErrorResponse(error: OAuthError, nonce?: string): Response {
// Create a plain object with all properties we want to transfer
const errorData = {
message: error.message,
Expand All @@ -35,7 +36,7 @@ export function createErrorResponse(error: OAuthError): Response {
};

return new Response(
`<script>
`<script${nonce ? ` nonce="${nonce}"` : ''}>
const errorObj = ${JSON.stringify(errorData)};
window.opener.__oauthHandler?.onError(errorObj);
window.close();
Expand Down
13 changes: 8 additions & 5 deletions src/notionOAuth/core/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,18 @@ export class NotionOAuth extends BaseOAuth {
* @param code Authorization code from the OAuth redirect
* @param config The OAuth configuration
* @param error Optional error from the OAuth process
* @param nonce Optional nonce for Content Security Policy
* @returns A Response object with the callback page
*/
public static override async createCallbackResponse(
code: string,
config: NotionOAuthConfig,
error?: string | OAuthError
error?: string | OAuthError,
nonce?: string
): Promise<Response> {
if (error) {
const errorObj = typeof error === 'string' ? new OAuthError(error, 'CALLBACK_ERROR') : error;
return this.createErrorResponse(errorObj);
return this.createErrorResponse(errorObj, nonce);
}

try {
Expand All @@ -105,16 +107,17 @@ export class NotionOAuth extends BaseOAuth {
);

// Use the Notion picker template
const htmlContent = NotionPicker.createPickerHTML(tokens, config, tokens.access_token);
const htmlContent = NotionPicker.createPickerHTML(tokens, config, tokens.access_token, undefined, nonce);

return new Response(htmlContent, { headers: { 'Content-Type': 'text/html' } });
} catch (error) {
return this.createErrorResponse(
error instanceof OAuthError ? error : new OAuthError(
error instanceof Error ? error.message : 'Failed to create callback page',
'CALLBACK_ERROR',
error
)
),
nonce
);
}
}
Expand Down