Files
netris-nestri/packages/auth/src/provider/steam.ts
2026-08-06 22:13:51 +03:00

53 lines
1.6 KiB
TypeScript

import { getRelativeUrl } from '../util.js';
import { Provider } from './provider.js';
const STEAM_OPENID_URL = 'https://steamcommunity.com/openid/login';
export function SteamProvider(): Provider<{ steamid: string }> {
return {
type: 'steam',
init(routes, ctx) {
routes.get('/authorize', async (c) => {
const returnUrl = getRelativeUrl(c, './callback');
const openidURL =
`${STEAM_OPENID_URL}?` +
`openid.ns=${encodeURIComponent('http://specs.openid.net/auth/2.0')}&` +
`openid.mode=checkid_setup&` +
`openid.return_to=${encodeURIComponent(returnUrl)}&` +
`openid.realm=${encodeURIComponent(new URL(c.req.url).origin)}&` +
`openid.identity=${encodeURIComponent('http://specs.openid.net/auth/2.0/identifier_select')}&` +
`openid.claimed_id=${encodeURIComponent('http://specs.openid.net/auth/2.0/identifier_select')}`;
return c.redirect(openidURL);
});
routes.get('/callback', async (c) => {
const url = new URL(c.req.url);
const params = Object.fromEntries(url.searchParams.entries());
const verifyRes = await fetch(STEAM_OPENID_URL, {
method: 'POST',
body: new URLSearchParams({
...params,
'openid.mode': 'check_authentication'
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const verifyText = await verifyRes.text();
if (!verifyText.includes('is_valid:true')) {
throw new Error('Steam OpenID validation failed');
}
const steamid = params['openid.claimed_id']?.split('/').pop();
if (!steamid) {
throw new Error('Steam ID not found');
}
return ctx.success(c, { steamid });
});
}
};
}