Use the dropbox sdk to connect with dropbox. This will handle all the requirements to setup a proper PKCE flow.
Register the application with dropbox to use the dropbox sdk.
Install dropbox sdk:
$ yarn add dropbox
Authorization Flow
The plugin can be considered a client side application. Therefore, the suggested oauth2 authorization flow is the PKCE (Proof Key for Code Exchange) flow. The dropbox sdk handles almost all the steps in the flow. The only responsibility of the app is to properly store the refresh token to allow the authorization state to be persistent - the user will not have to authorize the plugin every time they start the application.
PKCE Flow Overview
The following is taken from the PKCE RFC(1):
A. The client creates and records a secret named the "code_verifier" and derives a transformed version "t(code_verifier)" (referred to as the "code_challenge"), which is sent in the OAuth 2.0 Authorization Request along with the transformation method "t_m".
B. The Authorization Endpoint responds as usual but records "t(code_verifier)" and the transformation method.
C. The client then sends the authorization code in the Access Token Request as usual but includes the "code_verifier" secret generated at (A).
D. The authorization server transforms "code_verifier" and compares it to "t(code_verifier)" from (B). Access is denied if they are not equal.
Plugin Implementation
The authorization will be triggered in the settings view.
The user will click a button to start the authorization flow
The user will be redirected to the dropbox authorization site in their web browser where the will authorize the application
The user will be returned to the obsidian application. The protocolHandler will handle the authorization response:
exchange the authorization code for an access token
set the access token in the dropbox sdk
set the refresh token in the dropbox sdk
store the refresh token in localstorage.
Implementation in code (The UI is not included in these notes. Can be seen in settings.ts file):
const REDIRECT_URI = "obsidian://connect-dropbox";
// Create the authorization url and redirect the user to accept authorization for the application
dropboxAuth.getAuthenticationUrl(
REDIRECT_URI, // redirectUri
undefined, // state
"code", // authType
"offline", // tokenAccessType
undefined, // scope
undefined, // includeGrantedScopes
true, // usePKCE
)
.then((authUrl) => {
window.sessionStorage.clear();
window.sessionStorage.setItem(
"codeVerifier",
this.dropboxAuth.getCodeVerifier(),
);
window.location.href = authUrl as string;
})
.catch((error) => console.error(error));
The tokenAccessType must be set to offline. This allows the dropbox sdk to handle refressing the access token. See Response By Dropbox on PKCE w/ Refresh
The usePKCE flag needs to be set to true.
// Exchange the authorization token for an access token. This is run in the obsidian protocol handler
getAccessToken(protocolData: ObsidianProtocolData): Promise<void> {
const { code } = protocolData;
if (!code) throw new Error("Authorization Error: Code Not Available");
const codeVerifier = window.sessionStorage.getItem("codeVerifier");
if (!codeVerifier) {
throw new Error("Authorization Error: Code Verifier Not Available");
}
this.dropboxAuth.setCodeVerifier(codeVerifier);
return this.dropboxAuth
.getAccessTokenFromCode(REDIRECT_URI, code)
.then(
(
response: DropboxResponse<{
access_token: string;
refresh_token: string;
}>,
) => {
this.dropboxAuth.setAccessToken(
response.result.access_token,
);
this.dropboxAuth.setRefreshToken(
response.result.refresh_token,
);
// Store Refresh token in local storage for persistant authorization
localStorage.setItem(
"dropboxRefreshToken",
response.result.refresh_token,
);
},
)
.catch((error) => console.error(error));
}
Important Implementation Details:
The access token has to be explicitly set in the dropbox sdk using the setAccessToken method.
The refresh token has to be explicitly set in the dropbox sdk using the setRefreshToken method.
The refresh token has to be stored to make authorization persistent between application lifecycles.
Refresh Token and Continued Access
The authorization flow handles storing the refresh token after initial authorization. The refresh token is also stored in local storage to allow the plugin to attempt to reauthorize on loading the plugin. This is handled in the main.ts file in the Plugin class. The following code is in the dropboxProvider
Setup
Use the dropbox sdk to connect with dropbox. This will handle all the requirements to setup a proper PKCE flow.
Register the application with dropbox to use the dropbox sdk.
Install dropbox sdk:
Authorization Flow
The plugin can be considered a client side application. Therefore, the suggested oauth2 authorization flow is the PKCE (Proof Key for Code Exchange) flow. The dropbox sdk handles almost all the steps in the flow. The only responsibility of the app is to properly store the refresh token to allow the authorization state to be persistent - the user will not have to authorize the plugin every time they start the application.
PKCE Flow Overview
The following is taken from the PKCE RFC(1):
A. The client creates and records a secret named the "code_verifier" and derives a transformed version "t(code_verifier)" (referred to as the "code_challenge"), which is sent in the OAuth 2.0 Authorization Request along with the transformation method "t_m".
B. The Authorization Endpoint responds as usual but records "t(code_verifier)" and the transformation method.
C. The client then sends the authorization code in the Access Token Request as usual but includes the "code_verifier" secret generated at (A).
D. The authorization server transforms "code_verifier" and compares it to "t(code_verifier)" from (B). Access is denied if they are not equal.
Plugin Implementation
The authorization will be triggered in the settings view.
protocolHandler
will handle the authorization response:localstorage
.Implementation in code (The UI is not included in these notes. Can be seen in
settings.ts
file):Important Implementation Details:
REDIRECT_URI
calls out what registeredprotocolHandler
will catch the response. See registerObsidianProtocolHandler documentationtokenAccessType
must be set to offline. This allows the dropbox sdk to handle refressing the access token. See Response By Dropbox on PKCE w/ RefreshusePKCE
flag needs to be set to true.Important Implementation Details:
setAccessToken
method.setRefreshToken
method.Refresh Token and Continued Access
The authorization flow handles storing the refresh token after initial authorization. The refresh token is also stored in local storage to allow the plugin to attempt to reauthorize on loading the plugin. This is handled in the
main.ts
file in thePlugin
class. The following code is in thedropboxProvider
Resouces