auth0
Version:
SDK for Auth0 API v2
110 lines • 4.46 kB
JavaScript
;
// Wednesday, 8 January, 2025
// Client Initiated Backchannel Authentication (CIBA)
Object.defineProperty(exports, "__esModule", { value: true });
exports.Backchannel = void 0;
// CIBA is an OpenID Foundation standard for a decoupled authentication flow. It enables
// solution developers to build authentication flows where the user logging in does not do so
// directly on the device that receives the ID or access tokens (the “Consumption Device”), but
// instead on a separate “Authorization Device”.
const models_js_1 = require("../lib/models.js");
const base_auth_api_js_1 = require("./base-auth-api.js");
/**
* Generates the login hint for the user.
*
* @param {string} userId - The user ID.
* @param {string} domain - The tenant domain.
* @returns {string} - The login hint as a JSON string.
*/
const getLoginHint = (userId, domain) => {
// remove trailing '/' from domain, added later for uniformity
const trimmedDomain = domain.endsWith('/') ? domain.slice(0, -1) : domain;
const loginHint = {
format: 'iss_sub',
iss: `https://${trimmedDomain}/`,
sub: `${userId}`,
};
return JSON.stringify(loginHint);
};
const CIBA_GRANT_TYPE = 'urn:openid:params:grant-type:ciba';
const CIBA_AUTHORIZE_URL = '/bc-authorize';
const CIBA_TOKEN_URL = '/oauth/token';
/**
* Class implementing the backchannel authentication flow.
*/
class Backchannel extends base_auth_api_js_1.BaseAuthAPI {
/**
* Initiates a CIBA authorization request.
*
* @param {AuthorizeOptions} options - The options for the request.
* @returns {Promise<AuthorizeResponse>} - The authorization response.
*
* @throws {Error} - If the request fails.
*/
async authorize({ userId, ...options }) {
const body = {
...options,
login_hint: getLoginHint(userId, this.domain),
client_id: this.clientId,
};
await this.addClientAuthentication(body);
const response = await this.request.bind(this)({
path: CIBA_AUTHORIZE_URL,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(body),
}, {});
const r = await models_js_1.JSONApiResponse.fromResponse(response);
return r.data;
}
/**
* Handles the backchannel grant flow for authentication. Client can poll this method at regular intervals to check if the backchannel auth request has been approved.
*
* @param {string} auth_req_id - The authorization request ID. This value is returned from the call to /bc-authorize. Once you have exchanged an auth_req_id for an ID and access token, it is no longer usable.
* @returns {Promise<TokenResponse>} - A promise that resolves to the token response.
*
* @throws {Error} - Throws an error if the request fails.
*
* If the authorizing user has not yet approved or rejected the request, you will receive a response like this:
* ```json
* {
* "error": "authorization_pending",
* "error_description": "The end-user authorization is pending"
* }
* ```
*
* If the authorizing user rejects the request, you will receive a response like this:
* ```json
* {
* "error": "access_denied",
* "error_description": "The end-user denied the authorization request or it has been expired"
* }
* ```
*
* If you are polling too quickly (faster than the interval value returned from /bc-authorize), you will receive a response like this:
* ```json
* {
* "error": "slow_down",
* "error_description": "You are polling faster than allowed. Try again in 10 seconds."
* }
* ```
*/
async backchannelGrant({ auth_req_id }) {
const body = {
client_id: this.clientId,
auth_req_id,
grant_type: CIBA_GRANT_TYPE,
};
await this.addClientAuthentication(body);
const response = await this.request.bind(this)({
path: CIBA_TOKEN_URL,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(body),
}, {});
const r = await models_js_1.JSONApiResponse.fromResponse(response);
return r.data;
}
}
exports.Backchannel = Backchannel;
//# sourceMappingURL=backchannel.js.map