From 928a55e4e2ffc6ed4ebce541b292e54b2e6f7fb7 Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Tue, 12 Jul 2016 18:19:20 -0700 Subject: [PATCH 1/6] Added token.getWithPopup Resolves: OKTA-94708 --- lib/clientBuilder.js | 3 +- lib/token.js | 9 +++ test/spec/token.js | 176 +++++++++++++++++++++++++++++++++++++++++ test/util/oauthUtil.js | 3 + 4 files changed, 190 insertions(+), 1 deletion(-) diff --git a/lib/clientBuilder.js b/lib/clientBuilder.js index 869fec48a..5a5e52e46 100644 --- a/lib/clientBuilder.js +++ b/lib/clientBuilder.js @@ -66,7 +66,7 @@ function OktaAuthBuilder(args) { }; sdk.idToken = { - authorize: util.bind(token.getIdToken, sdk, sdk), // deprecated for sessionToken + authorize: util.bind(token.getIdToken, sdk, sdk), // deprecated for sessionToken and idp flows verify: util.bind(token.verifyIdToken, sdk, sdk), refresh: util.bind(token.refreshIdToken, sdk, sdk), decode: util.bind(token.decodeToken, sdk) // deprecated @@ -79,6 +79,7 @@ function OktaAuthBuilder(args) { sdk.token = { getWithoutPrompt: util.bind(token.getWithoutPrompt, sdk, sdk), + getWithPopup: util.bind(token.getWithPopup, sdk, sdk), decode: util.bind(token.decodeToken, sdk) }; } diff --git a/lib/token.js b/lib/token.js index 43d9e7d97..bd7c9aefd 100644 --- a/lib/token.js +++ b/lib/token.js @@ -543,9 +543,18 @@ function getWithoutPrompt(sdk, oauthOptions, options) { return getIdToken(sdk, oauthParams, options); } +function getWithPopup(sdk, oauthOptions, options) { + var oauthParams = util.clone(oauthOptions) || {}; + util.extend(oauthParams, { + display: 'popup' + }); + return getIdToken(sdk, oauthParams, options); +} + module.exports = { getIdToken: getIdToken, getWithoutPrompt: getWithoutPrompt, + getWithPopup: getWithPopup, refreshIdToken: refreshIdToken, decodeToken: decodeToken, verifyIdToken: verifyIdToken diff --git a/test/spec/token.js b/test/spec/token.js index 4bb50e282..0d7853d83 100644 --- a/test/spec/token.js +++ b/test/spec/token.js @@ -263,4 +263,180 @@ define(function(require) { } ); }); + + describe('token.getWithPopup', function () { + it('returns id_token using idp', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }, + getWithPopupArgs: { + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + } + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token using sessionToken', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }, + getWithPopupArgs: { + responseType: 'token', + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'response_type': 'token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + }, + time: 1449699929, + postMessageResp: { + 'access_token': tokens.standardAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: { + accessToken: tokens.standardAccessToken, + expiresAt: 1449703529, + scopes: ['openid', 'email'], + tokenType: 'Bearer' + } + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token and id_token (in that order) using idp', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }, + getWithPopupArgs: { + responseType: ['token', 'id_token'], + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'response_type': 'token id_token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + }, + time: 1449699929, + postMessageResp: { + 'id_token': tokens.standardIdToken, + 'access_token': tokens.standardAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: [{ + accessToken: tokens.standardAccessToken, + expiresAt: 1449703529, + scopes: ['openid', 'email'], + tokenType: 'Bearer' + }, { + idToken: tokens.standardIdToken, + claims: tokens.standardIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'email'] + }] + }) + .fin(function() { + done(); + }); + }); + + it('returns id_token and access_token (in that order) using idp', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }, + getWithPopupArgs: { + responseType: ['id_token', 'token'], + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'response_type': 'id_token token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + }, + time: 1449699929, + postMessageResp: { + 'id_token': tokens.standardIdToken, + 'access_token': tokens.standardAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: [{ + idToken: tokens.standardIdToken, + claims: tokens.standardIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'email'] + }, { + accessToken: tokens.standardAccessToken, + expiresAt: 1449703529, + scopes: ['openid', 'email'], + tokenType: 'Bearer' + }] + }) + .fin(function() { + done(); + }); + }); + }); }); diff --git a/test/util/oauthUtil.js b/test/util/oauthUtil.js index efcd2224f..3d017a32e 100644 --- a/test/util/oauthUtil.js +++ b/test/util/oauthUtil.js @@ -35,6 +35,7 @@ define(function(require) { if (opts && (opts.authorizeArgs && opts.authorizeArgs.responseMode !== 'fragment') || opts.getWithoutPromptArgs || + opts.getWithPopupArgs || opts.refreshArgs) { // Simulate the postMessage between the window and the popup or iframe spyOn(window, 'addEventListener').and.callFake(function(eventName, fn) { @@ -80,6 +81,8 @@ define(function(require) { promise = authClient.idToken.refresh(opts.refreshArgs); } else if (opts.getWithoutPromptArgs) { promise = authClient.token.getWithoutPrompt(opts.getWithoutPromptArgs); + } else if (opts.getWithPopupArgs) { + promise = authClient.token.getWithPopup(opts.getWithPopupArgs); } else { promise = authClient.idToken.authorize(opts.authorizeArgs); } From f680133c0c536823a8442e812df959aec3c943bf Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Fri, 15 Jul 2016 12:33:19 -0700 Subject: [PATCH 2/6] Added token.getWithRedirect and token.parseFromUrl Resolves: OKTA-94711 --- lib/clientBuilder.js | 12 ++ lib/cookies.js | 14 +- lib/token.js | 335 ++++++++++++++++++++++++----------------- package.json | 3 +- test/spec/oauth.js | 4 +- test/spec/token.js | 248 ++++++++++++++++++++++++++++++ test/util/oauthUtil.js | 102 +++++++++---- test/util/util.js | 21 ++- webpack.config.js | 5 +- 9 files changed, 570 insertions(+), 174 deletions(-) diff --git a/lib/clientBuilder.js b/lib/clientBuilder.js index 5a5e52e46..917c73912 100644 --- a/lib/clientBuilder.js +++ b/lib/clientBuilder.js @@ -80,8 +80,20 @@ function OktaAuthBuilder(args) { sdk.token = { getWithoutPrompt: util.bind(token.getWithoutPrompt, sdk, sdk), getWithPopup: util.bind(token.getWithPopup, sdk, sdk), + getWithRedirect: util.bind(token.getWithRedirect, sdk, sdk), + parseFromUrl: util.bind(token.parseFromUrl, sdk, sdk), decode: util.bind(token.decodeToken, sdk) }; + + // This is exposed so we can set window.location in our tests + sdk.token.getWithRedirect._setLocation = function(url) { + window.location = url; + }; + + // This is exposed so we can mock window.location.hash in our tests + sdk.token.parseFromUrl._getLocationHash = function(url) { + return window.location.hash; + }; } var proto = OktaAuthBuilder.prototype; diff --git a/lib/cookies.js b/lib/cookies.js index d089ea1b7..aec9f2f9e 100644 --- a/lib/cookies.js +++ b/lib/cookies.js @@ -7,14 +7,19 @@ function setCookie(name, value, expiresAt) { } var cookieText = name + '=' + value + ';' + expiresText; - document.cookie = cookieText; + setCookie._setDocumentCookie(cookieText); return cookieText; } +// Exposed for testing +setCookie._setDocumentCookie = function(cookieText) { + document.cookie = cookieText; +}; + function getCookie(name) { var pattern = new RegExp(name + '=([^;]*)'), - matched = document.cookie.match(pattern); + matched = getCookie._getDocumentCookie().match(pattern); if (matched) { var cookie = matched[1]; @@ -22,6 +27,11 @@ function getCookie(name) { } } +// Exposed for testing +getCookie._getDocumentCookie = function() { + return document.cookie; +}; + function deleteCookie(name) { setCookie(name, '', '1970-01-01T00:00:00Z'); } diff --git a/lib/token.js b/lib/token.js index bd7c9aefd..48d613c33 100644 --- a/lib/token.js +++ b/lib/token.js @@ -6,6 +6,7 @@ var sdkCrypto = require('./crypto'); var AuthSdkError = require('./errors/AuthSdkError'); var OAuthError = require('./errors/OAuthError'); var config = require('./config.json'); +var cookies = require('./cookies'); function getWellKnown(sdk) { return http.get(sdk, sdk.options.url + '/.well-known/openid-configuration'); @@ -190,37 +191,37 @@ function addPostMessageListener(sdk, timeout) { }); } -function addFragmentListener(sdk, windowEl, timeout) { - var deferred = Q.defer(); - +function hashToObject(hash) { // Predefine regexs for parsing hash var plus2space = /\+/g; var paramSplit = /([^&=]+)=?([^&]*)/g; - function hashToObject(hash) { - // Remove the leading hash - var fragment = hash.substring(1); + // Remove the leading hash + var fragment = hash.substring(1); - var obj = {}; + var obj = {}; - // Loop until we have no more params - var param; - while (true) { // eslint-disable-line no-constant-condition - param = paramSplit.exec(fragment); - if (!param) { break; } + // Loop until we have no more params + var param; + while (true) { // eslint-disable-line no-constant-condition + param = paramSplit.exec(fragment); + if (!param) { break; } - var key = param[1]; - var value = param[2]; + var key = param[1]; + var value = param[2]; - // id_token should remain base64url encoded - if (key === 'id_token') { - obj[key] = value; - } else { - obj[key] = decodeURIComponent(value.replace(plus2space, ' ')); - } + // id_token should remain base64url encoded + if (key === 'id_token' || key === 'access_token') { + obj[key] = value; + } else { + obj[key] = decodeURIComponent(value.replace(plus2space, ' ')); } - return obj; } + return obj; +} + +function addFragmentListener(sdk, windowEl, timeout) { + var deferred = Q.defer(); function hashChangeHandler() { /* @@ -248,6 +249,129 @@ function addFragmentListener(sdk, windowEl, timeout) { return deferred.promise.timeout(timeout || 120000, new AuthSdkError('OAuth flow timed out')); } +function handleOAuthResponse(sdk, oauthParams, res) { + if (res['error'] || res['error_description']) { + throw new OAuthError(res['error'], res['error_description']); + } + + if (res.state !== oauthParams.state) { + throw new AuthSdkError('OAuth flow response state doesn\'t match request state'); + } + + var tokenTypes = oauthParams.responseType; + var scopes = util.clone(oauthParams.scope); + var tokenDict = {}; + + if (res['id_token']) { + var jwt = sdk.idToken.decode(res['id_token']); + if (jwt.payload.nonce !== oauthParams.nonce) { + throw new AuthSdkError('OAuth flow response nonce doesn\'t match request nonce'); + } + + var clientId = oauthParams.clientId || sdk.options.clientId; + validateClaims(jwt.payload, sdk.options.url, clientId); + + var idToken = { + idToken: res['id_token'], + claims: jwt.payload, + expiresAt: jwt.payload.exp, + scopes: scopes + }; + + if (Array.isArray(tokenTypes)) { + tokenDict['id_token'] = idToken; + } else { + return idToken; + } + } + + if (res['access_token']) { + var accessToken = { + accessToken: res['access_token'], + expiresAt: Number(res['expires_in']) + Math.floor(Date.now()/1000), + tokenType: res['token_type'], + scopes: scopes + }; + + if (Array.isArray(tokenTypes)) { + tokenDict['token'] = accessToken; + } else { + return accessToken; + } + } + + if (!tokenDict['token'] && !tokenDict['id_token']) { + throw new AuthSdkError('Unable to parse OAuth flow response'); + } + + var tokens = []; + + // Create token array in the order of the responseType array + for (var t = 0, tl = tokenTypes.length; t < tl; t++) { + var tokenType = tokenTypes[t]; + tokens.push(tokenDict[tokenType]); + } + + return tokens; +} + +function getDefaultOAuthParams(sdk, oauthOptions) { + oauthOptions = util.clone(oauthOptions) || {}; + var defaults = { + clientId: sdk.options.clientId, + redirectUri: sdk.options.redirectUri || window.location.href, + responseType: 'id_token', + responseMode: 'okta_post_message', + state: util.genRandomString(64), + nonce: util.genRandomString(64), + scope: ['openid', 'email'] + }; + util.extend(defaults, oauthOptions); + return defaults; +} + +function convertOAuthParamsToQueryParams(oauthParams) { + // Quick validation + if (!oauthParams.clientId) { + throw new AuthSdkError('A clientId must be specified in the OktaAuth constructor to get a token'); + } + + if (util.isString(oauthParams.responseType) && oauthParams.responseType.indexOf(' ') !== -1) { + throw new AuthSdkError('Multiple OAuth responseTypes must be defined as an array'); + } + + // Convert our params to their actual OAuth equivalents + var oauthQueryParams = util.removeNils({ + 'client_id': oauthParams.clientId, + 'redirect_uri': oauthParams.redirectUri, + 'response_type': oauthParams.responseType, + 'response_mode': oauthParams.responseMode, + 'state': oauthParams.state, + 'nonce': oauthParams.nonce, + 'prompt': oauthParams.prompt, + 'display': oauthParams.display, + 'sessionToken': oauthParams.sessionToken, + 'idp': oauthParams.idp + }); + + if (Array.isArray(oauthQueryParams['response_type'])) { + oauthQueryParams['response_type'] = oauthQueryParams['response_type'].join(' '); + } + + if (oauthParams.scope.indexOf('openid') !== -1) { + oauthQueryParams.scope = oauthParams.scope.join(' '); + } else { + throw new AuthSdkError('openid scope must be specified in the scope argument'); + } + + return oauthQueryParams; +} + +function buildAuthorizeUrl(sdk, oauthParams) { + var oauthQueryParams = convertOAuthParamsToQueryParams(oauthParams); + return sdk.options.url + '/oauth2/v1/authorize' + util.toQueryParams(oauthQueryParams); +} + /* * Retrieve an idToken from an Okta or a third party idp * @@ -308,18 +432,7 @@ function getIdToken(sdk, oauthOptions, options) { } // Default OAuth query params - var oauthParams = { - clientId: sdk.options.clientId, - redirectUri: sdk.options.redirectUri || window.location.href, - responseType: 'id_token', - responseMode: 'okta_post_message', - state: util.genRandomString(64), - nonce: util.genRandomString(64), - scope: ['openid', 'email'] - }; - - // Add user-provided options - util.extend(oauthParams, oauthOptions); + var oauthParams = getDefaultOAuthParams(sdk, oauthOptions); // Start overriding any options that don't make sense var sessionTokenOverrides = { @@ -338,41 +451,8 @@ function getIdToken(sdk, oauthOptions, options) { util.extend(oauthParams, idpOverrides); } - // Quick validation - if (!oauthParams.clientId) { - throw new AuthSdkError('A clientId must be specified in the OktaAuth constructor to get an idToken'); - } - - if (util.isString(oauthParams.responseType) && oauthParams.responseType.indexOf(' ') !== -1) { - throw new AuthSdkError('Multiple OAuth responseTypes must be defined as an array'); - } - - // Convert our params to their actual OAuth equivalents - var oauthQueryHash = util.removeNils({ - 'client_id': oauthParams.clientId, - 'redirect_uri': oauthParams.redirectUri, - 'response_type': oauthParams.responseType, - 'response_mode': oauthParams.responseMode, - 'state': oauthParams.state, - 'nonce': oauthParams.nonce, - 'prompt': oauthParams.prompt, - 'display': oauthParams.display, - 'sessionToken': oauthParams.sessionToken, - 'idp': oauthParams.idp - }); - - if (Array.isArray(oauthQueryHash['response_type'])) { - oauthQueryHash['response_type'] = oauthQueryHash['response_type'].join(' '); - } - - if (oauthParams.scope.indexOf('openid') !== -1) { - oauthQueryHash.scope = oauthParams.scope.join(' '); - } else { - throw new AuthSdkError('openid scope must be specified in the scope argument'); - } - // Use the query params to build the authorize url - var requestUrl = sdk.options.url + '/oauth2/v1/authorize' + util.toQueryParams(oauthQueryHash); + var requestUrl = buildAuthorizeUrl(sdk, oauthParams); // Determine the flow type var flowType; @@ -384,74 +464,6 @@ function getIdToken(sdk, oauthOptions, options) { flowType = 'IMPLICIT'; } - function handleOAuthResponse(res) { - if (res['error'] || res['error_description']) { - throw new OAuthError(res['error'], res['error_description']); - } - - if (res.state !== oauthParams.state) { - throw new AuthSdkError('OAuth flow response state doesn\'t match request state'); - } - - // If we're passed an array of tokenTypes, - // we return an array in the order specified. - // Otherwise, we return only the token requested - var tokenTypes = oauthParams.responseType; - var scopes = oauthQueryHash.scope.split(' '); - var tokenDict = {}; - - if (res['id_token']) { - var jwt = sdk.idToken.decode(res['id_token']); - if (jwt.payload.nonce !== oauthParams.nonce) { - throw new AuthSdkError('OAuth flow response nonce doesn\'t match request nonce'); - } - - validateClaims(jwt.payload, sdk.options.url, oauthParams.clientId); - - var idToken = { - idToken: res['id_token'], - claims: jwt.payload, - expiresAt: jwt.payload.exp, - scopes: scopes - }; - - if (Array.isArray(tokenTypes)) { - tokenDict['id_token'] = idToken; - } else { - return idToken; - } - } - - if (res['access_token']) { - var accessToken = { - accessToken: res['access_token'], - expiresAt: Number(res['expires_in']) + Math.floor(Date.now()/1000), - tokenType: res['token_type'], - scopes: scopes - }; - - if (Array.isArray(tokenTypes)) { - tokenDict['token'] = accessToken; - } else { - return accessToken; - } - } - - if (!tokenDict['token'] && !tokenDict['id_token']) { - throw new AuthSdkError('Unable to parse OAuth flow response'); - } - - var tokens = []; - - // Create token array in the order of the responseType array - for (var t = 0, tl = tokenTypes.length; t < tl; t++) { - var tokenType = tokenTypes[t]; - tokens.push(tokenDict[tokenType]); - } - - return tokens; - } - function getOrigin(url) { var originRegex = /^(https?\:\/\/)?([^:\/?#]*(?:\:[0-9]+)?)/; return originRegex.exec(url)[0]; @@ -463,7 +475,9 @@ function getIdToken(sdk, oauthOptions, options) { var iframePromise = addPostMessageListener(sdk, options.timeout); var iframeEl = loadFrame(requestUrl, config.FRAME_ID); return iframePromise - .then(handleOAuthResponse) + .then(function(res) { + return handleOAuthResponse(sdk, oauthParams, res); + }) .fin(function() { if (document.body.contains(iframeEl)) { iframeEl.parentElement.removeChild(iframeEl); @@ -520,7 +534,9 @@ function getIdToken(sdk, oauthOptions, options) { }); return popupDeferred.promise - .then(handleOAuthResponse) + .then(function(res) { + return handleOAuthResponse(sdk, oauthParams, res); + }) .fin(function() { if (!windowEl.closed) { clearInterval(closePoller); @@ -551,10 +567,55 @@ function getWithPopup(sdk, oauthOptions, options) { return getIdToken(sdk, oauthParams, options); } +function getWithRedirect(sdk, oauthOptions, options) { + oauthOptions = util.clone(oauthOptions) || {}; + var oauthParams = getDefaultOAuthParams(sdk, oauthOptions); + util.extend(oauthParams, { + responseMode: 'fragment' + }); + var requestUrl = buildAuthorizeUrl(sdk, oauthParams); + + // Set session cookie to store the oauthParams + cookies.setCookie(config.REDIRECT_OAUTH_PARAMS_COOKIE_NAME, JSON.stringify({ + responseType: oauthParams.responseType, + state: oauthParams.state, + nonce: oauthParams.nonce, + scope: oauthParams.scope + })); + + sdk.token.getWithRedirect._setLocation(requestUrl); +} + +function parseFromUrl(sdk, url) { + var hash = sdk.token.parseFromUrl._getLocationHash(); + if (url) { + hash = url.substring(url.indexOf('#')); + } + + var oauthParamsCookie = cookies.getCookie(config.REDIRECT_OAUTH_PARAMS_COOKIE_NAME); + if (!hash || !oauthParamsCookie) { + return Q.reject(new AuthSdkError('Unable to parse a token from the url')); + } + try { + var oauthParams = JSON.parse(oauthParamsCookie); + cookies.deleteCookie(config.REDIRECT_OAUTH_PARAMS_COOKIE_NAME); + } catch(e) { + return Q.reject(new AuthSdkError('Unable to parse the ' + + config.REDIRECT_OAUTH_PARAMS_COOKIE_NAME + ' cookie: ' + e.message)); + } + + return Q.resolve(hashToObject(hash)) + .then(function(res) { + return handleOAuthResponse(sdk, oauthParams, res); + }); +} + module.exports = { getIdToken: getIdToken, getWithoutPrompt: getWithoutPrompt, getWithPopup: getWithPopup, + getWithRedirect: getWithRedirect, + parseFromUrl: parseFromUrl, refreshIdToken: refreshIdToken, decodeToken: decodeToken, verifyIdToken: verifyIdToken diff --git a/package.json b/package.json index 35718e9c8..3fbd372c5 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "okta-auth-js": { "STATE_TOKEN_COOKIE_NAME": "oktaStateToken", "DEFAULT_POLLING_DELAY": 500, - "FRAME_ID": "okta-oauth-helper-frame" + "FRAME_ID": "okta-oauth-helper-frame", + "REDIRECT_OAUTH_PARAMS_COOKIE_NAME": "okta-oauth-redirect-params" } } diff --git a/test/spec/oauth.js b/test/spec/oauth.js index 7c803c892..f523ac353 100644 --- a/test/spec/oauth.js +++ b/test/spec/oauth.js @@ -260,9 +260,9 @@ define(function(require) { }, { name: 'AuthSdkError', - message: 'A clientId must be specified in the OktaAuth constructor to get an idToken', + message: 'A clientId must be specified in the OktaAuth constructor to get a token', errorCode: 'INTERNAL', - errorSummary: 'A clientId must be specified in the OktaAuth constructor to get an idToken', + errorSummary: 'A clientId must be specified in the OktaAuth constructor to get a token', errorLink: 'INTERNAL', errorId: 'INTERNAL', errorCauses: [] diff --git a/test/spec/token.js b/test/spec/token.js index 0d7853d83..f28cc4d69 100644 --- a/test/spec/token.js +++ b/test/spec/token.js @@ -439,4 +439,252 @@ define(function(require) { }); }); }); + + describe('token.getWithRedirect', function() { + it('sets authorize url and cookie for id_token using sessionToken', function() { + oauthUtil.setupRedirect({ + getWithRedirectArgs: { + sessionToken: 'testToken' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'id_token', + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'response_type=id_token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=openid%20email' + }); + }); + + it('sets authorize url for access_token using sessionToken', function() { + oauthUtil.setupRedirect({ + getWithRedirectArgs: { + responseType: 'token', + sessionToken: 'testToken' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'response_type=token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=openid%20email' + }); + }); + + it('sets authorize url for access_token and id_token using idp', function() { + oauthUtil.setupRedirect({ + getWithRedirectArgs: { + responseType: ['token', 'id_token'], + idp: 'testIdp' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['token', 'id_token'], + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'response_type=token%20id_token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'idp=testIdp&' + + 'scope=openid%20email' + }); + }); + }); + + describe('token.parseFromUrl', function() { + it('parses id_token', function(done) { + return oauthUtil.setupParseUrl({ + hashMock: '#id_token=' + tokens.standardIdToken + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'id_token', + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedResp: { + idToken: tokens.standardIdToken, + claims: tokens.standardIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'email'] + } + }) + .fin(function() { + done(); + }); + }); + + it('parses access_token', function(done) { + return oauthUtil.setupParseUrl({ + time: 1449699929, + hashMock: '#access_token=' + tokens.standardAccessToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedResp: { + accessToken: tokens.standardAccessToken, + expiresAt: 1449703529, + scopes: ['openid', 'email'], + tokenType: 'Bearer' + } + }) + .fin(function() { + done(); + }); + }); + + it('parses access_token and id_token', function(done) { + return oauthUtil.setupParseUrl({ + time: 1449699929, + hashMock: '#access_token=' + tokens.standardAccessToken + + '&id_token=' + tokens.standardIdToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token'], + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';', + expectedResp: [{ + idToken: tokens.standardIdToken, + claims: tokens.standardIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'email'] + }, { + accessToken: tokens.standardAccessToken, + expiresAt: 1449703529, + scopes: ['openid', 'email'], + tokenType: 'Bearer' + }] + }) + .fin(function() { + done(); + }); + }); + + oauthUtil.itpErrorsCorrectly('throws an error if nothing to parse', + { + setupMethod: oauthUtil.setupParseUrl, + hashMock: '', + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token'], + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';' + }, + { + name: 'AuthSdkError', + message: 'Unable to parse a token from the url', + errorCode: 'INTERNAL', + errorSummary: 'Unable to parse a token from the url', + errorLink: 'INTERNAL', + errorId: 'INTERNAL', + errorCauses: [] + } + ); + + oauthUtil.itpErrorsCorrectly('throws an error if no cookie set', + { + setupMethod: oauthUtil.setupParseUrl, + hashMock: '#access_token=' + tokens.standardAccessToken + + '&id_token=' + tokens.standardIdToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: '' + }, + { + name: 'AuthSdkError', + message: 'Unable to parse a token from the url', + errorCode: 'INTERNAL', + errorSummary: 'Unable to parse a token from the url', + errorLink: 'INTERNAL', + errorId: 'INTERNAL', + errorCauses: [] + } + ); + + oauthUtil.itpErrorsCorrectly('throws an error if state doesn\'t match', + { + setupMethod: oauthUtil.setupParseUrl, + hashMock: '#access_token=' + tokens.standardAccessToken + + '&id_token=' + tokens.standardIdToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token'], + state: 'mismatchedState', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scope: ['openid', 'email'] + }) + ';' + }, + { + name: 'AuthSdkError', + message: 'OAuth flow response state doesn\'t match request state', + errorCode: 'INTERNAL', + errorSummary: 'OAuth flow response state doesn\'t match request state', + errorLink: 'INTERNAL', + errorId: 'INTERNAL', + errorCauses: [] + } + ); + + oauthUtil.itpErrorsCorrectly('throws an error if nonce doesn\'t match', + { + setupMethod: oauthUtil.setupParseUrl, + hashMock: '#access_token=' + tokens.standardAccessToken + + '&id_token=' + tokens.standardIdToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token'], + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'mismatchedNonce', + scope: ['openid', 'email'] + }) + ';' + }, + { + name: 'AuthSdkError', + message: 'OAuth flow response nonce doesn\'t match request nonce', + errorCode: 'INTERNAL', + errorSummary: 'OAuth flow response nonce doesn\'t match request nonce', + errorLink: 'INTERNAL', + errorId: 'INTERNAL', + errorCauses: [] + } + ); + }); }); diff --git a/test/util/oauthUtil.js b/test/util/oauthUtil.js index 3d017a32e..531f505b6 100644 --- a/test/util/oauthUtil.js +++ b/test/util/oauthUtil.js @@ -30,6 +30,34 @@ define(function(require) { scopes: ['openid', 'email'] }; + function getTime(time) { + if (time || time === 0) { + return time; + } else { + return tokens.standardIdTokenClaims.exp - 1; + } + } + + function validateResponse(res, expectedResp) { + function expectResponsesToEqual(actual, expected) { + expect(actual.idToken).toEqual(expected.idToken); + expect(actual.claims).toEqual(expected.claims); + expect(actual.accessToken).toEqual(expected.accessToken); + expect(actual.expiresAt).toEqual(expected.expiresAt); + expect(actual.tokenType).toEqual(expected.tokenType); + } + + if (Array.isArray(expectedResp)) { + expect(res.length).toEqual(expectedResp.length); + var rl = res.length; + while(rl--) { + expectResponsesToEqual(res[rl], expectedResp[rl]); + } + } else { + expectResponsesToEqual(res, expectedResp); + } + } + oauthUtil.setup = function(opts) { if (opts && @@ -63,17 +91,10 @@ define(function(require) { }); } - // Make sure our token isn't expired - var time; - if (opts.time || opts.time === 0) { - time = opts.time; - } else { - time = tokens.standardIdTokenClaims.exp - 1; - } - util.warpToUnixTime(time); + util.warpToUnixTime(getTime(opts.time)); if (opts.hrefMock) { - util.mockWindowLocationHref(authClient, opts.hrefMock); + util.mockGetWindowLocation(authClient, opts.hrefMock); } var promise; @@ -89,24 +110,7 @@ define(function(require) { return promise .then(function(res) { var expectedResp = opts.expectedResp || defaultResponse; - - function expectResponsesToEqual(actual, expected) { - expect(actual.idToken).toEqual(expected.idToken); - expect(actual.claims).toEqual(expected.claims); - expect(actual.accessToken).toEqual(expected.accessToken); - expect(actual.expiresAt).toEqual(expected.expiresAt); - expect(actual.tokenType).toEqual(expected.tokenType); - } - - if (Array.isArray(expectedResp)) { - expect(res.length).toEqual(expectedResp.length); - var rl = res.length; - while(rl--) { - expectResponsesToEqual(res[rl], expectedResp[rl]); - } - } else { - expectResponsesToEqual(res, expectedResp); - } + validateResponse(res, expectedResp); }) .fail(function(err) { if (opts.willFail) { @@ -207,6 +211,46 @@ define(function(require) { } }); }; + + oauthUtil.setupRedirect = function(opts) { + var client = new OktaAuth({ + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }); + + oauthUtil.mockStateAndNonce(); + var windowLocationMock = util.mockSetWindowLocation(client); + var setCookieMock = util.mockSetCookie(); + + client.token.getWithRedirect(opts.getWithRedirectArgs); + + expect(windowLocationMock).toHaveBeenCalledWith(opts.expectedRedirectUrl); + expect(setCookieMock).toHaveBeenCalledWith(opts.expectedCookie); + }; + + oauthUtil.setupParseUrl = function(opts) { + var client = new OktaAuth({ + url: 'https://lboyette.trexcloud.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://lboyette.trexcloud.com/redirect' + }); + + util.warpToUnixTime(getTime(opts.time)); + util.mockGetLocationHash(client, opts.hashMock); + util.mockGetCookie(opts.oauthCookie); + var setCookieMock = util.mockSetCookie(); + + return client.token.parseFromUrl() + .then(function(res) { + var expectedResp = opts.expectedResp; + validateResponse(res, expectedResp); + + // The cookie should be deleted + expect(setCookieMock).toHaveBeenCalledWith('okta-oauth-redirect-params=; ' + + 'expires=Thu, 01 Jan 1970 00:00:00 GMT;'); + }); + }; function expectErrorToEqual(actual, expected) { expect(actual.name).toEqual(expected.name); @@ -241,7 +285,9 @@ define(function(require) { it(title, function (done) { options.willFail = true; var setupMethod; - if (options.authorizeArgs && + if (options.setupMethod) { + setupMethod = options.setupMethod; + } else if (options.authorizeArgs && (options.authorizeArgs.responseMode === 'fragment' || options.authorizeArgs.idp)) { setupMethod = oauthUtil.setupPopup; } else { diff --git a/test/util/util.js b/test/util/util.js index e61a3252c..edc2de483 100644 --- a/test/util/util.js +++ b/test/util/util.js @@ -4,7 +4,8 @@ define(function(require) { var Q = require('q'), $ = require('jquery'), _ = require('lodash'), - OktaAuth = require('OktaAuth'); + OktaAuth = require('OktaAuth'), + cookies = require('../../lib/cookies'); function generateXHRPair(request, response, uri) { return Q.Promise(function(resolve) { @@ -314,9 +315,25 @@ define(function(require) { }); }; - util.mockWindowLocationHref = function (client, href) { + util.mockGetWindowLocation = function (client, href) { spyOn(client.idToken.authorize, '_getLocationHref').and.returnValue(href); }; + util.mockSetWindowLocation = function (client) { + return spyOn(client.token.getWithRedirect, '_setLocation'); + }; + + util.mockSetCookie = function () { + return spyOn(cookies.setCookie, '_setDocumentCookie'); + }; + + util.mockGetCookie = function (text) { + spyOn(cookies.getCookie, '_getDocumentCookie').and.returnValue(text || ''); + }; + + util.mockGetLocationHash = function (client, hash) { + spyOn(client.token.parseFromUrl, '_getLocationHash').and.returnValue(hash); + }; + return util; }); diff --git a/webpack.config.js b/webpack.config.js index 8c4a7cf10..0dd9be912 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -25,7 +25,7 @@ module.exports = _.extend(commonConfig, { compress: { warnings: false }, - sourceMap: false, + sourceMap: true, comments: function(node, comment) { // Remove other Okta copyrights var isLicense = /^!/.test(comment.value); @@ -36,5 +36,6 @@ module.exports = _.extend(commonConfig, { // Add a single Okta license after removing others new webpack.BannerPlugin(license) - ] + ], + devtool: 'source-map' }); From bf7f9b1236cf2934e55da1658b5ec542f764b125 Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Thu, 21 Jul 2016 09:53:06 -0700 Subject: [PATCH 3/6] Add null check when building token array --- lib/token.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/token.js b/lib/token.js index 48d613c33..9090e536b 100644 --- a/lib/token.js +++ b/lib/token.js @@ -309,7 +309,9 @@ function handleOAuthResponse(sdk, oauthParams, res) { // Create token array in the order of the responseType array for (var t = 0, tl = tokenTypes.length; t < tl; t++) { var tokenType = tokenTypes[t]; - tokens.push(tokenDict[tokenType]); + if (tokenDict[tokenType]) { + tokens.push(tokenDict[tokenType]); + } } return tokens; From 32a221678cd688414844e3babea81b2b4a06d574 Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Thu, 21 Jul 2016 14:52:03 -0700 Subject: [PATCH 4/6] Renamed getIdToken to getToken --- lib/clientBuilder.js | 2 +- lib/token.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/clientBuilder.js b/lib/clientBuilder.js index 917c73912..5279b657b 100644 --- a/lib/clientBuilder.js +++ b/lib/clientBuilder.js @@ -66,7 +66,7 @@ function OktaAuthBuilder(args) { }; sdk.idToken = { - authorize: util.bind(token.getIdToken, sdk, sdk), // deprecated for sessionToken and idp flows + authorize: util.bind(token.getToken, sdk, sdk), // deprecated for sessionToken and idp flows verify: util.bind(token.verifyIdToken, sdk, sdk), refresh: util.bind(token.refreshIdToken, sdk, sdk), decode: util.bind(token.decodeToken, sdk) // deprecated diff --git a/lib/token.js b/lib/token.js index 9090e536b..f638c5194 100644 --- a/lib/token.js +++ b/lib/token.js @@ -129,7 +129,7 @@ function refreshIdToken(sdk, opts) { opts = opts || {}; opts.display = null; opts.prompt = 'none'; - return getIdToken(sdk, opts); + return getToken(sdk, opts); } function loadFrame(src, iframeId) { @@ -382,7 +382,7 @@ function buildAuthorizeUrl(sdk, oauthParams) { * 1) Exchange a sessionToken for an idToken * * Required: - * clientId: passed via the OktaAuth constructor or into getIdToken + * clientId: passed via the OktaAuth constructor or into getToken * sessionToken: 'yourtoken' * * Optional: @@ -397,7 +397,7 @@ function buildAuthorizeUrl(sdk, oauthParams) { * 2) Get an idToken from an idp * * Required: - * clientId: passed via the OktaAuth constructor or into getIdToken + * clientId: passed via the OktaAuth constructor or into getToken * * Optional: * redirectUri: defaults to window.location.href @@ -424,7 +424,7 @@ function buildAuthorizeUrl(sdk, oauthParams) { * @param {String} [options.popupTitle] Title dispayed in the popup. * Defaults to 'External Identity Provider User Authentication' */ -function getIdToken(sdk, oauthOptions, options) { +function getToken(sdk, oauthOptions, options) { if (!oauthOptions) { oauthOptions = {}; } @@ -558,7 +558,7 @@ function getWithoutPrompt(sdk, oauthOptions, options) { responseMode: 'okta_post_message', display: null }); - return getIdToken(sdk, oauthParams, options); + return getToken(sdk, oauthParams, options); } function getWithPopup(sdk, oauthOptions, options) { @@ -566,7 +566,7 @@ function getWithPopup(sdk, oauthOptions, options) { util.extend(oauthParams, { display: 'popup' }); - return getIdToken(sdk, oauthParams, options); + return getToken(sdk, oauthParams, options); } function getWithRedirect(sdk, oauthOptions, options) { @@ -613,7 +613,7 @@ function parseFromUrl(sdk, url) { } module.exports = { - getIdToken: getIdToken, + getToken: getToken, getWithoutPrompt: getWithoutPrompt, getWithPopup: getWithPopup, getWithRedirect: getWithRedirect, From 30427f9ccb1336f2b611067f9ad81ebbd86343eb Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Thu, 21 Jul 2016 15:23:48 -0700 Subject: [PATCH 5/6] Anonymized test data --- test/spec/general.js | 66 ++++++------------------------- test/spec/oauth.js | 82 +++++++++++++++++++-------------------- test/spec/token.js | 88 +++++++++++++++++++++--------------------- test/util/oauthUtil.js | 12 +++--- test/util/tokens.js | 84 ++++++++++++++++++++-------------------- 5 files changed, 145 insertions(+), 187 deletions(-) diff --git a/test/spec/general.js b/test/spec/general.js index f5e48eab3..5c2ad8f5c 100644 --- a/test/spec/general.js +++ b/test/spec/general.js @@ -46,50 +46,6 @@ define(function(require) { // Run if browser supports crypto var describeType = OktaAuth.prototype.features.isTokenVerifySupported() ? describe : xdescribe; describeType('idToken.verify', function () { - - /* - { - "sub": "00u1pcla5qYIREDLWCQV", - "name": "Len Boyette", - "given_name": "Len", - "family_name": "Boyette", - "updated_at": 1446153401, - "email": "lboyette@okta.com", - "email_verified": true, - "ver": 1, - "iss": "https://lboyette.trexcloud.com", - "login": "admin@okta.com", - "aud": "NPSfOkH5eZrTy8PMDlvx", - "iat": 1449696330, - "exp": 1449699930, - "amr": [ - "kba", - "mfa", - "pwd" - ], - "jti": "TRZT7RCiSymTs5W7Ryh3", - "auth_time": 1449696330 - } - */ - var standardIdToken = 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIwMHUxcGNsYTVxWUlSRU' + - 'RMV0NRViIsIm5hbWUiOiJMZW4gQm95ZXR0ZSIsImdpdmVuX25hb' + - 'WUiOiJMZW4iLCJmYW1pbHlfbmFtZSI6IkJveWV0dGUiLCJ1cGRh' + - 'dGVkX2F0IjoxNDQ2MTUzNDAxLCJlbWFpbCI6Imxib3lldHRlQG9' + - 'rdGEuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInZlciI6MS' + - 'wiaXNzIjoiaHR0cHM6Ly9sYm95ZXR0ZS50cmV4Y2xvdWQuY29tI' + - 'iwibG9naW4iOiJhZG1pbkBva3RhLmNvbSIsImF1ZCI6Ik5QU2ZP' + - 'a0g1ZVpyVHk4UE1EbHZ4IiwiaWF0IjoxNDQ5Njk2MzMwLCJleHA' + - 'iOjE0NDk2OTk5MzAsImFtciI6WyJrYmEiLCJtZmEiLCJwd2QiXS' + - 'wianRpIjoiVFJaVDdSQ2lTeW1UczVXN1J5aDMiLCJhdXRoX3Rpb' + - 'WUiOjE0NDk2OTYzMzB9.YWCNE3ZvT-8ceKnAbTkmSxYE-jIPpfh' + - '2s8f_hTagUUxrfdKgyWzBb9iN3GOPaQ2K6jqOFx90RI2GBzAWec' + - 'pel3sAxG-wvLqiy0d8g0CUb7XTHdhXOLRrXvlpbULxdNnMbBcc6' + - 'uOLDalBjrumOiDMLzti-Bx6uQQ0EjUwuC-Dhv7I3wMsVxyEKejv' + - 'jMLbfWJ6iu4-UUx1r8_ZZUjDDXSB3OFXJQ3nPwRVFXZuRNhGScL' + - 'nftXz7mypRGxrapIQusym1K8hk9uy8_KYL2H2QNbyIqK9Vh9JhY' + - '1rtkQNpv3ZerCUXEVGRiEXDqR_OHu4vUi1-FkONZZe2ov8dQ1mX' + - 'iHHdw'; - function setupVerifyIdTokenTest(opts) { util.itMakesCorrectRequestResponse({ title: opts.title, @@ -131,7 +87,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies a valid idToken', - idToken: standardIdToken, + idToken: tokens.standardIdToken, expectations: function (test, res) { expect(res).toEqual(true); } @@ -164,7 +120,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'rejects an invalid idToken due to expiration', - idToken: standardIdToken, + idToken: tokens.standardIdToken, execute: function(test, opts) { util.warpToDistantPast(); return test.oa.idToken.verify(opts.idToken, opts.verifyOpts) @@ -181,7 +137,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies an idToken that would be invalid, except ' + 'we\'re using the expirationTime option', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { expirationTime: 9999999999 }, @@ -200,7 +156,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies a valid idToken using single audience option', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { audience: 'NPSfOkH5eZrTy8PMDlvx' }, @@ -211,7 +167,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'rejects an invalid idToken using single audience option', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { audience: 'invalid' }, @@ -222,7 +178,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies a valid idToken using multiple audience option (all valid)', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { audience: ['NPSfOkH5eZrTy8PMDlvx', 'NPSfOkH5eZrTy8PMDlvx'] }, @@ -233,7 +189,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies a valid idToken using multiple audience option (valid and invalid)', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { audience: ['NPSfOkH5eZrTy8PMDlvx', 'invalid2'] }, @@ -244,7 +200,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'rejects an invalid idToken using multiple audience option (all invalid)', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { audience: ['invalid1', 'invalid2'] }, @@ -255,9 +211,9 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'verifies a valid idToken using issuer option', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { - issuer: 'https://lboyette.trexcloud.com' + issuer: 'https://auth-js-test.okta.com' }, expectations: function (test, res) { expect(res).toEqual(true); @@ -266,7 +222,7 @@ define(function(require) { setupVerifyIdTokenTest({ title: 'rejects an invalid idToken using issuer option', - idToken: standardIdToken, + idToken: tokens.standardIdToken, verifyOpts: { issuer: 'invalid' }, diff --git a/test/spec/oauth.js b/test/spec/oauth.js index f523ac353..0c2212f4e 100644 --- a/test/spec/oauth.js +++ b/test/spec/oauth.js @@ -9,16 +9,16 @@ define(function(require) { it('returns new id_token using old id_token', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, refreshArgs: {}, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -40,14 +40,14 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -67,14 +67,14 @@ define(function(require) { return oauthUtil.setupPopup({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', idp: 'testIdp' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -94,7 +94,7 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' } }) @@ -105,19 +105,19 @@ define(function(require) { it('returns id_token using popup fragment', function (done) { return oauthUtil.setupPopup({ - hrefMock: 'https://lboyette.trexcloud.com', + hrefMock: 'https://auth-js-test.okta.com', changeToHash: '#id_token=' + tokens.standardIdToken + '&state=' + oauthUtil.mockedState, authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', idp: 'testIdp', responseMode: 'fragment' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'fragment', 'display': 'popup', @@ -136,9 +136,9 @@ define(function(require) { it('doesn\'t throw an error when redirectUri and clientId are passed via OktaAuth', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, authorizeArgs: { sessionToken: 'testToken' @@ -154,14 +154,14 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -178,15 +178,15 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', scope: ['openid', 'testscope'], sessionToken: 'testToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -213,7 +213,7 @@ define(function(require) { sessionToken: 'testToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', 'redirect_uri': window.location.href, @@ -236,7 +236,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', scope: ['notopenid'], sessionToken: 'testToken' } @@ -254,7 +254,7 @@ define(function(require) { oauthUtil.itErrorsCorrectly('throws an error when clientId isn\'t specified', { authorizeArgs: { - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' } }, @@ -272,7 +272,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' }, postMessageResp: { @@ -291,11 +291,11 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', idp: 'testIdp', responseMode: 'fragment' }, - hrefMock: 'https://lboyette.trexcloud.com', + hrefMock: 'https://auth-js-test.okta.com', changeToHash: '#error=invalid_scope&error_description=' + 'The+requested+scope+is+invalid%2C+unknown%2C+or+malformed.' }, @@ -310,11 +310,11 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', idp: 'testIdp', responseMode: 'fragment' }, - hrefMock: 'https://lboyette.trexcloud.com', + hrefMock: 'https://auth-js-test.okta.com', closePopup: true }, { @@ -331,7 +331,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', idp: 'testIdp' }, closePopup: true @@ -350,7 +350,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' }, postMessageResp: { @@ -372,7 +372,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken', nonce: 'mismatchedNonce' } @@ -392,7 +392,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://different.issuer.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, authorizeArgs: { sessionToken: 'testToken' @@ -400,9 +400,9 @@ define(function(require) { }, { name: 'AuthSdkError', - message: 'The issuer [https://lboyette.trexcloud.com] does not match [https://different.issuer.com]', + message: 'The issuer [https://auth-js-test.okta.com] does not match [https://different.issuer.com]', errorCode: 'INTERNAL', - errorSummary: 'The issuer [https://lboyette.trexcloud.com] does not match [https://different.issuer.com]', + errorSummary: 'The issuer [https://auth-js-test.okta.com] does not match [https://different.issuer.com]', errorLink: 'INTERNAL', errorId: 'INTERNAL', errorCauses: [] @@ -412,7 +412,7 @@ define(function(require) { { authorizeArgs: { clientId: 'differentAudience', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' } }, @@ -430,7 +430,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' }, postMessageResp: { @@ -453,7 +453,7 @@ define(function(require) { time: 9999999999, authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' } }, @@ -472,7 +472,7 @@ define(function(require) { time: 0, authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect', + redirectUri: 'https://auth-js-test.okta.com/redirect', sessionToken: 'testToken' } }, diff --git a/test/spec/token.js b/test/spec/token.js index f28cc4d69..de7995190 100644 --- a/test/spec/token.js +++ b/test/spec/token.js @@ -32,18 +32,18 @@ define(function(require) { it('returns id_token using sessionToken', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -62,19 +62,19 @@ define(function(require) { it('returns access_token using sessionToken', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { responseType: 'token', sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -106,19 +106,19 @@ define(function(require) { it('returns id_token and access_token (in that order) using an array of responseTypes', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { responseType: ['id_token', 'token'], sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -156,19 +156,19 @@ define(function(require) { it('returns access_token and id_token (in that order) using an array of responseTypes', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { responseType: ['token', 'id_token'], sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'token id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -206,19 +206,19 @@ define(function(require) { it('returns a single token using an array with a single responseType', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { responseType: ['id_token'], sessionToken: 'testSessionToken' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -243,9 +243,9 @@ define(function(require) { oauthUtil.itErrorsCorrectly('throws an error if multiple responseTypes are sent as a string', { oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithoutPromptArgs: { responseType: 'id_token token', @@ -268,18 +268,18 @@ define(function(require) { it('returns id_token using idp', function (done) { return oauthUtil.setupPopup({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithPopupArgs: { idp: 'testIdp' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -298,19 +298,19 @@ define(function(require) { it('returns access_token using sessionToken', function (done) { return oauthUtil.setupPopup({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithPopupArgs: { responseType: 'token', idp: 'testIdp' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -342,19 +342,19 @@ define(function(require) { it('returns access_token and id_token (in that order) using idp', function (done) { return oauthUtil.setupPopup({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithPopupArgs: { responseType: ['token', 'id_token'], idp: 'testIdp' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'token id_token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -392,19 +392,19 @@ define(function(require) { it('returns id_token and access_token (in that order) using idp', function (done) { return oauthUtil.setupPopup({ oktaAuthArgs: { - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }, getWithPopupArgs: { responseType: ['id_token', 'token'], idp: 'testIdp' }, postMessageSrc: { - baseUri: 'https://lboyette.trexcloud.com/oauth2/v1/authorize', + baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://lboyette.trexcloud.com/redirect', + 'redirect_uri': 'https://auth-js-test.okta.com/redirect', 'response_type': 'id_token token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -452,9 +452,9 @@ define(function(require) { nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', scope: ['openid', 'email'] }) + ';', - expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + 'response_type=id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -476,9 +476,9 @@ define(function(require) { nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', scope: ['openid', 'email'] }) + ';', - expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + 'response_type=token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -500,9 +500,9 @@ define(function(require) { nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', scope: ['openid', 'email'] }) + ';', - expectedRedirectUrl: 'https://lboyette.trexcloud.com/oauth2/v1/authorize?' + + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Flboyette.trexcloud.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + 'response_type=token%20id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + diff --git a/test/util/oauthUtil.js b/test/util/oauthUtil.js index 531f505b6..cbe8976b3 100644 --- a/test/util/oauthUtil.js +++ b/test/util/oauthUtil.js @@ -73,7 +73,7 @@ define(function(require) { fn({ data: opts.postMessageResp || defaultPostMessage, origin: opts.oktaAuthArgs && opts.oktaAuthArgs.url || - 'https://lboyette.trexcloud.com' + 'https://auth-js-test.okta.com' }); }); } @@ -87,7 +87,7 @@ define(function(require) { authClient = new OktaAuth(opts.oktaAuthArgs); } else { authClient = new OktaAuth({ - url: 'https://lboyette.trexcloud.com' + url: 'https://auth-js-test.okta.com' }); } @@ -214,9 +214,9 @@ define(function(require) { oauthUtil.setupRedirect = function(opts) { var client = new OktaAuth({ - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }); oauthUtil.mockStateAndNonce(); @@ -231,9 +231,9 @@ define(function(require) { oauthUtil.setupParseUrl = function(opts) { var client = new OktaAuth({ - url: 'https://lboyette.trexcloud.com', + url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://lboyette.trexcloud.com/redirect' + redirectUri: 'https://auth-js-test.okta.com/redirect' }); util.warpToUnixTime(getTime(opts.time)); diff --git a/test/util/tokens.js b/test/util/tokens.js index 0abcc357e..62b0d590e 100644 --- a/test/util/tokens.js +++ b/test/util/tokens.js @@ -24,33 +24,35 @@ define(function() { signature: 'TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ' }; - tokens.standardIdToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMH' + - 'UxcGNsYTVxWUlSRURMV0NRViIsIm5hbWUiOiJMZW4gQm95ZXR0Z' + - 'SIsImdpdmVuX25hbWUiOiJMZW4iLCJmYW1pbHlfbmFtZSI6IkJv' + - 'eWV0dGUiLCJ1cGRhdGVkX2F0IjoxNDQ2MTUzNDAxLCJlbWFpbCI' + - '6Imxib3lldHRlQG9rdGEuY29tIiwiZW1haWxfdmVyaWZpZWQiOn' + - 'RydWUsInZlciI6MSwiaXNzIjoiaHR0cHM6Ly9sYm95ZXR0ZS50c' + - 'mV4Y2xvdWQuY29tIiwibG9naW4iOiJhZG1pbkBva3RhLmNvbSIs' + - 'Im5vbmNlIjoiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' + - 'hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSIsIm' + - 'F1ZCI6Ik5QU2ZPa0g1ZVpyVHk4UE1EbHZ4IiwiaWF0IjoxNDQ5N' + - 'jk2MzMwLCJleHAiOjE0NDk2OTk5MzAsImFtciI6WyJrYmEiLCJt' + - 'ZmEiLCJwd2QiXSwianRpIjoiVFJaVDdSQ2lTeW1UczVXN1J5aDM' + - 'iLCJhdXRoX3RpbWUiOjE0NDk2OTYzMzB9.w_JtTGqho5rIVvIkh' + - 'OyXun2wzOeWOw-1eNBqwy15XvEj_lrz2rVJW9-kxKZgLyQRMRcb' + - '7br_I284szVX848gQQ-E5X73j9uuBmpYRtrAlb35E4TUXGKxXs9' + - 'kgJku2QOQeX-AHQj0MSWzDMSjK2JqJxnwifi6pgFA8RMiNfmLloc'; + tokens.standardIdToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOi' + + 'IwMHUxcGNsYTVxWUlSRURMV0NRViIsIm5hbWUiOiJTYW1sI' + + 'EphY2tzb24iLCJnaXZlbl9uYW1lIjoiU2FtbCIsImZhbWls' + + 'eV9uYW1lIjoiSmFja3NvbiIsInVwZGF0ZWRfYXQiOjE0NDY' + + 'xNTM0MDEsImVtYWlsIjoic2FtbGphY2tzb25Ab2t0YS5jb2' + + '0iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwidmVyIjoxLCJpc' + + '3MiOiJodHRwczovL2F1dGgtanMtdGVzdC5va3RhLmNvbSIs' + + 'ImxvZ2luIjoiYWRtaW5Ab2t0YS5jb20iLCJub25jZSI6ImF' + + 'hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW' + + 'FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEiLCJhdWQiO' + + 'iJOUFNmT2tINWVaclR5OFBNRGx2eCIsImlhdCI6MTQ0OTY5' + + 'NjMzMCwiZXhwIjoxNDQ5Njk5OTMwLCJhbXIiOlsia2JhIiw' + + 'ibWZhIiwicHdkIl0sImp0aSI6IlRSWlQ3UkNpU3ltVHM1Vz' + + 'dSeWgzIiwiYXV0aF90aW1lIjoxNDQ5Njk2MzMwfQ.PDuo7r' + + 'brqHIqXRIuF5eP-hovEs9ZBVuwXf7_qKUKld-2c7YVguuSO' + + 'uhXvC4ngcZhxjw9Y0nefogFdI47Qqhdw-dggtgsGzHxiPvr' + + 't0e5Vh4m5L4lVedSpsCdlMIPOv78-d_N6sAAXPiQ3MYhu5x' + + 'zhMm8Y_PK8JZnFtfN47vrNlk'; tokens.standardIdTokenClaims = { 'sub': '00u1pcla5qYIREDLWCQV', - 'name': 'Len Boyette', - 'given_name': 'Len', - 'family_name': 'Boyette', + 'name': 'Saml Jackson', + 'given_name': 'Saml', + 'family_name': 'Jackson', 'updated_at': 1446153401, - 'email': 'lboyette@okta.com', + 'email': 'samljackson@okta.com', 'email_verified': true, 'ver': 1, - 'iss': 'https://lboyette.trexcloud.com', + 'iss': 'https://auth-js-test.okta.com', 'login': 'admin@okta.com', 'nonce': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aud': 'NPSfOkH5eZrTy8PMDlvx', @@ -83,14 +85,14 @@ define(function() { /* { 'sub': '00u1pcla5qYIREDLWCQV', - 'name': 'Len Boyette', - 'given_name': 'Len', - 'family_name': 'Boyette', + 'name': 'Saml Jackson', + 'given_name': 'Saml', + 'family_name': 'Jackson', 'updated_at': 1446153401, - 'email': 'lboyette@okta.com', + 'email': 'samljackson@okta.com', 'email_verified': true, 'ver': 1, - 'iss': 'https://lboyette.trexcloud.com', + 'iss': 'https://auth-js-test.okta.com', 'login': 'admin@okta.com', 'nonce': standardNonce, 'aud': 'NPSfOkH5eZrTy8PMDlvx', @@ -106,22 +108,22 @@ define(function() { } */ tokens.expiredBeforeIssuedToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzd' + - 'WIiOiIwMHUxcGNsYTVxWUlSRURMV0NRViIsIm5hbWUiOiJMZW4g' + - 'Qm95ZXR0ZSIsImdpdmVuX25hbWUiOiJMZW4iLCJmYW1pbHlfbmF' + - 'tZSI6IkJveWV0dGUiLCJ1cGRhdGVkX2F0IjoxNDQ2MTUzNDAxLC' + - 'JlbWFpbCI6Imxib3lldHRlQG9rdGEuY29tIiwiZW1haWxfdmVya' + - 'WZpZWQiOnRydWUsInZlciI6MSwiaXNzIjoiaHR0cHM6Ly9sYm95' + - 'ZXR0ZS50cmV4Y2xvdWQuY29tIiwibG9naW4iOiJhZG1pbkBva3R' + - 'hLmNvbSIsIm5vbmNlIjoiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW' + + 'WIiOiIwMHUxcGNsYTVxWUlSRURMV0NRViIsIm5hbWUiOiJTYW1s' + + 'IEphY2tzb24iLCJnaXZlbl9uYW1lIjoiU2FtbCIsImZhbWlseV9' + + 'uYW1lIjoiSmFja3NvbiIsInVwZGF0ZWRfYXQiOjE0NDYxNTM0MD' + + 'EsImVtYWlsIjoic2FtbGphY2tzb25Ab2t0YS5jb20iLCJlbWFpb' + + 'F92ZXJpZmllZCI6dHJ1ZSwidmVyIjoxLCJpc3MiOiJodHRwczov' + + 'L2F1dGgtanMtdGVzdC5va3RhLmNvbSIsImxvZ2luIjoiYWRtaW5' + + 'Ab2t0YS5jb20iLCJub25jZSI6ImFhYWFhYWFhYWFhYWFhYWFhYW' + 'FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY' + - 'WFhYSIsImF1ZCI6Ik5QU2ZPa0g1ZVpyVHk4UE1EbHZ4IiwiaWF0' + - 'IjoyNDQ5Njk2MzMwLCJleHAiOjE0NDk2OTk5MzAsImFtciI6WyJ' + - 'rYmEiLCJtZmEiLCJwd2QiXSwianRpIjoiVFJaVDdSQ2lTeW1Ucz' + - 'VXN1J5aDMiLCJhdXRoX3RpbWUiOjE0NDk2OTYzMzB9.u7ClfS2w' + - '7O_kei5gtBfY_M01WCxLZ30A8KUhkHd2bDzkHFKmc3c4OT86PKS' + - '3I-JKeRIflXTwcIe8IUqtFGv8pM9iAT_mi2nxieMqOdrFw4S8UM' + - 'KKgPcYLLfFCvcDs_1d0XqHHohmHKdM6YIsgP8abPk2ugwSX49Dz' + - 'LyJrVkCZIM'; + 'WFhYWFhYWEiLCJhdWQiOiJOUFNmT2tINWVaclR5OFBNRGx2eCIs' + + 'ImlhdCI6MjQ0OTY5NjMzMCwiZXhwIjoxNDQ5Njk5OTMwLCJhbXI' + + 'iOlsia2JhIiwibWZhIiwicHdkIl0sImp0aSI6IlRSWlQ3UkNpU3' + + 'ltVHM1VzdSeWgzIiwiYXV0aF90aW1lIjoxNDQ5Njk2MzMwfQ.o1' + + '5xo_fc3Xc-KLxjyD5HxgQcmuVOxRAlcATa8HDzZv04g3CmrgdFN' + + '7W2smjXDgBXFPBFLcgpiDqDioAfnMC6KI0G9a2tJMTjwBLwtYMh' + + 'KZsa4srVE0uXiqdiyiljZ692gdXbwBXgWNIA2PWMrIagxWiqYCn' + + 'fAJcS7TCE611eg-c'; return tokens; }); From c8c1318ec1ef7da10140d01b08d302109bf5e65a Mon Sep 17 00:00:00 2001 From: lboyette-okta Date: Thu, 21 Jul 2016 16:07:46 -0700 Subject: [PATCH 6/6] Remove requirement for openid --- lib/token.js | 7 ++++--- test/spec/oauth.js | 4 ++-- test/spec/token.js | 7 ++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/token.js b/lib/token.js index f638c5194..905b0f968 100644 --- a/lib/token.js +++ b/lib/token.js @@ -360,10 +360,11 @@ function convertOAuthParamsToQueryParams(oauthParams) { oauthQueryParams['response_type'] = oauthQueryParams['response_type'].join(' '); } - if (oauthParams.scope.indexOf('openid') !== -1) { - oauthQueryParams.scope = oauthParams.scope.join(' '); + if (oauthParams.responseType.indexOf('id_token') !== -1 && + oauthParams.scope.indexOf('openid') === -1) { + throw new AuthSdkError('openid scope must be specified in the scope argument when requesting an id_token'); } else { - throw new AuthSdkError('openid scope must be specified in the scope argument'); + oauthQueryParams.scope = oauthParams.scope.join(' '); } return oauthQueryParams; diff --git a/test/spec/oauth.js b/test/spec/oauth.js index 0c2212f4e..212f1bc31 100644 --- a/test/spec/oauth.js +++ b/test/spec/oauth.js @@ -243,9 +243,9 @@ define(function(require) { }, { name: 'AuthSdkError', - message: 'openid scope must be specified in the scope argument', + message: 'openid scope must be specified in the scope argument when requesting an id_token', errorCode: 'INTERNAL', - errorSummary: 'openid scope must be specified in the scope argument', + errorSummary: 'openid scope must be specified in the scope argument when requesting an id_token', errorLink: 'INTERNAL', errorId: 'INTERNAL', errorCauses: [] diff --git a/test/spec/token.js b/test/spec/token.js index de7995190..5d432860b 100644 --- a/test/spec/token.js +++ b/test/spec/token.js @@ -464,17 +464,18 @@ define(function(require) { }); }); - it('sets authorize url for access_token using sessionToken', function() { + it('sets authorize url for access_token and don\'t throw an error if openid isn\'t included in scope', function() { oauthUtil.setupRedirect({ getWithRedirectArgs: { responseType: 'token', + scope: ['email'], sessionToken: 'testToken' }, expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ responseType: 'token', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scope: ['openid', 'email'] + scope: ['email'] }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + @@ -484,7 +485,7 @@ define(function(require) { 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + 'sessionToken=testToken&' + - 'scope=openid%20email' + 'scope=email' }); });