onehr_dan
Version:
DAN integration package
96 lines • 3.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeServiceStructure = encodeServiceStructure;
exports.generateAuthorizationUrl = generateAuthorizationUrl;
exports.validateState = validateState;
exports.exchangeCodeForToken = exchangeCodeForToken;
exports.callResource = callResource;
const url_1 = require("url");
/**
* Encode the given service structure into Base64-encoded JSON.
* @param serviceStructure The structure describing the services to request.
*/
function encodeServiceStructure(serviceStructure) {
const jsonStr = JSON.stringify(serviceStructure);
const base64Str = Buffer.from(jsonStr, "utf-8").toString("base64");
return base64Str;
}
/**
* Generate the authorization URL.
* @param oauthAuthorizeEndpoint OAuth authorization endpoint (e.g. https://sso.gov.mn/oauth2/authorize)
* @param clientId Client ID issued by the OAuth-DAN server
* @param redirectUri Redirect URI registered at the OAuth-DAN server
* @param serviceStructure The service structure to request
* @param state A unique, non-reusable state string (for CSRF protection)
* @param loginType Optional login type: "OTP", "signature", or "bank"
*/
function generateAuthorizationUrl({ oauthAuthorizeEndpoint, clientId, redirectUri, serviceStructure, state, loginType, }) {
const scope = encodeServiceStructure(serviceStructure);
const params = new url_1.URLSearchParams({
response_type: "code",
client_id: clientId,
redirect_uri: redirectUri,
scope: scope,
state: state,
});
// LOGIN TYPE IS OPTIONAL - (DEFAULT: "OTP")
if (loginType)
params.set("login_type", loginType);
return `${oauthAuthorizeEndpoint}?${params.toString()}`;
}
/**
* Validate the returned state parameter.
* @param returnedState The state value returned from the OAuth server after authorization
* @param originalState The original state value sent
*/
function validateState({ returnedState, originalState, }) {
if (returnedState !== originalState) {
throw new Error("Invalid state parameter. Possible CSRF attack.");
}
}
/**
* Exchange authorization code for access token.
* @param oauthTokenEndpoint OAuth token endpoint (https://sso.gov.mn/oauth2/token)
* @param clientId Client ID issued by the OAuth-DAN server
* @param clientSecret Client Secret Key issued by the OAuth-DAN server
* @param code The code returned by the OAuth-DAN server after user authorization
* @param redirectUri Redirect URI registered at the OAuth-DAN server
*/
async function exchangeCodeForToken({ oauthTokenEndpoint, clientId, clientSecret, code, redirectUri, }) {
const params = new url_1.URLSearchParams({
grant_type: "authorization_code",
code: code,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
});
const response = await fetch(oauthTokenEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params.toString(),
});
if (!response.ok) {
throw new Error(`Failed to exchange code for token: ${response.status} ${response.statusText}`);
}
return response.json();
}
/**
* Call a protected resource using the provided access token.
* @param resourceEndpoint The protected resource endpoint
* @param accessToken The access token obtained from the OAuth server
*/
async function callResource({ resourceEndpoint, accessToken, }) {
const response = await fetch(resourceEndpoint, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Protected resource request failed: ${response.status} ${response.statusText}`);
}
return response.json();
}
//# sourceMappingURL=utils.js.map