From d89b413ad6050a79c68e8813316afffc81fcc870 Mon Sep 17 00:00:00 2001 From: Jared Perreault <90656038+jaredperreault-okta@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:18:54 -0400 Subject: [PATCH 1/2] feat: enable `extraParams` to persist to token refresh (#1529) OKTA-750886 fix: persist `extraParams` passed to `/authorize` and include them during token refresh --- CHANGELOG.md | 17 ++++- lib/oidc/endpoints/token.ts | 7 +- lib/oidc/exchangeCodeForTokens.ts | 2 + lib/oidc/handleOAuthResponse.ts | 13 ++++ lib/oidc/renewToken.ts | 5 +- lib/oidc/renewTokens.ts | 4 +- lib/oidc/renewTokensWithRefresh.ts | 6 ++ lib/oidc/types/Token.ts | 1 + lib/oidc/types/meta.ts | 3 +- lib/oidc/util/oauthMeta.ts | 1 + package.json | 2 +- samples/test/cucumber.wdio.conf.ts | 2 +- scripts/e2e/e2e-mfa.sh | 4 +- scripts/e2e/e2e-saucelabs.sh | 2 +- scripts/integration.sh | 4 +- ...express-embedded-auth-with-sdk-features.sh | 2 +- ...e2e-express-embedded-auth-with-sdk-spec.sh | 2 +- .../e2e-express-embedded-auth-with-sdk.sh | 2 +- scripts/setup-e2e.sh | 67 +++++++++++++------ scripts/setup.sh | 8 +++ test/apps/app/src/testApp.ts | 3 + test/spec/oidc/endpoints/token.ts | 28 +++++++- test/spec/oidc/exchangeCodeForTokens.ts | 11 ++- test/spec/oidc/parseFromUrl.ts | 6 +- test/spec/oidc/renewTokens.ts | 17 +++++ test/spec/oidc/util/handleOAuthResponse.ts | 10 ++- 26 files changed, 185 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66afc0b95..1b973cf32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/lib/oidc/endpoints/token.ts b/lib/oidc/endpoints/token.ts index e98f2f1e5..8a257a5cc 100644 --- a/lib/oidc/endpoints/token.ts +++ b/lib/oidc/endpoints/token.ts @@ -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); + } + const params: TokenRequestParams = { - url: refreshToken.tokenUrl, + url, data, dpopKeyPair: options?.dpopKeyPair }; diff --git a/lib/oidc/exchangeCodeForTokens.ts b/lib/oidc/exchangeCodeForTokens.ts index 12cba44d0..b679ff020 100644 --- a/lib/oidc/exchangeCodeForTokens.ts +++ b/lib/oidc/exchangeCodeForTokens.ts @@ -37,6 +37,7 @@ export async function exchangeCodeForTokens(sdk: OktaAuthOAuthInterface, tokenPa acrValues, dpop, dpopPairId, + extraParams } = tokenParams; // postToTokenEndpoint() params @@ -64,6 +65,7 @@ export async function exchangeCodeForTokens(sdk: OktaAuthOAuthInterface, tokenPa responseType, ignoreSignature, acrValues, + extraParams }; try { diff --git a/lib/oidc/handleOAuthResponse.ts b/lib/oidc/handleOAuthResponse.ts index 02fa80cb7..ea92baddb 100644 --- a/lib/oidc/handleOAuthResponse.ts +++ b/lib/oidc/handleOAuthResponse.ts @@ -55,6 +55,7 @@ export async function handleOAuthResponse( ): Promise { 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)) { @@ -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) { @@ -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) { @@ -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!, diff --git a/lib/oidc/renewToken.ts b/lib/oidc/renewToken.ts index fcf0dbdd7..d59e28b02 100644 --- a/lib/oidc/renewToken.ts +++ b/lib/oidc/renewToken.ts @@ -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); diff --git a/lib/oidc/renewTokens.ts b/lib/oidc/renewTokens.ts index 3e47d9939..d7f853a47 100644 --- a/lib/oidc/renewTokens.ts +++ b/lib/oidc/renewTokens.ts @@ -41,6 +41,7 @@ export async function renewTokens(sdk, options?: RenewTokensParams): Promise; } export interface AccessToken extends AbstractToken { diff --git a/lib/oidc/types/meta.ts b/lib/oidc/types/meta.ts index 8b857a2b1..fd096d550 100644 --- a/lib/oidc/types/meta.ts +++ b/lib/oidc/types/meta.ts @@ -26,7 +26,8 @@ export interface OAuthTransactionMeta extends 'ignoreSignature' | 'nonce' | 'acrValues' | - 'enrollAmrValues' + 'enrollAmrValues' | + 'extraParams' > { urls: CustomUrls; diff --git a/lib/oidc/util/oauthMeta.ts b/lib/oidc/util/oauthMeta.ts index 6e00e1e6e..94f2ebeb2 100644 --- a/lib/oidc/util/oauthMeta.ts +++ b/lib/oidc/util/oauthMeta.ts @@ -20,6 +20,7 @@ export function createOAuthMeta( nonce: tokenParams.nonce!, ignoreSignature: tokenParams.ignoreSignature!, acrValues: tokenParams.acrValues, + extraParams: tokenParams.extraParams }; if (tokenParams.pkce === false) { diff --git a/package.json b/package.json index b0ff8d5e1..42b3625f3 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/samples/test/cucumber.wdio.conf.ts b/samples/test/cucumber.wdio.conf.ts index e306851ec..63d8c3ef8 100644 --- a/samples/test/cucumber.wdio.conf.ts +++ b/samples/test/cucumber.wdio.conf.ts @@ -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: [] diff --git a/scripts/e2e/e2e-mfa.sh b/scripts/e2e/e2e-mfa.sh index acbfb7e9d..6c5cc580a 100755 --- a/scripts/e2e/e2e-mfa.sh +++ b/scripts/e2e/e2e-mfa.sh @@ -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 diff --git a/scripts/e2e/e2e-saucelabs.sh b/scripts/e2e/e2e-saucelabs.sh index 8dfe0ae9a..1635e9d78 100755 --- a/scripts/e2e/e2e-saucelabs.sh +++ b/scripts/e2e/e2e-saucelabs.sh @@ -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 diff --git a/scripts/integration.sh b/scripts/integration.sh index 282f43e72..cbbc22d68 100755 --- a/scripts/integration.sh +++ b/scripts/integration.sh @@ -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 diff --git a/scripts/samples/e2e-express-embedded-auth-with-sdk-features.sh b/scripts/samples/e2e-express-embedded-auth-with-sdk-features.sh index e4ef719b8..6ba3651b8 100644 --- a/scripts/samples/e2e-express-embedded-auth-with-sdk-features.sh +++ b/scripts/samples/e2e-express-embedded-auth-with-sdk-features.sh @@ -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" diff --git a/scripts/samples/e2e-express-embedded-auth-with-sdk-spec.sh b/scripts/samples/e2e-express-embedded-auth-with-sdk-spec.sh index 18b4a1390..d2ae8e081 100644 --- a/scripts/samples/e2e-express-embedded-auth-with-sdk-spec.sh +++ b/scripts/samples/e2e-express-embedded-auth-with-sdk-spec.sh @@ -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" diff --git a/scripts/samples/e2e-express-embedded-auth-with-sdk.sh b/scripts/samples/e2e-express-embedded-auth-with-sdk.sh index d93e81b67..ddb61d23c 100755 --- a/scripts/samples/e2e-express-embedded-auth-with-sdk.sh +++ b/scripts/samples/e2e-express-embedded-auth-with-sdk.sh @@ -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" diff --git a/scripts/setup-e2e.sh b/scripts/setup-e2e.sh index 59dbfb555..4243603d0 100755 --- a/scripts/setup-e2e.sh +++ b/scripts/setup-e2e.sh @@ -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) export CI=true else @@ -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..." @@ -76,10 +98,11 @@ 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 @@ -87,24 +110,24 @@ setup_sample_tests () { 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 $? @@ -112,6 +135,12 @@ setup_sample_tests () { 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..." diff --git a/scripts/setup.sh b/scripts/setup.sh index b05a8d166..0c9c57e42 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -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' } diff --git a/test/apps/app/src/testApp.ts b/test/apps/app/src/testApp.ts index e8301b7fb..c7f5470a7 100644 --- a/test/apps/app/src/testApp.ts +++ b/test/apps/app/src/testApp.ts @@ -674,6 +674,9 @@ class TestApp { scopes: this.config.defaultScopes ? [] : this.config.scopes, acrValues: this.config.acrValues, state: this.config.state, + extraParams: { + foo: 'bar' + } }, options); return this.oktaAuth.token.getWithRedirect(options) .catch(e => { diff --git a/test/spec/oidc/endpoints/token.ts b/test/spec/oidc/endpoints/token.ts index 5cb4596ac..770653ee6 100644 --- a/test/spec/oidc/endpoints/token.ts +++ b/test/spec/oidc/endpoints/token.ts @@ -40,6 +40,7 @@ describe('token endpoint', function() { var endpoint = '/oauth2/v1/token'; var codeVerifier = 'superfake'; var authorizationCode = 'notreal'; + var extraParams = { foo: 'bar' }; util.itMakesCorrectRequestResponse({ title: 'requests a token', @@ -55,7 +56,7 @@ describe('token endpoint', function() { data: { client_id: CLIENT_ID, grant_type: 'authorization_code', - redirect_uri: REDIRECT_URI + redirect_uri: REDIRECT_URI, }, headers: { 'Accept': 'application/json', @@ -80,7 +81,7 @@ describe('token endpoint', function() { clientId: CLIENT_ID, redirectUri: REDIRECT_URI, authorizationCode: authorizationCode, - codeVerifier: codeVerifier, + codeVerifier: codeVerifier }, { tokenUrl: ISSUER + endpoint }); @@ -156,6 +157,29 @@ describe('token endpoint', function() { }); + describe('postRefreshToken', () => { + var authClient; + + beforeEach(function() { + spyOn(OktaAuth.features, 'isPKCESupported').and.returnValue(true); + authClient = new OktaAuth({ + issuer: 'https://auth-js-test.okta.com' + }); + }); + + it('should append extra params as query params', async () => { + var httpRequest = jest.spyOn(mocked.http, 'httpRequest').mockImplementation(); + const refreshToken = tokens.standardRefreshTokenParsed; + await postRefreshToken(authClient, { extraParams }, refreshToken); + expect(httpRequest).toHaveBeenCalled(); + expect(httpRequest).toHaveBeenLastCalledWith(expect.any(OktaAuth), expect.objectContaining({ + url: 'https://auth-js-test.okta.com/oauth2/v1/token?foo=bar', + method: 'POST', + headers: {'Content-Type': 'application/x-www-form-urlencoded' } + })); + }); + }); + describe('dpop', () => { const ctx: any = {}; diff --git a/test/spec/oidc/exchangeCodeForTokens.ts b/test/spec/oidc/exchangeCodeForTokens.ts index d2e0ac86a..19d3cca55 100644 --- a/test/spec/oidc/exchangeCodeForTokens.ts +++ b/test/spec/oidc/exchangeCodeForTokens.ts @@ -52,7 +52,13 @@ describe('exchangeCodeForTokens', () => { (postToTokenEndpoint as jest.Mock).mockResolvedValue(oauthResponse); (handleOAuthResponse as jest.Mock).mockResolvedValue(tokenResponse); const acrValues = 'foo'; - const tokenParams = { ...testParams, acrValues }; + const tokenParams = { + ...testParams, + acrValues, + extraParams: { + foo: 'bar' + } + }; const urls = getOAuthUrls(sdk); await exchangeCodeForTokens(sdk, tokenParams); expect(postToTokenEndpoint).toHaveBeenCalledWith(sdk, testParams, urls); @@ -62,7 +68,8 @@ describe('exchangeCodeForTokens', () => { redirectUri: testParams.redirectUri, responseType: ['token', 'id_token'], scopes: ['openid', 'email'], - acrValues + acrValues, + extraParams: tokenParams.extraParams }, oauthResponse, urls); }); diff --git a/test/spec/oidc/parseFromUrl.ts b/test/spec/oidc/parseFromUrl.ts index 60dd3d341..65c76995f 100644 --- a/test/spec/oidc/parseFromUrl.ts +++ b/test/spec/oidc/parseFromUrl.ts @@ -51,7 +51,8 @@ describe('token.parseFromUrl', function() { oktaAuthArgs: { pkce: false, responseMode: 'query', - responseType: ['code'] + responseType: ['code'], + extraParams: { foo: 'bar' } }, searchMock: '?code=fake' + '&state=' + oauthUtil.mockedState, @@ -65,7 +66,8 @@ describe('token.parseFromUrl', function() { tokenUrl: 'https://auth-js-test.okta.com/oauth2/v1/token', authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' - } + }, + extraParams: { foo: 'bar' } }, expectedResp: { code: 'fake', diff --git a/test/spec/oidc/renewTokens.ts b/test/spec/oidc/renewTokens.ts index 985e51fec..5ae4fc5eb 100644 --- a/test/spec/oidc/renewTokens.ts +++ b/test/spec/oidc/renewTokens.ts @@ -293,6 +293,23 @@ describe('token.renewTokens', function() { }); }); + it('extraParams', async () => { + const { sdk, accessToken, idToken, getWihoutPromptResponse, withoutPromptSpy } = testContext; + accessToken.extraParams = { foo: 'bar' }; + const tokens = { fake: true }; + getWihoutPromptResponse.tokens = tokens; + const res = await renewTokens(sdk, {}); + expect(res).toBe(tokens); + expect(withoutPromptSpy).toHaveBeenCalledWith(sdk, { + authorizeUrl: accessToken.authorizeUrl, + issuer: idToken.issuer, + responseType: ['token', 'id_token'], + scopes: accessToken.scopes, + userinfoUrl: accessToken.userinfoUrl, + extraParams: { foo: 'bar' } + }); + }); + }); }); diff --git a/test/spec/oidc/util/handleOAuthResponse.ts b/test/spec/oidc/util/handleOAuthResponse.ts index 6d6837796..c41774b8d 100644 --- a/test/spec/oidc/util/handleOAuthResponse.ts +++ b/test/spec/oidc/util/handleOAuthResponse.ts @@ -59,16 +59,23 @@ describe('handleOAuthResponse', () => { expect(res.tokens.refreshToken!.refreshToken).toBe('foo'); }); it('returns all tokens from the response', async () => { - const tokenParams: TokenParams = { responseType: ['token', 'id_token', 'refresh_token'], dpop: true }; + const tokenParams: TokenParams = { + responseType: ['token', 'id_token', 'refresh_token'], + dpop: true, + extraParams: { foo: 'bar' } + }; const oauthRes = { id_token: 'foo', access_token: 'blar', refresh_token: 'bloo', token_type: 'DPoP' }; const res = await handleOAuthResponse(sdk, tokenParams, oauthRes, undefined as unknown as CustomUrls); expect(res.tokens).toBeTruthy(); expect(res.tokens.accessToken).toBeTruthy(); expect(res.tokens.accessToken!.accessToken).toBe('blar'); + expect(res.tokens.accessToken!.extraParams).toEqual({ foo: 'bar' }); expect(res.tokens.idToken).toBeTruthy(); expect(res.tokens.idToken!.idToken).toBe('foo'); + expect(res.tokens.idToken!.extraParams).toEqual({ foo: 'bar' }); expect(res.tokens.refreshToken).toBeTruthy(); expect(res.tokens.refreshToken!.refreshToken).toBe('bloo'); + expect(res.tokens.refreshToken!.extraParams).toEqual({ foo: 'bar' }); }); it('prefers "scope" value from endpoint response over method parameter', async () => { const tokenParams: TokenParams = { responseType: ['token', 'id_token', 'refresh_token'], scopes: ['profile'] }; @@ -78,7 +85,6 @@ describe('handleOAuthResponse', () => { expect(res.tokens.idToken!.scopes).toEqual(['openid', 'offline_access']); expect(res.tokens.refreshToken!.scopes).toEqual(['openid', 'offline_access']); }); - describe('errors', () => { it('does not throw if response contains only "error" without "error_description"', async () => { let errorThrown = false; From 45ea58f53983a5fa0cfe0c086d34183e6dc77eab Mon Sep 17 00:00:00 2001 From: Jared Perreault <90656038+jaredperreault-okta@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:01:49 -0400 Subject: [PATCH 2/2] fix: fixes failing tests (#1533) OKTA-750886 fixes ci test --- ...service-registration-custom-attribute.feature | 2 +- .../features/self-service-registration.feature | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/samples/test/features/self-service-registration-custom-attribute.feature b/samples/test/features/self-service-registration-custom-attribute.feature index 1648132f8..7c4dd96a8 100644 --- a/samples/test/features/self-service-registration-custom-attribute.feature +++ b/samples/test/features/self-service-registration-custom-attribute.feature @@ -16,4 +16,4 @@ Feature: Add another Required Attribute to the Profile Enrollment Policy And she fills out another property And she submits the form # Then her user is created in the "Staged" state - Then she is redirected to the "Select Authenticator Method" page + Then she is redirected to the "Select Authenticator" page diff --git a/samples/test/features/self-service-registration.feature b/samples/test/features/self-service-registration.feature index 1fdf7a635..2d40b123b 100644 --- a/samples/test/features/self-service-registration.feature +++ b/samples/test/features/self-service-registration.feature @@ -20,8 +20,8 @@ Scenario: Mary signs up for an account with Password, setups up required Email f And she fills out her Last Name And she fills out her Email And she submits the form - Then she is redirected to the "Select Authenticator Method" page - When she selects the "email" method + Then she is redirected to the "Select Authenticator" page + When she selects the "Email" factor And she submits the form Then she sees a page to input a code for email authenticator enrollment When she inputs the correct code from her "Email" @@ -47,8 +47,8 @@ Scenario: Mary signs up for an account with Password, setups up required Email f And she fills out her Last Name And she fills out her Email And she submits the form - Then she is redirected to the "Select Authenticator Method" page - When she selects the "email" method + Then she is redirected to the "Select Authenticator" page + When she selects the "Email" factor And she submits the form Then she sees a page to input a code for email authenticator enrollment When she inputs the correct code from her "Email" @@ -90,8 +90,8 @@ Scenario: Mary signs up for an account with Password, sets up required Email fac And she fills out her Last Name And she fills out her Email And she submits the form - Then she is redirected to the "Select Authenticator Method" page - When she selects the "email" method + Then she is redirected to the "Select Authenticator" page + When she selects the "Email" factor And she submits the form Then she sees a page to input a code for email authenticator enrollment When she inputs the correct code from her "Email" @@ -118,8 +118,8 @@ Scenario: Mary signs up for an account with Password, setups up required Email f And she fills out her Last Name And she fills out her Email And she submits the form - Then she is redirected to the "Select Authenticator Method" page - When she selects the "email" method + Then she is redirected to the "Select Authenticator" page + When she selects the "Email" factor And she submits the form Then she sees a page to input a code for email authenticator enrollment When she clicks the Email magic link for email verification