Skip to content

Commit

Permalink
version 3.0.0
Browse files Browse the repository at this point in the history
Add babel, browserslist. eslint for browser compatibility (#306)

chore : remove Q, replace with standard Promise (#309)

feat: signOut uses redirect method. new method closeSession (#310)
  • Loading branch information
aarongranick-okta committed Jan 21, 2020
1 parent adb3573 commit 28a83f5
Show file tree
Hide file tree
Showing 50 changed files with 1,230 additions and 1,050 deletions.
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
{
"extends": ["eslint:recommended"],
"env": {
"browser": true,
"browser": false,
"commonjs": true
},
"globals": {
"Promise": true,
"console": true,
"setTimeout": true,
"clearTimeout": true,
"setInterval": true,
"clearInterval": true
},
"rules": {
"camelcase": 2,
"complexity": [2, 7],
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- '8'
- '10'
install:
- yarn install --frozen-lockfile
script:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 3.0.0

### Breaking Changes

- [#309](https://github.com/okta/okta-auth-js/pull/309) - Removed `Q` library, now using standard Promise. IE11 will require a polyfill for the `Promise` object. Use of `Promise.prototype.finally` requires Node > 10.3 for server-side use.

- [#310](https://github.com/okta/okta-auth-js/pull/310)
- `postLogoutRedirectUri` will default to `window.location.origin`
- `signOut` will revoke access token and perform redirect by default. Fallback to XHR (`closeSession`) if no idToken.
- New method `closeSession` for XHR signout without redirect or reload.
- New method `revokeAccessToken`

### Other

## 2.12.0

### Features
Expand Down
126 changes: 73 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,29 @@ Installing the Authentication SDK is simple. You can include it in your project
You'll also need:

* An Okta account, called an _organization_ (sign up for a free [developer organization](https://developer.okta.com/signup) if you need one)
* An Okta application, which can be created using the Okta Admin UI

### Creating your Okta application

When creating a new Okta application, you can specify the application type. This SDK is designed to work with `SPA` (Single-page Applications) or `Web` applications. A `SPA` application will perform all logic and authorization flows client-side. A `Web` application will perform authorization flows on the server.

### Configuring your Okta application

From the Okta Admin UI, click `Applications`, then select your application. You can view and edit your Okta application's configuration under the application's `General` tab.

#### Client ID

A string which uniquely identifies your Okta application.

#### Login redirect URIs

To sign users in, your application redirects the browser to an Okta-hosted sign-in page. Okta then redirects back to your application with information about the user. You can learn more about how this works on [Okta-hosted flows](https://developer.okta.com/docs/concepts/okta-hosted-flows/).

You need to whitelist the login redirect URL in your Okta application settings.

#### Logout redirect URIs

After you sign users out of your app and out of Okta, you have to redirect users to a specific location in your application. You need to whitelist the post sign-out URL in your Okta application settings.

### Using the npm module

Expand Down Expand Up @@ -194,8 +217,8 @@ tokenManager: {
| -------------- | ------------ |
| `issuer` | Specify a custom issuer to perform the OIDC flow. Defaults to the base url parameter if not provided. |
| `clientId` | Client Id pre-registered with Okta for the OIDC authentication flow. |
| `redirectUri` | The url that is redirected to when using `token.getWithRedirect`. This must be pre-registered as part of client registration. If no `redirectUri` is provided, defaults to the current origin. |
| `postLogoutRedirectUri` | Specify the url where the browser should be redirected after [signOut](#signout). This url must be added to the list of `Logout redirect URIs` on the application's `General Settings` tab.
| `redirectUri` | The url that is redirected to when using `token.getWithRedirect`. This must be listed in your Okta application's [Login redirect URIs](#login-redirect-uris). If no `redirectUri` is provided, defaults to the current origin (`window.location.origin`). |
| `postLogoutRedirectUri` | Specify the url where the browser should be redirected after [signOut](#signout). This url must be listed in your Okta application's [Logout redirect URIs](#logout-redirect-uris). If not specified, your application's origin (`window.location.origin`) will be used.
| `pkce` | If set to true, the authorization flow will automatically use PKCE. The authorize request will use `response_type=code`, and `grant_type=authorization_code` will be used on the token request. All these details are handled for you, including the creation and verification of code verifiers. |
| `authorizeUrl` | Specify a custom authorizeUrl to perform the OIDC flow. Defaults to the issuer plus "/v1/authorize". |
| `userinfoUrl` | Specify a custom userinfoUrl. Defaults to the issuer plus "/v1/userinfo". |
Expand Down Expand Up @@ -331,6 +354,8 @@ var config = {

* [signIn](#signinoptions)
* [signOut](#signout)
* [closeSession](#closesession)
* [revokeAccessToken](#revokeaccesstokenaccesstoken)
* [forgotPassword](#forgotpasswordoptions)
* [unlockAccount](#unlockaccountoptions)
* [verifyRecoveryToken](#verifyrecoverytokenoptions)
Expand Down Expand Up @@ -395,88 +420,83 @@ authClient.signIn({
throw 'We cannot handle the ' + transaction.status + ' status';
}
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
```

### `signOut()`

Signs the user out of their current [Okta session](https://developer.okta.com/docs/api/resources/sessions) and clears all tokens stored locally in the `TokenManager`. The Okta session can be closed using either an `XHR` method or a `redirect` method. By default, the `XHR` method is used. Here are some points to consider when deciding which method is most appropriate for your application:
Signs the user out of their current [Okta session](https://developer.okta.com/docs/api/resources/sessions) and clears all tokens stored locally in the `TokenManager`. By default, the access token is revoked so it can no longer be used. Some points to consider:

XHR:

* Executes in the background. The user will see not any change to `window.location`.
* Will fail if 3rd-party cookies are blocked by the browser.
* If the session is already closed, the method will fail and reject the returned Promise. This error can be caught by the app and handled seamlessly.
* It is recommended (but not required) for the app to call `window.location.reload()` after the `XHR` method completes to ensure your app is properly re-initialized in an unauthenticated state.
* For more information, see [Close Current Session](https://developer.okta.com/docs/reference/api/sessions/#close-current-session) in the Session API documentation.

Redirect:

* Will change the `window.location` to an Okta-hosted page before redirecting to a URI of your choice.
* No issue with 3rd-party cookies.
* Requires a `postLogoutRedirectUri` to be specified. This URI must be whitelisted in the Okta application's settings. If the `postLogoutRedirectUri` is unknown or invalid the redirect will end on a 400 error page from Okta. This error will be visible to the user and cannot be handled by the app.
* Requires a valid ID token. If an ID token is not available, `signOut` will fallback to using the `XHR` method and then redirect to the `postLogoutRedirectUri`.
* Will redirect to an Okta-hosted page before returning to your app.
* If a `postLogoutRedirectUri` has not been specified or configured, `window.location.origin` will be used as the return URI. This URI must be listed in the Okta application's [Login redirect URIs](#login-redirect-uris). If the URI is unknown or invalid the redirect will end on a 400 error page from Okta. This error will be visible to the user and cannot be handled by the app.
* Requires a valid ID token. If an ID token is not available, `signOut` will fallback to using the XHR-based [closeSession](#closesession) method. This method may fail to sign the user out if 3rd-party cookies have been blocked by the browser.
* For more information, see [Logout](https://developer.okta.com/docs/reference/api/oidc/#logout) in the OIDC API documentation.

`signOut` takes the following options:

* `postLogoutRedirectUri` - Setting a value will enable the logout redirect method. **The URI must be whitelisted** as a `Logout Redirect Uri` in your application's general settings. It is common to use your application's origin URI as the `postLogoutRedirectUri` so that users are sent to the application "home page" after signout.
* `postLogoutRedirectUri` - Setting a value will override the `postLogoutRedirectUri` configured on the SDK.
* `state` - An optional value, used along with `postLogoutRedirectUri`. If set, this value will be returned as a query parameter during the redirect to the `postLogoutRedirectUri`
* `idToken` - Specifies the ID token object. This is only relevant when a `postLogoutRedirectUri` has been specified. By default, `signOut` will look for a token object named `idToken` within the `TokenManager`. If you have stored the id token object in a different location, you should retrieve it first and then pass it here.
* `revokeAccessToken` - If `true`, the access token will be revoked before the session is closed.
* `accessToken` - Specifies the access token object. This is only relevant when the `revokeAccessToken` option is `true`. By default, `signOut` will look for a token object named `token` within the `TokenManager`. If you have stored the access token object in a different location, you should retrieve it first and then pass it here.
* `idToken` - Specifies the ID token object. By default, `signOut` will look for a token object named `idToken` within the `TokenManager`. If you have stored the id token object in a different location, you should retrieve it first and then pass it here.
* `revokeAccessToken` - If `false`, the access token will not be revoked. Use this option with care: not revoking the access token may pose a security risk if the token has been leaked outside the application.
* `accessToken` - Specifies the access token object. By default, `signOut` will look for a token object named `accessToken` within the `TokenManager`. If you have stored the access token object in a different location, you should retrieve it first and then pass it here. This options is ignored if the `revokeAccessToken` option is `false`.

```javascript
// Sign out using the XHR method
// Sign out using the default options
authClient.signOut()
.then(function() {
console.log('successfully logged out');
})
.catch(function(err) {
console.error(err);
})
.then(function() {
// Reload app in unauthenticated state
window.location.reload();
});
```

```javascript
// Sign out using the redirect method, specifying the current window origin as the post logout URI
// Override the post logout URI for this call
authClient.signOut({
postLogoutRedirectUri: window.location.origin
postLogoutRedirectUri: `${window.location.origin}/logout/callback`
});
```

```javascript
// In this case, the ID token is stored under the 'myIdToken' key
var idToken = await authClient.tokenManager.get('myIdToken');
authClient.signOut({
idToken: idToken,
postLogoutRedirectUri: window.location.origin
idToken: idToken
});
```

```javascript
// Revoke the access token and sign out using the redirect method
// In this case, the access token is stored under the 'myAccessToken' key
var accessToken = await authClient.tokenManager.get('myAccessToken');
authClient.signOut({
revokeAccessToken: true,
postLogoutRedirectUri: window.location.origin
accessToken: accessToken
});
```

### `closeSession()`

Signs the user out of their current [Okta session](https://developer.okta.com/docs/api/resources/sessions) and clears all tokens stored locally in the `TokenManager`. This method is an XHR-based alternative to [signOut](#signout), which will redirect to Okta before returning to your application. Here are some points to consider when using this method:

* Executes in the background. The user will see not any change to `window.location`.
* Will fail to sign the user out if 3rd-party cookies are blocked by the browser.
* Does not revoke the access token. It is strongly recommended to call [revokeAccessToken](#revokeaccesstokenaccesstoken) before calling this method
* It is recommended (but not required) for the app to call `window.location.reload()` after the `XHR` method completes to ensure your app is properly re-initialized in an unauthenticated state.
* For more information, see [Close Current Session](https://developer.okta.com/docs/reference/api/sessions/#close-current-session) in the Session API documentation.

```javascript
// In this case, the access token is stored under the 'myAccessToken' key
var accessToken = await authClient.tokenManager.get('myAccessToken');
authClient.signOut({
accessToken: accessToken,
revokeAccessToken: true,
postLogoutRedirectUri: window.location.origin
});
await authClient.revokeAccessToken(); // strongly recommended
authClient.closeSession()
.then(() => {
window.location.reload(); // optional
})
.catch(e => {
if (e.xhr && e.xhr.status === 429) {
// Too many requests
}
})
```

### `revokeAccessToken(accessToken?)`

Revokes the access token for this application so it can no longer be used to authenticate API requests. By default, `revokeAccessToken` will look for a token object named `accessToken` within the `TokenManager`. If you have stored the access token object in a different location, you should retrieve it first and then pass it here. Returns a promise that resolves when the operation has completed. This method will succeed even if the access token has already been revoked or removed.

### `forgotPassword(options)`

Starts a [new password recovery transaction](https://developer.okta.com/docs/api/resources/authn#forgot-password) for a given user and issues a recovery token that can be used to reset a user’s password.
Expand All @@ -502,7 +522,7 @@ authClient.forgotPassword({
throw 'We cannot handle the ' + transaction.status + ' status';
}
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
```
Expand Down Expand Up @@ -532,7 +552,7 @@ authClient.unlockAccount({
throw 'We cannot handle the ' + transaction.status + ' status';
}
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
```
Expand All @@ -554,7 +574,7 @@ authClient.verifyRecoveryToken({
throw 'We cannot handle the ' + transaction.status + ' status';
}
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
```
Expand All @@ -574,7 +594,7 @@ authClient.webfinger({
.then(function(res) {
// use the webfinger response to select an idp
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
```
Expand All @@ -590,7 +610,7 @@ authClient.fingerprint()
.then(function(fingerprint) {
// Do something with the fingerprint
})
.fail(function(err) {
.catch(function(err) {
console.log(err);
})
```
Expand All @@ -606,7 +626,7 @@ if (exists) {
.then(function(transaction) {
console.log('current status:', transaction.status);
})
.fail(function(err) {
.catch(function(err) {
console.error(err);
});
}
Expand Down
31 changes: 0 additions & 31 deletions THIRD-PARTY-NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -219,37 +219,6 @@ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE

0. You just DO WHAT THE FUCK YOU WANT TO.

q.js
Version (if any):
Brief Description: If a function cannot return a value or throw an
exception without blocking, it can return a promise instead. A promise is an
object that represents the return value or the thrown exception that the
function may eventually provide. A promise can also be used as a proxy for a
remote object to overcome latency. On the first pass, promises can mitigate the
“Pyramid of Doom”: the situation where code marches to the right faster than it
marches forward.
License MIT

Copyright 2009–2014 Kristopher Michael Kowal. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


reqwest
Version (if any): 2.0.5
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"@babel/preset-env": "^7.6.3",
"@babel/register": "^7.6.2",
"dotenv": "^8.1.0",
"eslint-plugin-compat": "^3.3.0",
"eslint-plugin-jasmine": "^2.10.1",
"globby": "^6.1.0",
"lerna": "^2.11.0"
Expand Down
14 changes: 14 additions & 0 deletions packages/okta-auth-js/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": ["plugin:compat/recommended"],
"settings": {
"polyfills": [
"Promise",
"Array.from",
"TextEncoder"
]
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2017
}
}
3 changes: 1 addition & 2 deletions packages/okta-auth-js/jest.server.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var packageJson = require('./package.json');
var OktaAuth = '<rootDir>/' + packageJson.main;
var OktaAuth = '<rootDir>/lib/server/serverIndex.js';

module.exports = {
'coverageDirectory': '<rootDir>/build2/reports/coverage',
Expand Down
7 changes: 3 additions & 4 deletions packages/okta-auth-js/lib/TokenManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@
* See the License for the specific language governing permissions and limitations under the License.
*
*/

/* global localStorage, sessionStorage */
/* eslint complexity:[0,8] max-statements:[0,21] */
var util = require('./util');
var AuthSdkError = require('./errors/AuthSdkError');
var storageUtil = require('./browser/browserStorage');
var Q = require('q');
var constants = require('./constants');
var storageBuilder = require('./storageBuilder');
var SdkClock = require('./clock');
Expand Down Expand Up @@ -115,7 +114,7 @@ function get(storage, key) {
}

function getAsync(sdk, tokenMgmtRef, storage, key) {
return Q.Promise(function(resolve) {
return new Promise(function(resolve) {
var token = get(storage, key);
if (!token || !hasExpired(tokenMgmtRef, token)) {
return resolve(token);
Expand Down Expand Up @@ -152,7 +151,7 @@ function renew(sdk, tokenMgmtRef, storage, key) {
throw new AuthSdkError('The tokenManager has no token for the key: ' + key);
}
} catch (e) {
return Q.reject(e);
return Promise.reject(e);
}

// Remove existing autoRenew timeout for this key
Expand Down
Loading

0 comments on commit 28a83f5

Please sign in to comment.