Skip to content

Instantly share code, notes, and snippets.

@itssimple
Created April 3, 2025 07:31
Show Gist options
  • Select an option

  • Save itssimple/c68a21bc210dbd2159fa487f0eb706da to your computer and use it in GitHub Desktop.

Select an option

Save itssimple/c68a21bc210dbd2159fa487f0eb706da to your computer and use it in GitHub Desktop.
OAuth server for handling Bungie-auth
const express = require("express");
const router = express.Router();
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(cors());
const services = {
<liveService>: {
clientId: <clientId>,
apiToken: "<apiToken>",
clientSecret: "<clientSecret>",
redirectUrl: "<liveRedirect>",
},
<localService>: {
clientId: <clientId>,
apiToken: "<apiToken>",
clientSecret: "<clientSecret>",
redirectUrl: "<localRedirect>",
},
};
app.use(express.json());
router.get("/", (req, res) => {
res.status(404).send("I am eskimo, there's nothing here");
});
router.get("/authenticate/:serviceName", (req, res) => {
let serviceName = req.params.serviceName;
if (!services[serviceName]) {
res.status(404).send({ error: "Service not found" });
return;
}
if (typeof req.query.state == "undefined" || req.query.state.length == 0) {
res.status(400).send({ error: "Missing required parameter, state" });
return;
}
function getAuthenticationUrl(service, randomState) {
return `https://www.bungie.net/en/oauth/authorize?client_id=${service.clientId}&response_type=code&state=${randomState}`;
}
res.redirect(getAuthenticationUrl(services[serviceName], req.query.state));
});
router.get("/redirect/:serviceName", (req, res) => {
let serviceName = req.params.serviceName;
if (!services[serviceName]) {
res.status(404).send({ error: "Service not found" });
return;
}
if (!services[serviceName].redirectUrl) {
res.status(404).send({ error: "Service not found" });
return;
}
res.redirect(
`${services[serviceName].redirectUrl}?authenticate=1&state=${req.query.state}&code=${req.query.code}`
);
});
router.post("/token/:serviceName", async (req, res) => {
let serviceName = req.params.serviceName;
if (!services[serviceName]) {
res.status(404).send({ error: "Service not found" });
return;
}
if (typeof req.body.code == "undefined" || req.body.code.length == 0) {
res.status(400).send({ error: "Missing required parameter, code" });
return;
}
async function getAccessToken(service, code) {
const params = new URLSearchParams();
params.append("client_id", service.clientId);
params.append("client_secret", service.clientSecret);
params.append("grant_type", "authorization_code");
params.append("code", code);
const response = await fetch(
`https://www.bungie.net/platform/app/oauth/token/`,
{
method: "POST",
body: params,
}
);
const json = await response.json();
return json;
}
let accessToken = await getAccessToken(services[serviceName], req.body.code);
res.send(accessToken);
});
router.post("/refresh/:serviceName", async (req, res) => {
let serviceName = req.params.serviceName;
if (!services[serviceName]) {
res.status(404).send({ error: "Service not found" });
return;
}
if (
typeof req.body.refresh_token == "undefined" ||
req.body.refresh_token.length == 0
) {
res
.status(400)
.send({ error: "Missing required parameter, refresh_token" });
return;
}
async function refreshToken(service, refresh_token) {
const params = new URLSearchParams();
params.append("client_id", service.clientId);
params.append("client_secret", service.clientSecret);
params.append("grant_type", "refresh_token");
params.append("refresh_token", refresh_token);
const response = await fetch(
`https://www.bungie.net/platform/app/oauth/token/`,
{
method: "POST",
body: params,
}
);
const json = await response.json();
return json;
}
let refreshedToken = await refreshToken(
services[serviceName],
req.body.refresh_token
);
res.send(refreshedToken);
});
app.use(router);
app.listen(3939, () => {
console.log("Server running on port 3939");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment