@rsweeten/dropbox-sync
Version:
Reusable Dropbox synchronization module with framework adapters
85 lines (84 loc) • 3.77 kB
JavaScript
export function createAuthMethods(getClient, credentials, setAccessToken) {
return {
/**
* Generate an authentication URL for Dropbox OAuth flow
*/
async getAuthUrl(redirectUri, state) {
const dropbox = getClient();
const randomState = state || Math.random().toString(36).substring(2, 15);
// Cast to extended auth type to access missing methods
const auth = dropbox.auth;
// Generate the authentication URL
const authUrl = auth.getAuthenticationUrl(redirectUri, randomState, 'code', // Use authorization code flow
'offline', // Request a refresh token for long-lived access
undefined, // No scope specified, request full access
undefined, // No include_granted_scopes
true // Force reapproval to ensure we get fresh tokens
);
return authUrl;
},
/**
* Exchange authorization code for access token
*/
async exchangeCodeForToken(code, redirectUri) {
const dropbox = getClient();
// Cast to extended auth type to access missing methods
const auth = dropbox.auth;
// Exchange the code for an access token
const response = await auth.getAccessTokenFromCode(redirectUri, code);
const tokenResponse = {
accessToken: response.result.access_token,
refreshToken: response.result.refresh_token,
expiresAt: response.result.expires_in
? Date.now() + response.result.expires_in * 1000
: undefined,
};
// Update the client with the new token
setAccessToken(tokenResponse.accessToken);
return tokenResponse;
},
/**
* Refresh an expired access token using the refresh token
*/
async refreshAccessToken() {
if (!credentials.refreshToken ||
!credentials.clientId ||
!credentials.clientSecret) {
throw new Error('Refresh token, client ID, and client secret are required to refresh access token');
}
// Dropbox API endpoint for token refresh
const tokenUrl = 'https://api.dropboxapi.com/oauth2/token';
// Prepare the form data for the token request
const formData = new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: credentials.refreshToken,
client_id: credentials.clientId,
client_secret: credentials.clientSecret,
});
// Make the request to refresh the token
const response = await fetch(tokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString(),
});
if (!response.ok) {
await response.text(); // Consume the response body
throw new Error(`Failed to refresh token: ${response.status} ${response.statusText}`);
}
// Parse the response
const data = await response.json();
const tokenResponse = {
accessToken: data.access_token,
refreshToken: data.refresh_token || credentials.refreshToken,
expiresAt: data.expires_in
? Date.now() + data.expires_in * 1000
: undefined,
};
// Update the client with the new token
setAccessToken(tokenResponse.accessToken);
return tokenResponse;
},
};
}