From e39e6cd7f14230a5d6fef0af6f2a9f9b235f01a9 Mon Sep 17 00:00:00 2001 From: Len Boyette Date: Mon, 17 Oct 2016 15:36:04 -0700 Subject: [PATCH] Added issuer, authorizeUrl, and userinfoUrl (#47) Resolves: OKTA-103713 --- lib/clientBuilder.js | 10 +- lib/oauthUtil.js | 189 +++++++ lib/token.js | 169 ++---- lib/util.js | 13 +- test/spec/oauth.js | 52 +- test/spec/oauthUtil.js | 190 +++++++ test/spec/token.js | 1049 ++++++++++++++++++++++++++++++++----- test/spec/tokenManager.js | 26 +- test/util/oauthUtil.js | 30 +- test/util/tokens.js | 80 ++- test/util/util.js | 2 +- 11 files changed, 1479 insertions(+), 331 deletions(-) create mode 100644 lib/oauthUtil.js create mode 100644 test/spec/oauthUtil.js diff --git a/lib/clientBuilder.js b/lib/clientBuilder.js index a57136147..7a5b7abfb 100644 --- a/lib/clientBuilder.js +++ b/lib/clientBuilder.js @@ -35,8 +35,11 @@ function OktaAuthBuilder(args) { } this.options = { - url: args.url, + url: util.removeTrailingSlash(args.url), clientId: args.clientId, + issuer: util.removeTrailingSlash(args.issuer), + authorizeUrl: util.removeTrailingSlash(args.authorizeUrl), + userinfoUrl: util.removeTrailingSlash(args.userinfoUrl), redirectUri: args.redirectUri, ajaxRequest: args.ajaxRequest, transformErrorXHR: args.transformErrorXHR, @@ -56,11 +59,6 @@ function OktaAuthBuilder(args) { this.options.maxClockSkew = args.maxClockSkew; } - // Remove trailing forward slash from url - if (this.options.url.slice(-1) === '/') { - this.options.url = this.options.url.slice(0, -1); - } - sdk.session = { close: util.bind(session.closeSession, null, sdk), exists: util.bind(session.sessionExists, null, sdk), diff --git a/lib/oauthUtil.js b/lib/oauthUtil.js new file mode 100644 index 000000000..fc895d295 --- /dev/null +++ b/lib/oauthUtil.js @@ -0,0 +1,189 @@ +/* eslint-disable complexity, max-statements */ +var http = require('./http'); +var util = require('./util'); +var AuthSdkError = require('./errors/AuthSdkError'); + +function isToken(obj) { + if (obj && + (obj.accessToken || obj.idToken) && + Array.isArray(obj.scopes)) { + return true; + } + return false; +} + +function addListener(eventTarget, name, fn) { + if (eventTarget.addEventListener) { + eventTarget.addEventListener(name, fn); + } else { + eventTarget.attachEvent('on' + name, fn); + } +} + +function removeListener(eventTarget, name, fn) { + if (eventTarget.removeEventListener) { + eventTarget.removeEventListener(name, fn); + } else { + eventTarget.detachEvent('on' + name, fn); + } +} + +function loadFrame(src) { + var iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.src = src; + + return document.body.appendChild(iframe); +} + +function loadPopup(src, options) { + var title = options.popupTitle || 'External Identity Provider User Authentication'; + var appearance = 'toolbar=no, scrollbars=yes, resizable=yes, ' + + 'top=100, left=500, width=600, height=600'; + return window.open(src, title, appearance); +} + +function getWellKnown(sdk) { + // TODO: Use the issuer when known (usually from the id_token) + return http.get(sdk, sdk.options.url + '/.well-known/openid-configuration'); +} + +function validateClaims(sdk, claims, aud, iss) { + if (!claims || !iss || !aud) { + throw new AuthSdkError('The jwt, iss, and aud arguments are all required'); + } + + var now = Math.floor(new Date().getTime()/1000); + + if (claims.iss !== iss) { + throw new AuthSdkError('The issuer [' + claims.iss + '] ' + + 'does not match [' + iss + ']'); + } + + if (claims.aud !== aud) { + throw new AuthSdkError('The audience [' + claims.aud + '] ' + + 'does not match [' + aud + ']'); + } + + if (claims.iat > claims.exp) { + throw new AuthSdkError('The JWT expired before it was issued'); + } + + if ((now - sdk.options.maxClockSkew) > claims.exp) { + throw new AuthSdkError('The JWT expired and is no longer valid'); + } + + if (claims.iat > (now + sdk.options.maxClockSkew)) { + throw new AuthSdkError('The JWT was issued in the future'); + } +} + +function getOAuthUrls(sdk, oauthParams, options) { + options = options || {}; + + // Get user-supplied arguments + var authorizeUrl = util.removeTrailingSlash(options.authorizeUrl) || sdk.options.authorizeUrl; + var issuer = util.removeTrailingSlash(options.issuer) || sdk.options.issuer; + var userinfoUrl = util.removeTrailingSlash(options.userinfoUrl) || sdk.options.userinfoUrl; + + // If an issuer exists but it's not a url, assume it's an authServerId + if (issuer && !(/^https?:/.test(issuer))) { + // Make it a url + issuer = sdk.options.url + '/oauth2/' + issuer; + } + + // If an authorizeUrl is supplied without an issuer, and an id_token is requested + if (!issuer && authorizeUrl && + oauthParams.responseType.indexOf('id_token') !== -1) { + // The issuer is ambiguous, so we won't be able to validate the id_token jwt + throw new AuthSdkError('Cannot request idToken with an authorizeUrl without an issuer'); + } + + // If a token is requested without an issuer + if (!issuer && oauthParams.responseType.indexOf('token') !== -1) { + // If an authorizeUrl is supplied without a userinfoUrl + if (authorizeUrl && !userinfoUrl) { + // The userinfoUrl is ambiguous, so we won't be able to call getUserInfo + throw new AuthSdkError('Cannot request accessToken with an authorizeUrl without an issuer or userinfoUrl'); + } + + // If a userinfoUrl is supplied without a authorizeUrl + if (userinfoUrl && !authorizeUrl) { + // The authorizeUrl is ambiguous, so we won't be able to call the authorize endpoint + throw new AuthSdkError('Cannot request token with an userinfoUrl without an issuer or authorizeUrl'); + } + } + + var sharedResourceServerRegex = new RegExp('^https?://.*?/oauth2/.+'); + + // Default the issuer to our baseUrl + issuer = issuer || sdk.options.url; + + // A shared resource server issuer looks like: + // https://example.okta.com/oauth2/aus8aus76q8iphupD0h7 + if (sharedResourceServerRegex.test(issuer)) { + // A shared resource server authorizeUrl looks like: + // https://example.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize + authorizeUrl = authorizeUrl || issuer + '/v1/authorize'; + // Shared resource server userinfoUrls look like: + // https://example.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo + userinfoUrl = userinfoUrl || issuer + '/v1/userinfo'; + + // Normally looks like: + // https://example.okta.com + } else { + // Normal authorizeUrls look like: + // https://example.okta.com/oauth2/v1/authorize + authorizeUrl = authorizeUrl || issuer + '/oauth2/v1/authorize'; + // Normal userinfoUrls look like: + // https://example.okta.com/oauth2/v1/userinfo + userinfoUrl = userinfoUrl || issuer + '/oauth2/v1/userinfo'; + } + + return { + issuer: issuer, + authorizeUrl: authorizeUrl, + userinfoUrl: userinfoUrl + }; +} + +function hashToObject(hash) { + // Predefine regexs for parsing hash + var plus2space = /\+/g; + var paramSplit = /([^&=]+)=?([^&]*)/g; + + // Remove the leading hash + var fragment = hash.substring(1); + + 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; } + + var key = param[1]; + var value = param[2]; + + // id_token should remain base64url encoded + if (key === 'id_token' || key === 'access_token' || key === 'code') { + obj[key] = value; + } else { + obj[key] = decodeURIComponent(value.replace(plus2space, ' ')); + } + } + return obj; +} + +module.exports = { + getWellKnown: getWellKnown, + validateClaims: validateClaims, + getOAuthUrls: getOAuthUrls, + loadFrame: loadFrame, + loadPopup: loadPopup, + hashToObject: hashToObject, + isToken: isToken, + addListener: addListener, + removeListener: removeListener +}; diff --git a/lib/token.js b/lib/token.js index 313850122..02e09139d 100644 --- a/lib/token.js +++ b/lib/token.js @@ -1,6 +1,7 @@ /* eslint-disable complexity, max-statements */ var http = require('./http'); var util = require('./util'); +var oauthUtil = require('./oauthUtil'); var Q = require('q'); var sdkCrypto = require('./crypto'); var AuthSdkError = require('./errors/AuthSdkError'); @@ -8,42 +9,6 @@ var OAuthError = require('./errors/OAuthError'); var config = require('./config'); var cookies = require('./cookies'); -function getWellKnown(sdk) { - return http.get(sdk, sdk.options.url + '/.well-known/openid-configuration'); -} - -function validateClaims(sdk, claims, aud) { - var iss = sdk.options.url; - - if (!claims || !iss || !aud) { - throw new AuthSdkError('The jwt, iss, and aud arguments are all required'); - } - - var now = Math.floor(new Date().getTime()/1000); - - if (claims.iss !== iss) { - throw new AuthSdkError('The issuer [' + claims.iss + '] ' + - 'does not match [' + iss + ']'); - } - - if (claims.aud !== aud) { - throw new AuthSdkError('The audience [' + claims.aud + '] ' + - 'does not match [' + aud + ']'); - } - - if (claims.iat > claims.exp) { - throw new AuthSdkError('The JWT expired before it was issued'); - } - - if ((now - sdk.options.maxClockSkew) > claims.exp) { - throw new AuthSdkError('The JWT expired and is no longer valid'); - } - - if (claims.iat > (now + sdk.options.maxClockSkew)) { - throw new AuthSdkError('The JWT was issued in the future'); - } -} - function decodeToken(token) { var jwt = token.split('.'); var decodedToken; @@ -96,7 +61,7 @@ function verifyIdToken(sdk, idToken, options) { } } - return getWellKnown(sdk) + return oauthUtil.getWellKnown(sdk) .then(function(res) { return http.get(sdk, res['jwks_uri']); }) @@ -134,37 +99,6 @@ function refreshIdToken(sdk, options) { return getToken(sdk, options); } -function loadFrame(src) { - var iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.src = src; - - return document.body.appendChild(iframe); -} - -function loadPopup(src, options) { - var title = options.popupTitle || 'External Identity Provider User Authentication'; - var appearance = 'toolbar=no, scrollbars=yes, resizable=yes, ' + - 'top=100, left=500, width=600, height=600'; - return window.open(src, title, appearance); -} - -function addListener(eventTarget, name, fn) { - if (eventTarget.addEventListener) { - eventTarget.addEventListener(name, fn); - } else { - eventTarget.attachEvent('on' + name, fn); - } - } - -function removeListener(eventTarget, name, fn) { - if (eventTarget.removeEventListener) { - eventTarget.removeEventListener(name, fn); - } else { - eventTarget.detachEvent('on' + name, fn); - } -} - function addPostMessageListener(sdk, timeout, state) { var deferred = Q.defer(); @@ -177,43 +111,14 @@ function addPostMessageListener(sdk, timeout, state) { deferred.resolve(e.data); } - addListener(window, 'message', responseHandler); + oauthUtil.addListener(window, 'message', responseHandler); return deferred.promise.timeout(timeout || 120000, new AuthSdkError('OAuth flow timed out')) .fin(function() { - removeListener(window, 'message', responseHandler); + oauthUtil.removeListener(window, 'message', responseHandler); }); } -function hashToObject(hash) { - // Predefine regexs for parsing hash - var plus2space = /\+/g; - var paramSplit = /([^&=]+)=?([^&]*)/g; - - // Remove the leading hash - var fragment = hash.substring(1); - - 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; } - - var key = param[1]; - var value = param[2]; - - // id_token should remain base64url encoded - if (key === 'id_token' || key === 'access_token' || key === 'code') { - obj[key] = value; - } else { - obj[key] = decodeURIComponent(value.replace(plus2space, ' ')); - } - } - return obj; -} - function addFragmentListener(sdk, windowEl, timeout) { var deferred = Q.defer(); @@ -229,7 +134,7 @@ function addFragmentListener(sdk, windowEl, timeout) { if (windowEl && windowEl.location && windowEl.location.hash) { - deferred.resolve(hashToObject(windowEl.location.hash)); + deferred.resolve(oauthUtil.hashToObject(windowEl.location.hash)); } else if (windowEl && !windowEl.closed) { setTimeout(hashChangeHandler, 500); } @@ -243,7 +148,9 @@ function addFragmentListener(sdk, windowEl, timeout) { return deferred.promise.timeout(timeout || 120000, new AuthSdkError('OAuth flow timed out')); } -function handleOAuthResponse(sdk, oauthParams, res) { +function handleOAuthResponse(sdk, oauthParams, res, urls) { + urls = urls || {}; + if (res['error'] || res['error_description']) { throw new OAuthError(res['error'], res['error_description']); } @@ -263,13 +170,15 @@ function handleOAuthResponse(sdk, oauthParams, res) { } var clientId = oauthParams.clientId || sdk.options.clientId; - validateClaims(sdk, jwt.payload, clientId); + oauthUtil.validateClaims(sdk, jwt.payload, clientId, urls.issuer); var idToken = { idToken: res['id_token'], claims: jwt.payload, expiresAt: jwt.payload.exp, - scopes: scopes + scopes: scopes, + authorizeUrl: urls.authorizeUrl, + issuer: urls.issuer }; if (Array.isArray(tokenTypes)) { @@ -284,7 +193,9 @@ function handleOAuthResponse(sdk, oauthParams, res) { accessToken: res['access_token'], expiresAt: Number(res['expires_in']) + Math.floor(Date.now()/1000), tokenType: res['token_type'], - scopes: scopes + scopes: scopes, + authorizeUrl: urls.authorizeUrl, + userinfoUrl: urls.userinfoUrl }; if (Array.isArray(tokenTypes)) { @@ -384,9 +295,9 @@ function convertOAuthParamsToQueryParams(oauthParams) { return oauthQueryParams; } -function buildAuthorizeUrl(sdk, oauthParams) { +function buildAuthorizeParams(oauthParams) { var oauthQueryParams = convertOAuthParamsToQueryParams(oauthParams); - return sdk.options.url + '/oauth2/v1/authorize' + util.toQueryParams(oauthQueryParams); + return util.toQueryParams(oauthQueryParams); } /* @@ -464,9 +375,12 @@ function getToken(sdk, oauthOptions, options) { } // Use the query params to build the authorize url - var requestUrl; + var requestUrl, + urls; try { - requestUrl = buildAuthorizeUrl(sdk, oauthParams); + // Get authorizeUrl and issuer + urls = oauthUtil.getOAuthUrls(sdk, oauthParams, options); + requestUrl = urls.authorizeUrl + buildAuthorizeParams(oauthParams); } catch (e) { return Q.reject(e); } @@ -490,10 +404,10 @@ function getToken(sdk, oauthOptions, options) { switch (flowType) { case 'IFRAME': var iframePromise = addPostMessageListener(sdk, options.timeout, oauthParams.state); - var iframeEl = loadFrame(requestUrl); + var iframeEl = oauthUtil.loadFrame(requestUrl); return iframePromise .then(function(res) { - return handleOAuthResponse(sdk, oauthParams, res); + return handleOAuthResponse(sdk, oauthParams, res, urls); }) .fin(function() { if (document.body.contains(iframeEl)) { @@ -517,7 +431,7 @@ function getToken(sdk, oauthOptions, options) { var windowOptions = { popupTitle: options.popupTitle }; - var windowEl = loadPopup(requestUrl, windowOptions); + var windowEl = oauthUtil.loadPopup(requestUrl, windowOptions); // Poll until we get a valid hash fragment if (oauthParams.responseMode === 'fragment') { @@ -552,7 +466,7 @@ function getToken(sdk, oauthOptions, options) { return popupDeferred.promise .then(function(res) { - return handleOAuthResponse(sdk, oauthParams, res); + return handleOAuthResponse(sdk, oauthParams, res, urls); }) .fin(function() { if (!windowEl.closed) { @@ -605,30 +519,23 @@ function getWithRedirect(sdk, oauthOptions, options) { } } - var requestUrl = buildAuthorizeUrl(sdk, oauthParams); + var urls = oauthUtil.getOAuthUrls(sdk, oauthParams, options); + var requestUrl = urls.authorizeUrl + buildAuthorizeParams(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, - scopes: oauthParams.scopes + scopes: oauthParams.scopes, + urls: urls })); sdk.token.getWithRedirect._setLocation(requestUrl); } -function isToken(obj) { - if (obj && - (obj.accessToken || obj.idToken) && - Array.isArray(obj.scopes)) { - return true; - } - return false; -} - function refreshToken(sdk, token) { - if (!isToken(token)) { + if (!oauthUtil.isToken(token)) { return Q.reject(new AuthSdkError('Refresh must be passed a token with ' + 'an array of scopes and an accessToken or idToken')); } @@ -642,6 +549,10 @@ function refreshToken(sdk, token) { return sdk.token.getWithoutPrompt({ responseType: responseType, scopes: token.scopes + }, { + authorizeUrl: token.authorizeUrl, + userinfoUrl: token.userinfoUrl, + issuer: token.issuer }); } @@ -657,25 +568,27 @@ function parseFromUrl(sdk, url) { } try { var oauthParams = JSON.parse(oauthParamsCookie); + var urls = oauthParams.urls; + delete oauthParams.urls; 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)) + return Q.resolve(oauthUtil.hashToObject(hash)) .then(function(res) { - return handleOAuthResponse(sdk, oauthParams, res); + return handleOAuthResponse(sdk, oauthParams, res, urls); }); } function getUserInfo(sdk, accessTokenObject) { if (!accessTokenObject || - (!isToken(accessTokenObject) && !accessTokenObject.accessToken)) { + (!oauthUtil.isToken(accessTokenObject) && !accessTokenObject.accessToken && !accessTokenObject.userinfoUrl)) { return Q.reject(new AuthSdkError('getUserInfo requires an access token object')); } return http.httpRequest(sdk, { - url: sdk.options.url + '/oauth2/v1/userinfo', + url: accessTokenObject.userinfoUrl, method: 'GET', dontSaveResponse: true, accessToken: accessTokenObject.accessToken diff --git a/lib/util.js b/lib/util.js index 537827431..357195df9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -206,6 +206,16 @@ function deprecateWrap(text, fn) { }; } +function removeTrailingSlash(path) { + if (!path) { + return; + } + if (path.slice(-1) === '/') { + return path.slice(0, -1); + } + return path; +} + module.exports = { base64UrlToBase64: base64UrlToBase64, base64UrlToString: base64UrlToString, @@ -227,5 +237,6 @@ module.exports = { find: find, getLink: getLink, deprecate: deprecate, - deprecateWrap: deprecateWrap + deprecateWrap: deprecateWrap, + removeTrailingSlash: removeTrailingSlash }; diff --git a/test/spec/oauth.js b/test/spec/oauth.js index 1f6628b6b..6f9859b24 100644 --- a/test/spec/oauth.js +++ b/test/spec/oauth.js @@ -11,14 +11,14 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, refreshArgs: {}, postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.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://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testSessionToken' }, postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.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://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', idp: 'testIdp' }, postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.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://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' } }) @@ -138,7 +138,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, authorizeArgs: { sessionToken: 'testToken' @@ -154,14 +154,14 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' }, postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -178,7 +178,7 @@ define(function(require) { return oauthUtil.setupFrame({ authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', scopes: ['openid', 'testscope'], sessionToken: 'testToken' }, @@ -186,7 +186,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -236,7 +236,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', scopes: ['notopenid'], sessionToken: 'testToken' } @@ -254,7 +254,7 @@ define(function(require) { oauthUtil.itpErrorsCorrectly('throws an error when clientId isn\'t specified', { authorizeArgs: { - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' } }, @@ -272,7 +272,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' }, postMessageResp: { @@ -332,7 +332,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', idp: 'testIdp' }, closePopup: true @@ -375,7 +375,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken', nonce: 'mismatchedNonce' } @@ -395,7 +395,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://different.issuer.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, authorizeArgs: { sessionToken: 'testToken' @@ -415,7 +415,7 @@ define(function(require) { { authorizeArgs: { clientId: 'differentAudience', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' } }, @@ -433,7 +433,7 @@ define(function(require) { { authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' }, postMessageResp: { @@ -456,7 +456,7 @@ define(function(require) { time: 9999999999, authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' } }, @@ -476,7 +476,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', maxClockSkew: 500 }, authorizeArgs: { @@ -490,7 +490,7 @@ define(function(require) { time: 0, authorizeArgs: { clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', sessionToken: 'testToken' } }, @@ -510,7 +510,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', maxClockSkew: 500 }, authorizeArgs: { @@ -525,7 +525,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, authorizeArgs: { sessionToken: 'testToken' @@ -539,7 +539,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', maxClockSkew: 0 }, authorizeArgs: { diff --git a/test/spec/oauthUtil.js b/test/spec/oauthUtil.js new file mode 100644 index 000000000..212a4eb25 --- /dev/null +++ b/test/spec/oauthUtil.js @@ -0,0 +1,190 @@ +define(function(require) { + var OktaAuth = require('OktaAuth'); + var oauthUtil = require('../../lib/oauthUtil'); + + describe('getOAuthUrls', function() { + function setupOAuthUrls(options) { + var sdk = new OktaAuth(options.oktaAuthArgs || { + url: 'https://auth-js-test.okta.com' + }); + + var oauthParams = options.oauthParams || { + responseType: 'id_token' + }; + + var result, error; + try { + result = oauthUtil.getOAuthUrls(sdk, oauthParams, options.options); + } catch(e) { + error = e; + } + + if (options.expectedResult) { + expect(result).toEqual(options.expectedResult); + } + + if (options.expectedError) { + expect(error.name).toEqual(options.expectedError.name); + expect(error.message).toEqual(options.expectedError.message); + expect(error.errorCode).toEqual('INTERNAL'); + expect(error.errorSummary).toEqual(options.expectedError.message); + expect(error.errorLink).toEqual('INTERNAL'); + expect(error.errorId).toEqual('INTERNAL'); + expect(error.errorCauses).toEqual([]); + } + } + + it('defaults all urls using global defaults', function() { + setupOAuthUrls({ + expectedResult: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }); + }); + it('sanitizes forward slashes', function() { + setupOAuthUrls({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + issuer: 'https://auth-js-test.okta.com/', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize/', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo/' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }); + }); + it('overrides defaults with options', function() { + setupOAuthUrls({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + issuer: 'https://bad.okta.com', + authorizeUrl: 'https://bad.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://bad.okta.com/oauth2/v1/userinfo' + }, + options: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }); + }); + it('sanitizes options with forward slashes', function() { + setupOAuthUrls({ + options: { + issuer: 'https://auth-js-test.okta.com/', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize/', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo/' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }); + }); + it('uses issuer to generate authorizeUrl and userinfoUrl', function() { + setupOAuthUrls({ + options: { + issuer: 'https://auth-js-test.okta.com' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }); + }); + it('uses authServer issuer to generate authorizeUrl and userinfoUrl', function() { + setupOAuthUrls({ + options: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }); + }); + it('uses authServer issuer as authServerId to generate authorizeUrl and userinfoUrl', function() { + setupOAuthUrls({ + options: { + issuer: 'aus8aus76q8iphupD0h7' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }); + }); + it('allows token requested with only authorizeUrl and userinfoUrl', function() { + setupOAuthUrls({ + oauthParams: { + responseType: 'token' + }, + options: { + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + }, + expectedResult: { + issuer: 'https://auth-js-test.okta.com', // We don't validate the issuer of access tokens, so this is ignored + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }); + }); + it('fails if id_token requested without issuer, with authorizeUrl', function() { + setupOAuthUrls({ + oauthParams: { + responseType: 'id_token' + }, + options: { + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize' + }, + expectedError: { + name: 'AuthSdkError', + message: 'Cannot request idToken with an authorizeUrl without an issuer' + } + }); + }); + it('fails if token requested without issuer, without userinfoUrl, with authorizeUrl', function() { + setupOAuthUrls({ + oauthParams: { + responseType: 'token' + }, + options: { + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize' + }, + expectedError: { + name: 'AuthSdkError', + message: 'Cannot request accessToken with an authorizeUrl without an issuer or userinfoUrl' + } + }); + }); + it('fails if token requested without issuer, without authorizeUrl, with userinfoUrl', function() { + setupOAuthUrls({ + oauthParams: { + responseType: 'id_token' + }, + options: { + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + }, + expectedError: { + name: 'AuthSdkError', + message: 'Cannot request token with an userinfoUrl without an issuer or authorizeUrl' + } + }); + }); + }); +}); diff --git a/test/spec/token.js b/test/spec/token.js index de071912c..e24d57ae2 100644 --- a/test/spec/token.js +++ b/test/spec/token.js @@ -37,7 +37,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { sessionToken: 'testSessionToken' @@ -46,7 +46,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -62,12 +62,160 @@ define(function(require) { }); }); + it('returns id_token using sessionToken with issuer', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithoutPromptArgs: { + sessionToken: 'testSessionToken' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('returns id_token using sessionToken with issuer as id', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'aus8aus76q8iphupD0h7' + }, + getWithoutPromptArgs: { + sessionToken: 'testSessionToken' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('allows passing issuer through getWithoutPrompt, which takes precedence', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/ORIGINAL_AUTH_SERVER_ID' + }, + getWithoutPromptArgs: [{ + sessionToken: 'testSessionToken' + }, { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }], + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('allows passing issuer as an id through getWithoutPrompt, which takes precedence', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/ORIGINAL_AUTH_SERVER_ID' + }, + getWithoutPromptArgs: [{ + sessionToken: 'testSessionToken' + }, { + issuer: 'aus8aus76q8iphupD0h7' + }], + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + it('returns id_token overriding all possible oauth params', function (done) { return oauthUtil.setupFrame({ oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { sessionToken: 'testSessionToken', @@ -177,7 +325,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { responseType: 'token', @@ -187,7 +335,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -204,12 +352,88 @@ define(function(require) { 'expires_in': 3600, 'state': oauthUtil.mockedState }, - expectedResp: { - accessToken: tokens.standardAccessToken, - expiresAt: 1449703529, - scopes: ['openid', 'email'], - tokenType: 'Bearer' - } + expectedResp: tokens.standardAccessTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token using sessionToken with authorization server', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithoutPromptArgs: { + responseType: 'token', + sessionToken: 'testSessionToken' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + time: 1449699929, + postMessageResp: { + 'access_token': tokens.authServerAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerAccessTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token and id_token with an authorization server', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithoutPromptArgs: { + responseType: ['id_token', 'token'], + sessionToken: 'testSessionToken' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none', + 'sessionToken': 'testSessionToken' + } + }, + time: 1449699929, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'access_token': tokens.authServerAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: [tokens.authServerIdTokenParsed, tokens.authServerAccessTokenParsed] }) .fin(function() { done(); @@ -221,7 +445,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { responseType: ['id_token', 'token'], @@ -231,7 +455,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -249,17 +473,7 @@ define(function(require) { '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' - }] + expectedResp: [tokens.standardIdTokenParsed, tokens.standardAccessTokenParsed] }) .fin(function() { done(); @@ -271,7 +485,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { responseType: ['token', 'id_token'], @@ -281,7 +495,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -299,17 +513,7 @@ define(function(require) { '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'] - }] + expectedResp: [tokens.standardAccessTokenParsed, tokens.standardIdTokenParsed] }) .fin(function() { done(); @@ -321,7 +525,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { responseType: ['id_token'], @@ -331,7 +535,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -341,12 +545,7 @@ define(function(require) { 'sessionToken': 'testSessionToken' } }, - expectedResp: [{ - idToken: tokens.standardIdToken, - claims: tokens.standardIdTokenClaims, - expiresAt: 1449699930, - scopes: ['openid', 'email'] - }] + expectedResp: [tokens.standardIdTokenParsed] }) .fin(function() { done(); @@ -358,7 +557,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithoutPromptArgs: { responseType: 'id_token token', @@ -383,7 +582,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithPopupArgs: { idp: 'testIdp' @@ -392,7 +591,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -408,6 +607,80 @@ define(function(require) { }); }); + it('returns id_token using idp with authorization server', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithPopupArgs: { + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('allows passing issuer through getWithPopup, which takes precedence', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/ORIGINAL_AUTH_SERVER_ID' + }, + getWithPopupArgs: [{ + idp: 'testIdp' + }, { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }], + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'display': 'popup', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'idp': 'testIdp' + } + }, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + it('allows multiple popups simultaneously', function (done) { return oauthUtil.setupSimultaneousPostMessage() .then(function(context) { @@ -474,7 +747,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithPopupArgs: { responseType: 'token', @@ -484,7 +757,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -501,12 +774,88 @@ define(function(require) { 'expires_in': 3600, 'state': oauthUtil.mockedState }, - expectedResp: { - accessToken: tokens.standardAccessToken, - expiresAt: 1449703529, - scopes: ['openid', 'email'], - tokenType: 'Bearer' - } + expectedResp: tokens.standardAccessTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token using idp with authorization server', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithPopupArgs: { + responseType: 'token', + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.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.authServerAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: tokens.authServerAccessTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token and id_token using idp with authorization server', function (done) { + return oauthUtil.setupPopup({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithPopupArgs: { + responseType: ['token', 'id_token'], + idp: 'testIdp' + }, + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.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.authServerIdToken, + 'access_token': tokens.authServerAccessToken, + 'token_type': 'Bearer', + 'expires_in': 3600, + 'state': oauthUtil.mockedState + }, + expectedResp: [tokens.authServerAccessTokenParsed, tokens.authServerIdTokenParsed] }) .fin(function() { done(); @@ -518,7 +867,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithPopupArgs: { responseType: ['token', 'id_token'], @@ -528,7 +877,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token id_token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -546,17 +895,7 @@ define(function(require) { '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'] - }] + expectedResp: [tokens.standardAccessTokenParsed, tokens.standardIdTokenParsed] }) .fin(function() { done(); @@ -568,7 +907,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, getWithPopupArgs: { responseType: ['id_token', 'token'], @@ -578,7 +917,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token token', 'response_mode': 'okta_post_message', 'display': 'popup', @@ -596,17 +935,7 @@ define(function(require) { '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' - }] + expectedResp: [tokens.standardIdTokenParsed, tokens.standardAccessTokenParsed] }) .fin(function() { done(); @@ -624,11 +953,16 @@ define(function(require) { responseType: 'id_token', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -638,46 +972,199 @@ define(function(require) { }); }); + it('sets authorize url and cookie for id_token using sessionToken and authorization server', function() { + oauthUtil.setupRedirect({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithRedirectArgs: { + sessionToken: 'testToken' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'id_token', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=id_token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=openid%20email' + }); + }); + + it('allows passing issuer through getWithRedirect, which takes precedence', function() { + oauthUtil.setupRedirect({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/ORIGINAL_AUTH_SERVER_ID' + }, + getWithRedirectArgs: [{ + responseType: 'token', + scopes: ['email'], + sessionToken: 'testToken' + }, { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }], + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=email' + }); + }); + 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', - scopes: ['email'], - sessionToken: 'testToken' + responseType: 'token', + scopes: ['email'], + sessionToken: 'testToken' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + scopes: ['email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } + }) + ';', + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=email' + }); + }); + + it('sets authorize url and cookie for access_token using sessionToken and authorization server', function() { + oauthUtil.setupRedirect({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithRedirectArgs: { + responseType: 'token', + scopes: ['email'], + sessionToken: 'testToken' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=token&' + + 'response_mode=fragment&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=email' + }); + }); + + 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', + responseType: ['token', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + - 'response_type=token&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=token%20id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + - 'sessionToken=testToken&' + - 'scope=email' + 'idp=testIdp&' + + 'scope=openid%20email' }); }); - it('sets authorize url for access_token and id_token using idp', function() { + it('sets authorize url for access_token and id_token using idp and authorization server', function() { oauthUtil.setupRedirect({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, getWithRedirectArgs: { responseType: ['token', 'id_token'], idp: 'testIdp' }, expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ responseType: ['token', 'id_token'], - state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } }) + ';', - expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=token%20id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -697,11 +1184,51 @@ define(function(require) { responseType: 'code', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + + 'response_type=code&' + + 'response_mode=query&' + + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'nonce=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + + 'sessionToken=testToken&' + + 'scope=openid%20email' + }); + }); + + it('sets authorize url for authorization code requests with an authorization server', function() { + oauthUtil.setupRedirect({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' + }, + getWithRedirectArgs: { + sessionToken: 'testToken', + responseType: 'code' + }, + expectedCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'code', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=code&' + 'response_mode=query&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -722,11 +1249,16 @@ define(function(require) { responseType: ['code'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=code&' + 'response_mode=query&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -747,11 +1279,16 @@ define(function(require) { responseType: ['code', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=code%20id_token&' + 'response_mode=fragment&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -772,11 +1309,16 @@ define(function(require) { responseType: 'code', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'redirect_uri=https%3A%2F%2Fauth-js-test.okta.com%2Fredirect&' + + 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + 'response_type=code&' + 'response_mode=form_post&' + 'state=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&' + @@ -796,7 +1338,12 @@ define(function(require) { responseType: 'id_token', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', expectedResp: { idToken: tokens.standardIdToken, @@ -810,6 +1357,28 @@ define(function(require) { }); }); + it('parses id_token with authorization server issuer', function(done) { + return oauthUtil.setupParseUrl({ + hashMock: '#id_token=' + tokens.authServerIdToken + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'id_token', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedResp: tokens.authServerIdTokenParsed + }) + .fin(function() { + done(); + }); + }); + it('parses access_token', function(done) { return oauthUtil.setupParseUrl({ time: 1449699929, @@ -821,14 +1390,39 @@ define(function(require) { responseType: 'token', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', - expectedResp: { - accessToken: tokens.standardAccessToken, - expiresAt: 1449703529, + expectedResp: tokens.standardAccessTokenParsed + }) + .fin(function() { + done(); + }); + }); + + it('parses access_token with authorization server issuer', function(done) { + return oauthUtil.setupParseUrl({ + time: 1449699929, + hashMock: '#access_token=' + tokens.authServerAccessToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: 'token', + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, scopes: ['openid', 'email'], - tokenType: 'Bearer' - } + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedResp: tokens.authServerAccessTokenParsed }) .fin(function() { done(); @@ -847,19 +1441,40 @@ define(function(require) { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', - expectedResp: [{ - idToken: tokens.standardIdToken, - claims: tokens.standardIdTokenClaims, - expiresAt: 1449699930, - scopes: ['openid', 'email'] - }, { - accessToken: tokens.standardAccessToken, - expiresAt: 1449703529, + expectedResp: [tokens.standardIdTokenParsed, tokens.standardAccessTokenParsed] + }) + .fin(function() { + done(); + }); + }); + + it('parses access_token and id_token with authorization server issuer', function(done) { + return oauthUtil.setupParseUrl({ + time: 1449699929, + hashMock: '#access_token=' + tokens.authServerAccessToken + + '&id_token=' + tokens.authServerIdToken + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token'], + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, scopes: ['openid', 'email'], - tokenType: 'Bearer' - }] + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedResp: [tokens.authServerIdTokenParsed, tokens.authServerTokenParsed] }) .fin(function() { done(); @@ -879,19 +1494,43 @@ define(function(require) { responseType: ['id_token', 'token', 'code'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';', - expectedResp: [{ - idToken: tokens.standardIdToken, - claims: tokens.standardIdTokenClaims, - expiresAt: 1449699930, - scopes: ['openid', 'email'] - }, { - accessToken: tokens.standardAccessToken, - expiresAt: 1449703529, + expectedResp: [tokens.standardIdTokenParsed, tokens.standardAccessTokenParsed, { + authorizationCode: tokens.standardAuthorizationCode + }] + }) + .fin(function() { + done(); + }); + }); + + it('parses access_token, id_token, and code with authorization server issuer', function(done) { + return oauthUtil.setupParseUrl({ + time: 1449699929, + hashMock: '#access_token=' + tokens.authServerAccessToken + + '&id_token=' + tokens.authServerIdToken + + '&code=' + tokens.standardAuthorizationCode + + '&expires_in=3600' + + '&token_type=Bearer' + + '&state=' + oauthUtil.mockedState, + oauthCookie: 'okta-oauth-redirect-params=' + JSON.stringify({ + responseType: ['id_token', 'token', 'code'], + state: oauthUtil.mockedState, + nonce: oauthUtil.mockedNonce, scopes: ['openid', 'email'], - tokenType: 'Bearer' - }, { + urls: { + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' + } + }) + ';', + expectedResp: [tokens.authServerIdTokenParsed, tokens.authServerAccessTokenParsed, { authorizationCode: tokens.standardAuthorizationCode }] }) @@ -908,7 +1547,12 @@ define(function(require) { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';' }, { @@ -955,7 +1599,12 @@ define(function(require) { responseType: ['id_token', 'token'], state: 'mismatchedState', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';' }, { @@ -981,7 +1630,12 @@ define(function(require) { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'mismatchedNonce', - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + urls: { + issuer: 'https://auth-js-test.okta.com', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + } }) + ';' }, { @@ -1002,14 +1656,41 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenRefreshArgs: [tokens.standardIdTokenParsed], postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'id_token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none' + } + } + }) + .fin(function() { + done(); + }); + }); + + it('returns id_token with authorization server', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect' + }, + tokenRefreshArgs: [tokens.authServerIdTokenParsed], + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -1017,6 +1698,18 @@ define(function(require) { 'scope': 'openid email', 'prompt': 'none' } + }, + time: 1449699929, + postMessageResp: { + 'id_token': tokens.authServerIdToken, + 'state': oauthUtil.mockedState + }, + expectedResp: { + idToken: tokens.authServerIdToken, + claims: tokens.authServerIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'custom'], + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' } }) .fin(function() { @@ -1029,14 +1722,42 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenRefreshArgs: [tokens.standardAccessTokenParsed], postMessageSrc: { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', + 'response_type': 'token', + 'response_mode': 'okta_post_message', + 'state': oauthUtil.mockedState, + 'nonce': oauthUtil.mockedNonce, + 'scope': 'openid email', + 'prompt': 'none' + } + } + }) + .fin(function() { + done(); + }); + }); + + it('returns access_token with authorization server', function (done) { + return oauthUtil.setupFrame({ + oktaAuthArgs: { + url: 'https://auth-js-test.okta.com', + clientId: 'NPSfOkH5eZrTy8PMDlvx', + redirectUri: 'https://example.com/redirect', + issuer: 'https://auth-js-test.okta.com/oauth2/wontusethisone' + }, + tokenRefreshArgs: [tokens.authServerAccessTokenParsed], + postMessageSrc: { + baseUri: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + queryParams: { + 'client_id': 'NPSfOkH5eZrTy8PMDlvx', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -1044,6 +1765,20 @@ define(function(require) { 'scope': 'openid email', 'prompt': 'none' } + }, + 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', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' } }) .fin(function() { @@ -1056,7 +1791,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenRefreshArgs: [{non:'token'}] }, @@ -1099,6 +1834,32 @@ define(function(require) { } }); + util.itMakesCorrectRequestResponse({ + title: 'allows retrieving UserInfo using authorization server', + setup: { + request: { + uri: '/oauth2/aus8aus76q8iphupD0h7/v1/userinfo', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Okta-User-Agent-Extended': 'okta-auth-js-' + packageJson.version, + 'Authorization': 'Bearer ' + tokens.authServerAccessToken + } + }, + response: 'userinfo' + }, + execute: function (test) { + return test.oa.token.getUserInfo(tokens.authServerAccessTokenParsed); + }, + expectations: function (test, res) { + expect(res).toEqual({ + 'sub': '00u15ozp26ACQTGHJEBH', + 'email': 'samljackson@example.com', + 'email_verified': true + }); + } + }); + it('throws an error if no arguments are passed instead', function(done) { return Q.resolve(setupSync()) .then(function (oa) { diff --git a/test/spec/tokenManager.js b/test/spec/tokenManager.js index d83948f88..e712f966c 100644 --- a/test/spec/tokenManager.js +++ b/test/spec/tokenManager.js @@ -9,7 +9,7 @@ define(function(require) { return new OktaAuth({ url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect', + redirectUri: 'https://example.com/redirect', tokenManager: { storage: options.type, autoRefresh: options.autoRefresh @@ -64,7 +64,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-idToken': { @@ -79,7 +79,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -107,7 +107,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-accessToken': { @@ -122,7 +122,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -152,7 +152,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerRefreshArgs: ['test-accessToken'] }, @@ -174,7 +174,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerRefreshArgs: ['test-accessToken'] }) @@ -200,7 +200,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-idToken': tokens.standardIdTokenParsed @@ -210,7 +210,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -241,7 +241,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-accessToken': tokens.standardAccessTokenParsed, @@ -286,7 +286,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-idToken': { @@ -300,7 +300,7 @@ define(function(require) { baseUri: 'https://auth-js-test.okta.com/oauth2/v1/authorize', queryParams: { 'client_id': 'NPSfOkH5eZrTy8PMDlvx', - 'redirect_uri': 'https://auth-js-test.okta.com/redirect', + 'redirect_uri': 'https://example.com/redirect', 'response_type': 'id_token', 'response_mode': 'okta_post_message', 'state': oauthUtil.mockedState, @@ -329,7 +329,7 @@ define(function(require) { oktaAuthArgs: { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }, tokenManagerAddKeys: { 'test-idToken': tokens.standardIdTokenParsed diff --git a/test/util/oauthUtil.js b/test/util/oauthUtil.js index cea121de6..bb1620537 100644 --- a/test/util/oauthUtil.js +++ b/test/util/oauthUtil.js @@ -118,9 +118,17 @@ define(function(require) { if (opts.refreshArgs) { promise = authClient.idToken.refresh(opts.refreshArgs); } else if (opts.getWithoutPromptArgs) { - promise = authClient.token.getWithoutPrompt(opts.getWithoutPromptArgs); + if (Array.isArray(opts.getWithoutPromptArgs)) { + promise = authClient.token.getWithoutPrompt.apply(null, opts.getWithoutPromptArgs); + } else { + promise = authClient.token.getWithoutPrompt(opts.getWithoutPromptArgs); + } } else if (opts.getWithPopupArgs) { - promise = authClient.token.getWithPopup(opts.getWithPopupArgs); + if (Array.isArray(opts.getWithPopupArgs)) { + promise = authClient.token.getWithPopup.apply(null, opts.getWithPopupArgs); + } else { + promise = authClient.token.getWithPopup(opts.getWithPopupArgs); + } } else if (opts.tokenManagerRefreshArgs) { promise = authClient.tokenManager.refresh.apply(this, opts.tokenManagerRefreshArgs); } else if (opts.tokenRefreshArgs) { @@ -155,8 +163,8 @@ define(function(require) { if (opts.willFail) { throw err; } else { - // Should never hit this - expect(true).toBe(false); + expect('not to be hit').toBe(true); + console.log(err); // eslint-disable-line } }); }; @@ -271,17 +279,21 @@ define(function(require) { }; oauthUtil.setupRedirect = function(opts) { - var client = new OktaAuth({ + var client = new OktaAuth(opts.oktaAuthArgs || { url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }); oauthUtil.mockStateAndNonce(); var windowLocationMock = util.mockSetWindowLocation(client); var setCookieMock = util.mockSetCookie(); - client.token.getWithRedirect(opts.getWithRedirectArgs); + if (Array.isArray(opts.getWithRedirectArgs)) { + client.token.getWithRedirect.apply(null, opts.getWithRedirectArgs); + } else { + client.token.getWithRedirect(opts.getWithRedirectArgs); + } expect(windowLocationMock).toHaveBeenCalledWith(opts.expectedRedirectUrl); expect(setCookieMock).toHaveBeenCalledWith(opts.expectedCookie); @@ -291,7 +303,7 @@ define(function(require) { var client = new OktaAuth({ url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }); util.warpToUnixTime(getTime(opts.time)); @@ -315,7 +327,7 @@ define(function(require) { var client = new OktaAuth({ url: 'https://auth-js-test.okta.com', clientId: 'NPSfOkH5eZrTy8PMDlvx', - redirectUri: 'https://auth-js-test.okta.com/redirect' + redirectUri: 'https://example.com/redirect' }); var emitter = new EventEmitter(); diff --git a/test/util/tokens.js b/test/util/tokens.js index 371a8250b..175b7c368 100644 --- a/test/util/tokens.js +++ b/test/util/tokens.js @@ -1,3 +1,4 @@ +/* eslint max-statements:[2,22] */ define(function() { var tokens = {}; @@ -90,7 +91,9 @@ define(function() { idToken: tokens.standardIdToken, claims: tokens.standardIdTokenClaims, expiresAt: 1449699930, - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + issuer: 'https://auth-js-test.okta.com' }; // Uses modified nonce for testing simultaneous iframes @@ -141,7 +144,54 @@ define(function() { idToken: tokens.standardIdToken2, claims: tokens.standardIdToken2Claims, expiresAt: 1449699930, - scopes: ['openid', 'email'] + scopes: ['openid', 'email'], + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + issuer: 'https://auth-js-test.okta.com' + }; + + tokens.authServerIdToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiO' + + 'iIwMHVrb2VFcUlvZ2lGSHBEZTBnMyIsImVtYWlsIjoic2F' + + 'tbGphY2tzb25Ab2t0YS5jb20iLCJ2ZXIiOjEsImlzcyI6I' + + 'mh0dHBzOi8vYXV0aC1qcy10ZXN0Lm9rdGEuY29tL29hdXR' + + 'oMi9hdXM4YXVzNzZxOGlwaHVwRDBoNyIsImF1ZCI6Ik5QU' + + '2ZPa0g1ZVpyVHk4UE1EbHZ4IiwiaWF0IjoxNDQ5Njk2MzM' + + 'wLCJleHAiOjE0NDk2OTk5MzAsImp0aSI6IklELlNpOUtxR' + + '3RTV2hLQnJzRGh2bEV0QVItR3lkc2V1Y1VHOXhXdVdLMUp' + + 'oNTgiLCJhbXIiOlsicHdkIl0sImlkcCI6IjAwb2tucjFDS' + + 'GxXYUF3d2dvMGczIiwibm9uY2UiOiJhYWFhYWFhYWFhYWF' + + 'hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY' + + 'WFhYWFhYWFhYWFhYWFhYWFhIiwiZW1haWxfdmVyaWZpZWQ' + + 'iOnRydWUsImF1dGhfdGltZSI6MTQ0OTY5NjMzMH0.ekTCW' + + 'khumsT0lXnY-JfzQqfiVkgJzcQoLkvMbtRWb2FG0PYvgTb' + + 'p2MH-lb_Oo6qc2_ZWNieGD7RAhr-dRBXJh8BtDOWR3Zrvp' + + 'Ib_l6Vuv0hDx03tD1WvsbXmwMNsDqFKzR6RGFB-g-Y0Ijc' + + 'qAdJH1xFyb0dPVgj86jb0niRX584'; + + tokens.authServerIdTokenClaims = { + 'sub': '00ukoeEqIogiFHpDe0g3', + 'email': 'samljackson@okta.com', + 'ver': 1, + 'iss': 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', + 'aud': 'NPSfOkH5eZrTy8PMDlvx', + 'iat': 1449696330, + 'exp': 1449699930, + 'jti': 'ID.Si9KqGtSWhKBrsDhvlEtAR-GydseucUG9xWuWK1Jh58', + 'amr': [ + 'pwd' + ], + 'idp': '00oknr1CHlWaAwwgo0g3', + 'nonce': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'email_verified': true, + 'auth_time': 1449696330 + }; + + tokens.authServerIdTokenParsed = { + idToken: tokens.authServerIdToken, + claims: tokens.authServerIdTokenClaims, + expiresAt: 1449699930, + scopes: ['openid', 'email'], + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' }; tokens.modifiedIdToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMHUx' + @@ -202,7 +252,31 @@ define(function() { accessToken: tokens.standardAccessToken, expiresAt: 1449703529, // assuming time = 1449699929 scopes: ['openid', 'email'], - tokenType: 'Bearer' + tokenType: 'Bearer', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' + }; + + tokens.authServerAccessToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXIiOjEsImp' + + '0aSI6IkFULl8wWTNCYkV5X2Y0MlNjUzJWT3drc1RwOEI4UW9qWVM' + + 'zYk10WENERnJ4aDgiLCJpc3MiOiJodHRwczovL2F1dGgtanMtdGV' + + 'zdC5va3RhLmNvbS9vYXV0aDIvYXVzOGF1czc2cThpcGh1cEQwaDc' + + 'iLCJhdWQiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJzdWIiOiJzYW1' + + 'samFja3NvbkBva3RhLmNvbSIsImlhdCI6MTQ0OTY5OTkyOSwiZXh' + + 'wIjoxNDQ5NzAzNTI5LCJjaWQiOiJnTHpGMERoalFJR0NUNHFPMFN' + + 'NQiIsInVpZCI6IjAwdWtvZUVxSW9naUZIcERlMGczIiwic2NwIjp' + + 'bIm9wZW5pZCIsImVtYWlsIl19.sD7CmiX1JCrngJFbYid5za78-c' + + 'vOdVEFONqx7m5Ar8OK3MWPuui9wbzBvyiBR70rCuKzb0gSZb96N0' + + 'EE8wXbgYjzGH5T6dazwgGfGmVf2PTa1pKfPew7f_XKE_t1O_tJ9C' + + 'h9gY9Z3xd92ac407ZIOHkabLvZ0-45ANM3Gm0LC0c'; + + tokens.authServerAccessTokenParsed = { + accessToken: tokens.authServerAccessToken, + expiresAt: 1449703529, // assuming time = 1449699929 + scopes: ['openid', 'email'], + tokenType: 'Bearer', + authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', + userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' }; /* diff --git a/test/util/util.js b/test/util/util.js index bc99dc6e3..f4aa63536 100644 --- a/test/util/util.js +++ b/test/util/util.js @@ -106,7 +106,7 @@ define(function(require) { function setup(options) { if (!options.uri) { - options.uri = 'http://foo.com'; + options.uri = 'https://auth-js-test.okta.com'; } var ajaxMock, resReply, oa, trans;