basic dropbox auth flow

This commit is contained in:
fyears
2021-11-28 16:28:52 +08:00
parent 00c840a758
commit 1effcdd7f7
4 changed files with 306 additions and 18 deletions
+95
View File
@@ -1,5 +1,7 @@
import * as path from "path";
import { FileStats, Vault } from "obsidian";
import { Buffer } from "buffer";
import * as crypto from "crypto";
import { Dropbox, DropboxResponse, files } from "dropbox";
export { Dropbox } from "dropbox";
@@ -17,10 +19,22 @@ import { strict as assert } from "assert";
export interface DropboxConfig {
accessToken: string;
clientID: string;
refreshToken: string;
accessTokenExpiresInSeconds: number;
accessTokenExpiresAtTime: number;
accountID: string;
username: string;
}
export const DEFAULT_DROPBOX_CONFIG = {
accessToken: "",
clientID: "",
refreshToken: "",
accessTokenExpiresInSeconds: 0,
accessTokenExpiresAtTime: 0,
accountID: "",
username: "",
};
export const getDropboxPath = (fileOrFolderPath: string) => {
@@ -370,3 +384,84 @@ export const checkConnectivity = async (dbx: Dropbox) => {
return false;
}
};
export const getUserDisplayName = async (dbx: Dropbox) => {
const acct = await dbx.usersGetCurrentAccount();
return acct.result.name.display_name;
};
/**
* Dropbox authorization using PKCE
* see https://dropbox.tech/developers/pkce--what-and-why-
*
*/
const specialBase64Encode = (str: Buffer) => {
return str
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
};
const sha256 = (buffer: string) => {
return crypto.createHash("sha256").update(buffer).digest();
};
export const getCodeVerifierAndChallenge = () => {
const codeVerifier = specialBase64Encode(crypto.randomBytes(32));
// console.log(`Client generated code_verifier: ${codeVerifier}`);
const codeChallenge = specialBase64Encode(sha256(codeVerifier));
// console.log(`Client generated code_challenge: ${codeChallenge}`);
return {
verifier: codeVerifier,
challenge: codeChallenge,
};
};
export const getAuthUrl = (appKey: string, challenge: string) => {
return `https://www.dropbox.com/oauth2/authorize?client_id=${appKey}&response_type=code&code_challenge=${challenge}&code_challenge_method=S256&token_access_type=offline`;
};
export interface DropboxSuccessAuthRes {
access_token: string;
token_type: string;
expires_in: number;
refresh_token: string;
scope: string;
uid: string;
account_id: string;
}
export const sendAuthReq = async (
appKey: string,
verifier: string,
authCode: string
) => {
const resp1 = await fetch("https://api.dropboxapi.com/oauth2/token", {
method: "POST",
body: new URLSearchParams({
code: authCode,
grant_type: "authorization_code",
code_verifier: verifier,
client_id: appKey,
}),
});
const resp2 = (await resp1.json()) as DropboxSuccessAuthRes;
return resp2;
};
export const setConfigBySuccessfullAuthInplace = (
config: DropboxConfig,
authRes: DropboxSuccessAuthRes
) => {
config.accessToken = authRes.access_token;
config.refreshToken = authRes.refresh_token;
config.accessTokenExpiresInSeconds = authRes.expires_in;
config.accessTokenExpiresAtTime =
Date.now() + authRes.expires_in * 1000 - 10 * 1000;
config.accountID = authRes.account_id;
};
export const revokeAuth = async (client: Dropbox) => {
await client.authTokenRevoke();
};