Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable extraParams to persist to token refresh #1529

Merged
merged 8 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
# Changelog

## 7.6.0
# 7.7.1

- [#1529](https://github.com/okta/okta-auth-js/pull/1529) fix: persist `extraParams` passed to `/authorize` and include them during token refresh

## 7.7.0

### Features

- [#1495](https://github.com/okta/okta-auth-js/pull/1495) add: DPoP support

### Fixes

- [#1508](https://github.com/okta/okta-auth-js/pull/1508) IDX: add condition to compare stateHandles when loading saved idxResponse only when useGenericRemediator option is false or undefined


## 7.6.0

### Features

- [#1507](https://github.com/okta/okta-auth-js/pull/1507) add: new method `getOrRenewAccessToken`
- [#1505](https://github.com/okta/okta-auth-js/pull/1505) add: support of `revokeSessions` param for `OktaPassword` authenticator (can be used in `reset-authenticator` remediation)
- [#1508](https://github.com/okta/okta-auth-js/pull/1508) IDX: add condition to compare stateHandles when loading saved idxResponse only when useGenericRemediator option is false or undefined
- [#1512](https://github.com/okta/okta-auth-js/pull/1512) add: new service `RenewOnTabActivation`

### Bug Fix
Expand Down
7 changes: 6 additions & 1 deletion lib/oidc/endpoints/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,13 @@ export async function postRefreshToken(
return name + '=' + encodeURIComponent(value!);
}).join('&');

let url = refreshToken.tokenUrl;
if (options.extraParams && Object.keys(options.extraParams).length >= 1) {
url += toQueryString(options.extraParams);
}
shawyu-okta marked this conversation as resolved.
Show resolved Hide resolved

const params: TokenRequestParams = {
url: refreshToken.tokenUrl,
url,
data,
dpopKeyPair: options?.dpopKeyPair
};
Expand Down
2 changes: 2 additions & 0 deletions lib/oidc/exchangeCodeForTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export async function exchangeCodeForTokens(sdk: OktaAuthOAuthInterface, tokenPa
acrValues,
dpop,
dpopPairId,
extraParams
} = tokenParams;

// postToTokenEndpoint() params
Expand Down Expand Up @@ -64,6 +65,7 @@ export async function exchangeCodeForTokens(sdk: OktaAuthOAuthInterface, tokenPa
responseType,
ignoreSignature,
acrValues,
extraParams
};

try {
Expand Down
13 changes: 13 additions & 0 deletions lib/oidc/handleOAuthResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export async function handleOAuthResponse(
): Promise<TokenResponse> {
const pkce = sdk.options.pkce !== false;


// The result contains an authorization_code and PKCE is enabled
// `exchangeCodeForTokens` will call /token then call `handleOauthResponse` recursively with the result
if (pkce && (res.code || res.interaction_code)) {
Expand Down Expand Up @@ -106,6 +107,10 @@ export async function handleOAuthResponse(
if (tokenParams.dpopPairId) {
tokenDict.accessToken.dpopPairId = tokenParams.dpopPairId;
}

if (tokenParams.extraParams) {
tokenDict.accessToken.extraParams = tokenParams.extraParams;
}
}

if (refreshToken) {
Expand All @@ -123,6 +128,10 @@ export async function handleOAuthResponse(
if (tokenParams.dpopPairId) {
tokenDict.refreshToken.dpopPairId = tokenParams.dpopPairId;
}

if (tokenParams.extraParams) {
tokenDict.refreshToken.extraParams = tokenParams.extraParams;
}
}

if (idToken) {
Expand All @@ -137,6 +146,10 @@ export async function handleOAuthResponse(
clientId: clientId!
};

if (tokenParams.extraParams) {
idTokenObj.extraParams = tokenParams.extraParams;
}

const validationParams: TokenVerifyParams = {
clientId: clientId!,
issuer: urls.issuer!,
Expand Down
5 changes: 3 additions & 2 deletions lib/oidc/renewToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,15 @@ export async function renewToken(sdk: OktaAuthOAuthInterface, token: Token): Pro
responseType = 'id_token';
}

const { scopes, authorizeUrl, userinfoUrl, issuer, dpopPairId } = token as (AccessToken & IDToken);
const { scopes, authorizeUrl, userinfoUrl, issuer, dpopPairId, extraParams } = token as (AccessToken & IDToken);
return getWithoutPrompt(sdk, {
responseType,
scopes,
authorizeUrl,
userinfoUrl,
issuer,
dpopPairId
dpopPairId,
extraParams
})
.then(function (res) {
return getSingleToken(token, res.tokens);
Expand Down
4 changes: 3 additions & 1 deletion lib/oidc/renewTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ export async function renewTokens(sdk, options?: RenewTokensParams): Promise<Tok
const userinfoUrl = accessToken.userinfoUrl || sdk.options.userinfoUrl;
const issuer = idToken.issuer || sdk.options.issuer;
const dpopPairId = accessToken?.dpopPairId;
const extraParams = accessToken?.extraParams || idToken?.extraParams;

// Get tokens using the SSO cookie
options = Object.assign({
scopes,
authorizeUrl,
userinfoUrl,
issuer,
dpopPairId
dpopPairId,
extraParams
}, options);

if (sdk.options.pkce) {
Expand Down
6 changes: 6 additions & 0 deletions lib/oidc/renewTokensWithRefresh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TokenEndpointParams, postRefreshToken } from './endpoints/token';
import { findKeyPair } from './dpop';
import { isRefreshTokenInvalidError } from './util/errors';

/* eslint complexity:[0,8] */
export async function renewTokensWithRefresh(
sdk: OktaAuthOAuthInterface,
tokenParams: TokenParams,
Expand All @@ -31,6 +32,11 @@ export async function renewTokensWithRefresh(

try {
const renewTokenParams: TokenParams = Object.assign({}, tokenParams, { clientId });

if (refreshTokenObject.extraParams) {
renewTokenParams.extraParams = refreshTokenObject.extraParams;
}

const endpointParams: TokenEndpointParams = {...renewTokenParams};

if (dpop) {
Expand Down
1 change: 1 addition & 0 deletions lib/oidc/types/Token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface AbstractToken {
authorizeUrl: string;
scopes: string[];
pendingRemove?: boolean;
extraParams?: Record<string, string>;
}

export interface AccessToken extends AbstractToken {
Expand Down
3 changes: 2 additions & 1 deletion lib/oidc/types/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export interface OAuthTransactionMeta extends
'ignoreSignature' |
'nonce' |
'acrValues' |
'enrollAmrValues'
'enrollAmrValues' |
'extraParams'
>
{
urls: CustomUrls;
Expand Down
1 change: 1 addition & 0 deletions lib/oidc/util/oauthMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function createOAuthMeta(
nonce: tokenParams.nonce!,
ignoreSignature: tokenParams.ignoreSignature!,
acrValues: tokenParams.acrValues,
extraParams: tokenParams.extraParams
};

if (tokenParams.pkce === false) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"name": "@okta/okta-auth-js",
"description": "The Okta Auth SDK",
"version": "7.7.0",
"version": "7.7.1",
"homepage": "https://github.com/okta/okta-auth-js",
"license": "Apache-2.0",
"main": "build/cjs/exports/default.js",
Expand Down
2 changes: 1 addition & 1 deletion samples/test/cucumber.wdio.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const USE_FIREFOX = !!process.env.USE_FIREFOX;
const DEBUG = process.env.DEBUG;
const CI = process.env.CI;
const LOG = process.env.LOG;
const defaultTimeoutInterval = DEBUG ? (24 * 60 * 60 * 1000) : 10000;
const defaultTimeoutInterval = DEBUG ? (24 * 60 * 60 * 1000) : 15000;
const logLevel = LOG || 'warn';
const chromeOptions = {
args: []
Expand Down
4 changes: 2 additions & 2 deletions scripts/e2e/e2e-mfa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export CLIENT_ID=0oa41zpqqxar7OFl84x7
export SPA_CLIENT_ID=0oa41zpqqxar7OFl84x7
export MFA_ENABLED=true

get_vault_secret_key devex/auth-js-sdk-vars security_question_answer SECURITY_QUESTION_ANSWER
get_vault_secret_key devex/auth-js-sdk-vars a18n_api_key A18N_API_KEY
get_terminus_secret "/" security_question_answer SECURITY_QUESTION_ANSWER
get_terminus_secret "/" a18n_api_key A18N_API_KEY

run_e2e
2 changes: 1 addition & 1 deletion scripts/e2e/e2e-saucelabs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export TEST_RESULT_FILE_DIR="${REPO}/build2/reports/e2e-saucelabs"

# run e2e tests with test/e2e/sauce.wdio.conf.js config
export CLIENT_ID=0oa1xyzajgPFGWlLP4x7
get_vault_secret_key devex/sauce-labs accessKey SAUCE_ACCESS_KEY
get_terminus_secret "/" accessKey SAUCE_ACCESS_KEY

export RUN_SAUCE_TESTS=true
export SAUCE_USERNAME=OktaSignInWidget
Expand Down
4 changes: 2 additions & 2 deletions scripts/integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ export TEST_RESULT_FILE_DIR="${REPO}/build2/reports/unit"
export CI=true
export ISSUER=https://javascript-idx-sdk-idfirst.okta.com
export USERNAME=george@acme.com
get_vault_secret_key repo_gh-okta-okta-auth-js/default password PASSWORD
get_terminus_secret "/" password PASSWORD

# for myaccount password API testing
export PASSWORDLESS_USERNAME=password.optional@mailinator.com
get_vault_secret_key devex/auth-js-sdk-vars a18n_api_key A18N_API_KEY
get_terminus_secret "/" a18n_api_key A18N_API_KEY

# This client has refresh token enabled and password optional
export CLIENT_ID=0oa3b5fp4h02UIrjZ697
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export SAMPLE_NAME=@okta/samples.express-embedded-auth-with-sdk
export MAX_INSTANCES=1

# NOTE: the command below evaluates to the same PASSWORD retrieved in setup-e2e, leaving commented just in case
# get_vault_secret_key devex/prod-js-idx-sdk-vars password PASSWORD
# get_terminus_secret "/" password PASSWORD

# based on run_sample_tests
create_log_group "E2E Test Run"
Expand Down
2 changes: 1 addition & 1 deletion scripts/samples/e2e-express-embedded-auth-with-sdk-spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export SAMPLE_NAME=@okta/samples.express-embedded-auth-with-sdk
export MAX_INSTANCES=1

# NOTE: the command below evaluates to the same PASSWORD retrieved in setup-e2e, leaving commented just in case
# get_vault_secret_key devex/prod-js-idx-sdk-vars password PASSWORD
# get_terminus_secret "/" password PASSWORD

# based on run_sample_tests
create_log_group "E2E Test Run"
Expand Down
2 changes: 1 addition & 1 deletion scripts/samples/e2e-express-embedded-auth-with-sdk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export SAMPLE_NAME=@okta/samples.express-embedded-auth-with-sdk
export MAX_INSTANCES=1

# NOTE: the command below evaluates to the same PASSWORD retrieved in setup-e2e, leaving commented just in case
# get_vault_secret_key devex/prod-js-idx-sdk-vars password PASSWORD
# get_terminus_secret "/" password PASSWORD

# based on run_sample_tests
create_log_group "E2E Spec Test Run"
Expand Down
67 changes: 48 additions & 19 deletions scripts/setup-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,33 @@ if [ -n "${TEST_SUITE_ID}" ]; then
setup_service java 1.8.222

# this chrome install is not used, however it will install linux deps chrome needs (via apt-get)
setup_service google-chrome-stable 118.0.5993.70-1
# setup_service google-chrome-stable 127.0.6533.88-1
setup_service google-chrome-stable 121.0.6167.85-1
# uses new chrome for testing installation utility (https://developer.chrome.com/blog/chrome-for-testing/)
# output format: chrome@118.0.5993.70 /path/to/chrome/binary
CHROME_INSTALL=$(npx @puppeteer/browsers install chrome@stable)
echo $CHROME_INSTALL
# extract installed version
export CHROMEDRIVER_VERSION=$(echo $CHROME_INSTALL | awk '{print $1}' | cut -d'@' -f 2)
echo $CHROMEDRIVER_VERSION
# extract binary path
export CHROME_BINARY=$(echo $CHROME_INSTALL | awk '{print $2}')
echo $CHROME_BINARY
# npm i -g @puppeteer/browsers@1.x
# @puppeteer/browsers install chrome@stable]

# OLD_NPM_REGISTRY=$(npm config get registry)
# npm config set registry https://registry.npmjs.org
# npm config get registry

# echo "Running npx @puppeteer/browsers"
# npx @puppeteer/browsers install chrome@stable --version
# npx @puppeteer/browsers install chrome@stable
# echo "Running puppeteer install"
# CHROME_INSTALL=$(npx @puppeteer/browsers@1.x install chrome@stable)
# echo "CHROME_INSTALL: $CHROME_INSTALL"
# # extract installed version
# export CHROMEDRIVER_VERSION=$(echo $CHROME_INSTALL | awk '{print $1}' | cut -d'@' -f 2)
# echo $CHROMEDRIVER_VERSION
# # extract binary path
# export CHROME_BINARY=$(echo $CHROME_INSTALL | awk '{print $2}')
# echo $CHROME_BINARY

# npm config set registry $OLD_NPM_REGISTRY
# wget -v https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/linux64/chrome-linux64.zip
# echo $(ls)
shawyu-okta marked this conversation as resolved.
Show resolved Hide resolved

export CI=true
else
Expand All @@ -45,12 +61,18 @@ setup_e2e () {

export ISSUER=https://samples-javascript.okta.com/oauth2/default
export USERNAME=george@acme.com
get_vault_secret_key repo_gh-okta-okta-auth-js/default password PASSWORD
get_terminus_secret "/" password PASSWORD
finish_log_group $?
}

run_e2e () {
create_log_group "E2E Test Run"

if [ -z "${PASSWORD}" ]; then
echo "No PASSWORD has been set! Exiting..."
exit ${TEST_FAILURE}
fi

if [ -n "${RUN_CUCUMBER}" ]; then
if ! yarn test:e2e:cucumber; then
echo "Cucumber tests failed! Exiting..."
Expand All @@ -76,42 +98,49 @@ setup_sample_tests () {
export TEST_RESULT_FILE_DIR="${REPO}/build2/reports/e2e"

export USERNAME=mary@acme.com
get_vault_secret_key repo_gh-okta-okta-auth-js/default password PASSWORD
get_terminus_secret "/" password PASSWORD

export ORG_OIE_ENABLED=true
get_vault_secret_key devex/auth-js-sdk-vars a18n_api_key A18N_API_KEY
get_terminus_secret "/" a18n_api_key A18N_API_KEY


# If this script is run as a bacon task, run against trexcloud environment
if [[ "${BACON_TASK}" == true ]]; then
echo "Running tests against trexcloud org"
export ISSUER=https://javascript-idx-sdk.trexcloud.com
export CLIENT_ID=0oa3r1keeeFFb7VMG0g7
export SPA_CLIENT_ID=0oa3r92jj01DWBeWC0g7
get_vault_secret_key devex/trex-js-idx-sdk-vars trex_client_secret CLIENT_SECRET
get_vault_secret_key devex/trex-js-idx-sdk-vars trex_idx_sdk_org_api_key OKTA_API_KEY
get_terminus_secret "/" trex_client_secret CLIENT_SECRET
get_terminus_secret "/" trex_idx_sdk_org_api_key OKTA_API_KEY
else
if [ -n "$USE_OK_14" ]; then
echo "Running tests against production (ok14) org"
export CLIENT_ID=0oax3dcx0sak1KKb9696
export ISSUER=https://javascript-idx-sdk-new.okta.com
export ISSUER_IDFIRST=https://javascript-idx-sdk-idfirst.okta.com
get_vault_secret_key devex/prod-js-idx-sdk-vars prod_client_secret_new CLIENT_SECRET
get_vault_secret_key devex/prod-js-idx-sdk-vars prod_idx_sdk_org_api_key_new OKTA_API_KEY
get_vault_secret_key devex/prod-js-idx-sdk-vars prod_idx_idfirst_sdk_org_api_key OKTA_API_KEY_IDFIRST
get_terminus_secret "/prod/idx" prod_client_secret_new CLIENT_SECRET
get_terminus_secret "/prod/idx" prod_idx_sdk_org_api_key_new OKTA_API_KEY
get_terminus_secret "/prod/idx" prod_idx_idfirst_sdk_org_api_key OKTA_API_KEY_IDFIRST
else
echo "Running tests against production (ok12) org"
export ISSUER=https://javascript-idx-sdk.okta.com
export CLIENT_ID=0oav2oxnlYjULp0Cy5d6
export SPA_CLIENT_ID=0oa17suj5x9khaVH75d7
get_vault_secret_key devex/prod-js-idx-sdk-vars prod_client_secret CLIENT_SECRET
get_vault_secret_key devex/prod-js-idx-sdk-vars prod_idx_sdk_org_api_key OKTA_API_KEY
get_terminus_secret "/prod/idx" prod_client_secret CLIENT_SECRET
get_terminus_secret "/prod/idx" prod_idx_sdk_org_api_key OKTA_API_KEY
fi
fi
finish_log_group $?
}

run_sample_tests () {
create_log_group "E2E Test Run"

if [ -z "${PASSWORD}" ]; then
echo "No PASSWORD has been set! Exiting..."
exit ${TEST_FAILURE}
fi

# Run the tests
if ! yarn test:samples; then
echo "tests failed! Exiting..."
Expand Down
8 changes: 8 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ else
fi
}

get_terminus_secret () {
# ensures the env var is set
if [ -z "$(echo "$3")" ]; then
echo "$3 is not defined. Exiting..."
exit 1
fi
}

junit () {
echo 'noop'
}
Expand Down
Loading