Skip to content

Instantly share code, notes, and snippets.

@fabriziogiordano
Created May 15, 2024 15:36
Show Gist options
  • Save fabriziogiordano/9a56f2b2ebbbc4ec0c313ff164fc6fa1 to your computer and use it in GitHub Desktop.
Save fabriziogiordano/9a56f2b2ebbbc4ec0c313ff164fc6fa1 to your computer and use it in GitHub Desktop.
Schwab - token flow
/*
ps aux | grep "ssh -L"|grep -v grep|awk '{print $2}'|xargs kill
ssh -L 443:127.0.0.1:443 -N -f root@linode; echo "linode: 443"
*/
import dotenv from "dotenv";
dotenv.config({ path: `${process.env.GAP_FOLDER}/.env` });
import fs from "fs";
import got from "got";
import { db } from "../db/index.js";
import Fastify from "fastify";
//SSL cert
const fastify = Fastify({
logger: false,
https: {
key: fs.readFileSync("./certs/key.pem"),
cert: fs.readFileSync("./certs/certificate.pem"),
},
});
const port = 443;
const host = "0.0.0.0";
const tokenJson = `${process.env.GAP_FOLDER}/utils/token/token.json`;
const { SCHWAB_APIKEY, SCHWAB_SECRET, SCHWAB_CALLBACK_URI } = process.env;
const BASIC = btoa(`${SCHWAB_APIKEY}:${SCHWAB_SECRET}`);
console.log("URL");
console.log(`https://api.schwabapi.com/v1/oauth/authorize?client_id=${SCHWAB_APIKEY}&redirect_uri=${encodeURIComponent(SCHWAB_CALLBACK_URI)}`);
fastify.get("/callback", async (req, res) => {
console.log("Waiting for the token");
try {
const options = {
// See the Authentication API's Post Access Token method for more information
url: "https://api.schwabapi.com/v1/oauth/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded",
},
// POST Body params
form: {
grant_type: "authorization_code",
access_type: "offline",
code: req.query.code, //get the code
redirect_uri: SCHWAB_CALLBACK_URI,
},
};
console.log("Sending request to verify token");
const response = await got(options);
// Post Access Token request
if (response.statusCode === 200) {
console.log("Token verified");
const authReply = JSON.parse(response.body);
try {
const tokenText = JSON.stringify(authReply, null, " ");
fs.writeFileSync(tokenJson, tokenText);
console.log("Token file updated");
// Do not save on the DB Yet
await saveToken(tokenText);
await res.send(authReply);
await fastify.close();
console.log("Successfully closed!");
process.exit(200);
} catch (error) {
console.error(error);
}
} else {
console.error(response.statusCode);
}
} catch (error) {
console.error(error);
}
});
fastify.get("/refresh", async (req, res) => {
try {
console.log("Refreshing");
const { refresh_token } = JSON.parse(fs.readFileSync(tokenJson, "utf-8"));
const response = await got({
// See the Authentication API's Post Access Token method for more information
url: "https://api.schwabapi.com/v1/oauth/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded",
},
// POST Body params
form: {
grant_type: "refresh_token",
refresh_token: refresh_token,
},
});
// Post Access Token request
if (response.statusCode === 200) {
// See Post Access Token response summary for what authReply contains
const authReply = JSON.parse(response.body);
fs.writeFileSync(tokenJson, JSON.stringify(authReply, null, " "));
console.log("Token updated");
await res.send(authReply);
} else {
await res.send(response.statusCode);
}
} catch (error) {
console.error(error);
await res.send(error);
}
});
// Run the server!
const start = async () => {
try {
console.log("Here");
await fastify.listen({ port: port, host: host });
console.log("Token server started");
} catch (error) {
fastify.log.error(error);
console.error(error);
process.exit(1);
}
};
start();
// Save token in DB
async function saveToken(tokenText) {
try {
const now = new Date().getTime();
const clearRegularTokens = "DELETE FROM tokens WHERE type = 'regular' AND platform = 'schwab'";
const setTokenQueryParams = [now, tokenText];
const setTokenQueryText = `
INSERT INTO tokens (datetime, type, value, platform)
VALUES ($1, 'regular', $2, 'schwab');
`;
console.log(clearRegularTokens);
console.log(setTokenQueryParams);
await db.query(clearRegularTokens);
await db.query(setTokenQueryText, setTokenQueryParams);
await db.end();
} catch (error) {
console.error("Token NOT updated in DB");
console.error(error.stack);
}
console.log("Token updated in DB");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment