@forgerock/javascript-sdk
Advanced tools
Comparing version 4.1.1 to 4.1.2
# Changelog | ||
## [4.1.2] - 2023-07-20 | ||
Features: | ||
- Minor changes to prepare for an upcoming Token Vault release | ||
Fixes: | ||
- fix(javascript-sdk): get-tokens-default-destructure (360df9968d) | ||
## [4.1.1] - 2023-06-29 | ||
@@ -4,0 +14,0 @@ |
{ | ||
"name": "@forgerock/javascript-sdk", | ||
"version": "4.1.1", | ||
"version": "4.1.2", | ||
"description": "ForgeRock JavaScript SDK", | ||
@@ -28,5 +28,5 @@ "author": "ForgeRock", | ||
"types": "./src/index.d.ts", | ||
"module": "./index.js", | ||
"main": "./index.cjs", | ||
"module": "./src/index.js", | ||
"main": "./src/index.cjs", | ||
"type": "module" | ||
} | ||
} |
@@ -13,7 +13,10 @@ /** | ||
export declare function examineForIGAuthz(res: Response): boolean; | ||
export declare function examineForIGAuthzHeader(headers: Headers): boolean; | ||
export declare function examineForRESTAuthz(res: Response): Promise<boolean>; | ||
export declare function getAdvicesFromHeader(header: string): Advices; | ||
export declare function hasAuthzAdvice(json: AuthorizationJSON): boolean; | ||
export declare function isAuthzStep(res: Response): Promise<boolean>; | ||
export declare function newTokenRequired(res: Response, requiresNewToken?: RequiresNewTokenFn): boolean; | ||
export declare function normalizeIGJSON(res: Response): AuthorizationJSON; | ||
export declare function normalizeIGRedirectResponseToAdviceJSON(res: Response): AuthorizationJSON; | ||
export declare function normalizeIGJSONResponseToAdviceJSON(res: Response): AuthorizationJSON; | ||
export declare function normalizeRESTJSON(res: Response): Promise<AuthorizationJSON>; |
@@ -88,2 +88,6 @@ import { getEndpointPath, resolve, stringify } from '../util/url.js'; | ||
} | ||
function examineForIGAuthzHeader(headers) { | ||
const authnHeader = headers.get('WWW-Authenticate') || ''; | ||
return authnHeader.includes('advices'); | ||
} | ||
async function examineForRESTAuthz(res) { | ||
@@ -103,2 +107,18 @@ const clone = res.clone(); | ||
} | ||
function getAdvicesFromHeader(header) { | ||
const headerArr = header.split(',') || []; | ||
const advicesSubstr = headerArr.find((substr) => substr.includes('advices')) || ''; | ||
let advicesValueParsed; | ||
try { | ||
const advicesValueArray = advicesSubstr.match(/"(\S+)"/); | ||
const advicesValue = advicesValueArray ? advicesValueArray[1] : ''; | ||
const advicesValueDecoded = atob(advicesValue); | ||
advicesValueParsed = JSON.parse(advicesValueDecoded); | ||
return advicesValueParsed; | ||
} | ||
catch (err) { | ||
console.error('Could not parse advices value from WWW-Authenticate header'); | ||
} | ||
return {}; | ||
} | ||
function hasAuthzAdvice(json) { | ||
@@ -129,3 +149,3 @@ if (json.advices && json.advices.AuthenticateToServiceConditionAdvice) { | ||
} | ||
function normalizeIGJSON(res) { | ||
function normalizeIGRedirectResponseToAdviceJSON(res) { | ||
const advices = {}; | ||
@@ -146,2 +166,13 @@ if (res.url.includes('AuthenticateToServiceConditionAdvice')) { | ||
} | ||
function normalizeIGJSONResponseToAdviceJSON(res) { | ||
const authHeader = res.headers.get('WWW-Authenticate') || ''; | ||
const advicesObject = getAdvicesFromHeader(authHeader); | ||
return { | ||
resource: '', | ||
actions: {}, | ||
attributes: {}, | ||
advices: advicesObject, | ||
ttl: 0, | ||
}; | ||
} | ||
async function normalizeRESTJSON(res) { | ||
@@ -151,2 +182,2 @@ return await res.json(); | ||
export { addAuthzInfoToHeaders, addAuthzInfoToURL, buildAuthzOptions, examineForIGAuthz, examineForRESTAuthz, hasAuthzAdvice, isAuthzStep, newTokenRequired, normalizeIGJSON, normalizeRESTJSON }; | ||
export { addAuthzInfoToHeaders, addAuthzInfoToURL, buildAuthzOptions, examineForIGAuthz, examineForIGAuthzHeader, examineForRESTAuthz, getAdvicesFromHeader, hasAuthzAdvice, isAuthzStep, newTokenRequired, normalizeIGJSONResponseToAdviceJSON, normalizeIGRedirectResponseToAdviceJSON, normalizeRESTJSON }; |
@@ -9,3 +9,3 @@ import Config from '../config/index.js'; | ||
import { withTimeout } from '../util/timeout.js'; | ||
import { newTokenRequired, examineForIGAuthz, normalizeIGJSON, examineForRESTAuthz, normalizeRESTJSON, buildAuthzOptions, isAuthzStep, hasAuthzAdvice, addAuthzInfoToURL, addAuthzInfoToHeaders } from './helpers.js'; | ||
import { newTokenRequired, examineForIGAuthzHeader, normalizeIGJSONResponseToAdviceJSON, examineForIGAuthz, normalizeIGRedirectResponseToAdviceJSON, examineForRESTAuthz, normalizeRESTJSON, buildAuthzOptions, isAuthzStep, hasAuthzAdvice, addAuthzInfoToURL, addAuthzInfoToHeaders } from './helpers.js'; | ||
import middlewareWrapper from '../util/middleware.js'; | ||
@@ -58,6 +58,10 @@ | ||
if (options.authorization && options.authorization.handleStep) { | ||
if (res.redirected && examineForIGAuthz(res)) { | ||
if (res.status === 401 && examineForIGAuthzHeader(res.headers)) { | ||
hasIG = true; | ||
authorizationJSON = normalizeIGJSON(res); | ||
authorizationJSON = normalizeIGJSONResponseToAdviceJSON(res); | ||
} | ||
else if (res.redirected && examineForIGAuthz(res)) { | ||
hasIG = true; | ||
authorizationJSON = normalizeIGRedirectResponseToAdviceJSON(res); | ||
} | ||
else if (await examineForRESTAuthz(res)) { | ||
@@ -90,3 +94,3 @@ authorizationJSON = await normalizeRESTJSON(res); | ||
// Walk through auth tree | ||
await this.stepIterator(initialStep, options.authorization.handleStep, type, tree); | ||
await this.stepIterator(initialStep, options.authorization.handleStep); | ||
// See if OAuth tokens are being used | ||
@@ -105,2 +109,5 @@ const tokens = await TokenStorage.get(); | ||
} | ||
else { | ||
throw new Error(`Error: Unable to process advice`); | ||
} | ||
} | ||
@@ -124,3 +131,3 @@ return res; | ||
} | ||
static async stepIterator(res, handleStep, type, tree) { | ||
static async stepIterator(res, handleStep) { | ||
const jsonRes = await res.json(); | ||
@@ -132,3 +139,3 @@ const initialStep = new FRStep(jsonRes); | ||
const input = await handleStep(step); | ||
const output = await FRAuth.next(input, { type, tree }); | ||
const output = await FRAuth.next(input, { tree: '', type: '' }); | ||
if (output.type === StepType.LoginSuccess) { | ||
@@ -150,2 +157,5 @@ resolve(); | ||
let headers = new Headers(init.headers || {}); | ||
if (options.authorization) { | ||
headers.set('x-authenticate-response', 'header'); | ||
} | ||
if (!options.bypassAuthentication) { | ||
@@ -152,0 +162,0 @@ headers = await this.setAuthHeaders(headers, forceRenew); |
@@ -189,18 +189,22 @@ import { ActionTypes } from '../config/enums.js'; | ||
const accessToken = tokens && tokens.accessToken; | ||
const body = { | ||
client_id: clientId, | ||
}; | ||
// This is needed to support Token Vault; the SDK may not have the token locally | ||
if (accessToken) { | ||
const init = { | ||
body: stringify({ client_id: clientId, token: accessToken }), | ||
credentials: 'include', | ||
headers: new Headers({ | ||
'Content-Type': 'application/x-www-form-urlencoded', | ||
}), | ||
method: 'POST', | ||
}; | ||
const response = await this.request('revoke', undefined, false, init, options); | ||
if (!isOkOr4xx(response)) { | ||
throw new Error(`Failed to revoke token; received ${response.status}`); | ||
} | ||
return response; | ||
body.token = accessToken; | ||
} | ||
return new Response(); | ||
const init = { | ||
body: stringify(body), | ||
credentials: 'include', | ||
headers: new Headers({ | ||
'Content-Type': 'application/x-www-form-urlencoded', | ||
}), | ||
method: 'POST', | ||
}; | ||
const response = await this.request('revoke', undefined, false, init, options); | ||
if (!isOkOr4xx(response)) { | ||
throw new Error(`Failed to revoke token; received ${response.status}`); | ||
} | ||
return response; | ||
} | ||
@@ -207,0 +211,0 @@ static async request(endpoint, query, includeToken, init, options) { |
@@ -104,5 +104,7 @@ import Config from '../config/index.js'; | ||
const state = PKCE.createState(); | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
const { forceRenew, login, ...config } = options; | ||
// so to not change the type of the above function | ||
// we assign it here if its undefined or null. | ||
const config = Object.assign({}, options); | ||
delete config.forceRenew; | ||
delete config.login; | ||
const authorizeUrlOptions = { | ||
@@ -109,0 +111,0 @@ ...config, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
413529
11213