fiemwl / src /lib /oauth /providers /qoder.ts
automindy's picture
Upload 1980 files
6111b2b verified
Raw
History Blame Contribute Delete
2.8 kB
import { QODER_CONFIG } from "../constants/oauth";
export const qoder = {
config: QODER_CONFIG,
flowType: "authorization_code",
buildAuthUrl: (config, redirectUri, state) => {
if (!config?.enabled || !config?.authorizeUrl) {
return null;
}
const params = new URLSearchParams({
loginMethod: config.extraParams.loginMethod,
type: config.extraParams.type,
redirect: redirectUri,
state: state,
client_id: config.clientId,
});
return `${config.authorizeUrl}?${params.toString()}`;
},
exchangeToken: async (config, code, redirectUri) => {
if (!config?.enabled || !config?.tokenUrl) {
throw new Error(
"Qoder browser OAuth is experimental and disabled by default. Configure QODER_OAUTH_* environment variables or use a Personal Access Token."
);
}
const headers: Record<string, string> = {
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/json",
};
if (config.clientSecret) {
const basicAuth = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64");
headers.Authorization = `Basic ${basicAuth}`;
}
const bodyParams: Record<string, string> = {
grant_type: "authorization_code",
code: code,
redirect_uri: redirectUri,
client_id: config.clientId,
};
if (config.clientSecret) {
bodyParams.client_secret = config.clientSecret;
}
const response = await fetch(config.tokenUrl, {
method: "POST",
headers: headers,
body: new URLSearchParams(bodyParams),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Token exchange failed: ${error}`);
}
return await response.json();
},
postExchange: async (tokens) => {
if (!QODER_CONFIG.enabled || !QODER_CONFIG.userInfoUrl) {
throw new Error(
"Qoder browser OAuth is experimental and disabled by default. Configure QODER_OAUTH_* environment variables or use a Personal Access Token."
);
}
const userInfoRes = await fetch(
`${QODER_CONFIG.userInfoUrl}?accessToken=${encodeURIComponent(tokens.access_token)}`,
{ headers: { Accept: "application/json" } }
);
const result = userInfoRes.ok ? await userInfoRes.json() : {};
const userInfo = result.success ? result.data : {};
return { userInfo };
},
mapTokens: (tokens, extra) => ({
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
expiresIn: tokens.expires_in,
apiKey: extra?.userInfo?.apiKey,
email: extra?.userInfo?.email || extra?.userInfo?.phone,
displayName: extra?.userInfo?.nickname || extra?.userInfo?.name,
}),
};