@aethex.os/discord
v1.0.1
Published
Discord OAuth and Activity auth helpers — build Discord login, account linking, and Discord Activity authentication in minutes
Maintainers
Readme
@aethex.os/discord
Discord OAuth and Activity auth helpers — build Discord login, account linking, and Discord Activity authentication in minutes.
Install
npm install @aethex.os/discordNo extra dependencies. Uses the native fetch API (Node 18+).
OAuth login flow
import { buildOAuthUrl, exchangeCode, getDiscordUser, getAvatarUrl } from "@aethex.os/discord";
const config = {
clientId: process.env.DISCORD_CLIENT_ID!,
clientSecret: process.env.DISCORD_CLIENT_SECRET!,
redirectUri: "https://myapp.com/api/discord/callback",
};
// 1. Redirect user to Discord
app.get("/api/discord/login", (req, res) => {
const url = buildOAuthUrl(config, { action: "login", redirectTo: "/dashboard" });
res.redirect(url);
});
// 2. Handle callback
app.get("/api/discord/callback", async (req, res) => {
const { code, state } = req.query;
const tokens = await exchangeCode(code as string, config);
const user = await getDiscordUser(tokens.accessToken);
console.log(user.id, user.username, user.email);
console.log(getAvatarUrl(user)); // https://cdn.discordapp.com/avatars/...
// create session, store tokens, redirect
res.redirect("/dashboard");
});Account linking
import { buildOAuthUrl, parseState } from "@aethex.os/discord";
// Generate a linking URL with a session token in state
const url = buildOAuthUrl(config, {
action: "link",
sessionToken: crypto.randomUUID(),
redirectTo: "/settings",
});
// In the callback, parse state to detect link vs login
const stateData = parseState(req.query.state as string);
if (stateData.action === "link") {
// retrieve sessionToken from your DB to get the authenticated userId
}Discord Activity auth
Verify a Discord Activity SDK access_token server-side:
import { verifyActivityToken } from "@aethex.os/discord";
app.post("/api/activity/auth", async (req, res) => {
const { access_token } = req.body;
const user = await verifyActivityToken(access_token);
// user.id, user.username, user.avatarUrl
res.json({ user });
});Or use the built-in Express handler:
import { createActivityAuthHandler } from "@aethex.os/discord";
app.post(
"/api/activity/auth",
createActivityAuthHandler({
onUserVerified: async (user) => {
// upsert user in your database
await db.users.upsert({ discordId: user.id, username: user.username });
},
})
);Token refresh
import { refreshTokens } from "@aethex.os/discord";
const newTokens = await refreshTokens(storedRefreshToken, {
clientId: process.env.DISCORD_CLIENT_ID!,
clientSecret: process.env.DISCORD_CLIENT_SECRET!,
});API
| Function | Description |
|----------|-------------|
| buildOAuthUrl(config, state?) | Build the Discord OAuth authorization URL |
| exchangeCode(code, config) | Exchange an authorization code for tokens |
| getDiscordUser(accessToken) | Fetch the authenticated Discord user |
| getAvatarUrl(user, format?) | Get a user's avatar CDN URL |
| refreshTokens(refreshToken, config) | Refresh an expired access token |
| parseState(stateParam) | Parse the state query parameter |
| verifyActivityToken(accessToken) | Verify a Discord Activity access token |
| createActivityAuthHandler(config?) | Express handler for Activity auth |
Part of the @aethex.os toolkit.
