# byu-wabs

##### Table of Contents

- [About WABS](#about-wabs)
- [Getting Started](#getting-started)
- [Server Middleware](#server-middleware)
- [Client Script](#client-script)
- [Release Notes](#release-notes)

## About WABS

The Web Application Bootstrap Service (WABS) is a [NodeJS](https://nodejs.org/en/) [Express](https://expressjs.com/) [middleware](http://expressjs.com/en/guide/using-middleware.html) that provides a useful set of common tools, such as:

- CAS Authentication
- WSO2 Authorization
- Interoperability with Legacy Applications
- Integrates with [byu-browser-oauth](https://github.com/byuweb/byu-browser-oauth)

### CAS Authentication

WABS uses CAS to make sure that the user is correctly signed in when they should be and signed out when they should be.

BYU's Central Authentication System (CAS) is used to establish user identity. CAS offers single sign-on, so if a user signs into one application that uses CAS authentication then goes to another application that uses CAS authentication then they could already be signed into the second application. CAS also offers single sign-out, causing a sign out of CAS in one application to sign out everyone.

Unfortunately not all of BYU's web applications properly support CAS's single sign-on, sometimes requiring the user to click the "Sign In" button even if they are already signed in. Additionally, no BYU web applications currently support single sign-out.

### WSO2 Authorization

BYU uses OAuth 2 and WSO2 to allow your application and it's users to access internal BYU web services. WABS provides tools to simplify the WSO2 authorization process. Additionally WABS will automatically manage OAuth tokens, refreshing tokens when necessary.

A problem that WABS solves with WSO2 is the authenticated user synchronization issue. A times WSO2 may believe erroneously that the signed in user is one person when it is actually another. (This issue can occur if two people are using the same computer.) WABS fixes this issue by making sure that the user's CAS identity matches their WSO2 identity and forcing an update in the case where they do not match.

### Legacy Applications

Many of BYU's legacy applications require state to be maintained on a per tab (not per browser) basis. This data was stored into what became known at BYU as a brownie. Because there was no way to maintain tab specific data prior to browser's [session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage), BYU used HTML forms to POST the tab specific information from one page to the next.

WABS will automatically receive brownies and send brownies in a way that is compliant with legacy applications. Additionally it uses session storage to store data per tab, automatically determining when that data is no-longer valid, and clearing it.

*[Table of Contents](#table-of-contents)*

## Release Notes

### 8.1.0

- Replaces the server-side refresh-token cookie encryption helpers with a Node-compatible AES-256-GCM implementation.
- New encrypted refresh-token cookie values use the `wabs-gcm-v1` format.
- Existing refresh-token cookies encrypted by earlier versions are not decrypted by this release. Affected users may need to log in again once after upgrading.

*[Table of Contents](#table-of-contents)*

## Getting Started

To run your application using WABS you first need to set a few things up:

1. [Create a WSO2 Application](#create-a-wso2-application)
2. [Create a WABS Configuration](#create-a-wabs-configuration)
3. [Add WABS Middleware to Your Server](#add-wabs-middleware-to-your-server)

### Create a WSO2 Application

You may need to get access to create a WSO2 application. Contact OIT if this is the case.

1. Visit https://api.byu.edu/store.
2. Select the link [My Applications](https://api.byu.edu/store/site/pages/applications.jag).
3. Fill out the form to add a new application. The `callbackURL` should be set to your domain name. For example, if you are developing locally on port 3000 then the `callbackUrl` should be `http://localhost:3000/`.
4. Save the WSO2 application.
5. Select the link [My Subscriptions](https://api.byu.edu/store/site/pages/subscriptions.jag).
6. From the drop down menu select your newly created application.
7. Click the button to generate keys for your application.
8. You will need your `Consumer Key` and `Consumer Secret` values for the WABS configuration.

### Create a WABS Configuration

If you plan to use authentication / authorization then you have two options:

1. **Recommended option:** [Store the configuration in the AWS parameter store](#in-the-aws-parameter-store).

2. Easy option: [Create a JSON file outside of your project directory](#in-a-configuration-file) that contains the protected configuration properties.

These are all of the options you can use with a WABS configuration:

| Option           | Type | Description                                                                                                                                                                                                                                              | Default |
|------------------| ---- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------- |
| appName          | `String` | **\[ REQUIRED \]** The name of the application. This value must be unique to your application. This can consist of letter, numbers, underscore and dash.                                                                                                 | |
| awsParameterName | `String` | The name of the AWS parameter store parameter to read additional configuration options from.                                                                                                                                                             | [Default AWS Parameter Name](#default-aws-parameter-name)</sup> |
| awsSsmConfig     | `Object` | A configuration to pass to the AWS SDK SSM constructor.                                                                                                                                                                                                  | `{ region: 'us-west-2' }` |
| casCallbackPath  | `String` | The path to redirect the browser to after CAS authentication. This value should match the path that your WABS `init` middleware is running from.                                                                                                         | `/` |
| configFile       | `String` | A file path to read additional configuration options from.                                                                                                                                                                                               | |
| consumerKey      | `String` | The WSO2 consumer key. <sup>[2](#protected-configuration-options)</sup>                                                                                                                                                                                  | |
| consumerSecret   | `String` | The WSO2 consumer secret. <sup>[2](#protected-configuration-options)</sup>                                                                                                                                                                               | |
| encryptSecret    | `String` | A seed to use to encrypt your applications sensitive information. **This must be a string of at least 40 characters in length.** <sup>[2](#protected-configuration-options)</sup>                                                                        | |
| hardTimeout      | `Number` | The maximum number of minutes to allow someone to be logged into your application.                                                                                                                                                                       | `600` |
| host             | `String` | The protocol, domain, and port used to get to your server. For example: `http://localhost:3000`. Generally this value can be determined automatically, but if you are having issues when people try to log in then you can try to set the host manually. | |
| apiHost          | `String` | The hostname of the API Manager used for authentication.                                                                                                                                                                                                 | |
| openProxy        | `Boolean` | Whether to allow the web browser to indiscriminately proxy web service requests through the server, using the server's identity to communicate with web serves.                                                                                          | `false` |
| reservedPath     | `String` | A reserved path that the init middleware uses.                                                                                                                                                                                                           | `"/__wabs"` |
| wso2CallbackPath | `String` | The path to redirect the browser to after WSO2 authorization. This value must match the path (excluding protocol, domain, and port) that you specified when creating your WSO2 application.                                                              | `/` |

###### Default AWS Parameter Name

The default value for `awsParameterName` is derived from a combination of the `appName`, the environment (defined by the environment variables `NODE_ENV` or `HANDEL_ENVIRONMENT_NAME`, defaulting to `"dev"`), and the suffix `"WABS_CONFIG"` joined by dots (`.`). For example if your app is named `"my-app"` and no environment is specified then this value will default to `"my-app.dev.WABS_CONFIG"`.

###### Protected Configuration Options

The consumer key, consumer secret, and encrypt secret are all required if your application uses authentication / authorization. Mechanisms are in place to prevent you from putting your consumer key, consumer secret, and encrypt secret in unsafe locations. <span style="font-weight: bold; color: red">NEVER STORE YOUR WSO2 CLIENT ID, WSO2 CLIENT SECRET, OR ENCRYPT SECRET IN YOUR CODE OR WITHIN YOUR APPLICATION DIRECTORY.</span>

#### Where to Put the Configuration

If you plan to use authentication and authorization with your application then the `consumerKey`, `consumerSecret`, and `encryptSecret` cannot be stored within your code or within a configuration file that resides within in your project directory. You can store the `consumerKey`, `consumerSecret`, and `encryptSecret` in a configuration file outside of your project directory or in an AWS Parameter store.

##### In Your Code

Within your code you can specify the `appName`, `awsConfig`, `awsParameterName`, `casCallbackPath`, `configFile`, `hardTimeout`, `host`, and `wso2CallbackPath`. This excludes only the `consumerKey`, `consumerSecret`, and `encryptSecret` which, if you attempt to include, will throw an error due to security concerns.

###### Define with App Name Only

```js
const Wabs = require('byu-wabs');
const middleware = Wabs('my-app-name'); // shortcut for defining just the app name
```

###### Define with Configuration File Path

The file path must include a path delimiter to be recognized as a path. This path cannot exist within your application directory or an error will be thrown.

```js
const Wabs = require('byu-wabs');
const middleware = Wabs('/path/to/config.json');
```

###### Define with Configuration

```js
const Wabs = require('byu-wabs');
const middleware = Wabs({
    appName: 'my-app-name',
    awsParameterName: 'my-app-param-name',
    awsSsmConfig: { region: 'us-west-2' },
    casCallbackPath: '/',
    configFile: '/path/to/config.json',
    hardTimeout: 600,
    host: 'http://localhost:3000',
    wso2CallbackPath: '/'
});
```

##### In the AWS Parameter Store

**This is the recommended method for storing your configuration.** By keeping this configuration in a central location other developers can also work on your code without having to acquire the secure configuration of your app.

The name of this parameter can be specified in the middleware configuration using the `awsParameterName` option. Alternatively it will use the [default name](#default-aws-parmeter-name).

Create a parameter in the AWS Parameter Store that has a value that is a JSON string containing all configuration options you'd like to store on AWS. Tell your configuration in code to use that parameter name.

###### server.js

```js
const Wabs = require('byu-wabs');
const middleware = Wabs('my-app-name');
```

###### parameter store

Assuming that the environment has not been set, because the `awsParameterName` has not been set, the default will be used with is derived to `"my-app-name.dev.WABS_CONFIG"`<sup>[1](#footnote1)</sup>

```text
my-app-name.dev.WABS_CONFIG = { "consumerKey": "<consumer-key>", "consumerSecret": "<consumer-secret>", "encryptSecret": "<encrypt-secret>" }
```

##### In a Configuration File

Due to security concerns, the configuration file must reside outside of your project directory. Any configuration option can be specified in this file but may be overwritten by configuration settings made in the application code. In other words, if you specify an option here that is already specified in the application code then the application code will take precedence.

###### server.js

```js
const Wabs = require('byu-wabs');
const middleware = Wabs('/path/to/config.json');
```

###### /path/to/config.json

```json
{
    "appName": "my-app-name",
    "awsParameterName": "my-app-param-name",
    "awsSsmConfig": { "region": "us-west-2" },
    "casCallbackPath": "/",
    "consumerKey": "<consumer-key>",
    "consumerSecret": "<consumer-secret>",
    "encryptSecret": "<encrypt-secret>",
    "hardTimeout": "600",
    "host": "http://localhost:3000",
    "wso2CallbackPath": "/"
}
```

*[Table of Contents](#table-of-contents)*

### Add WABS Middleware to Your Server

You'll need to be familiar with [Express Middleware](http://expressjs.com/en/guide/using-middleware.html) to understand this section.

WABS is a middleware that you can use to add functionality to your server. That functionality includes the mechanisms for authentication, authorization, token management, and interoperability with legacy code.

```js
// get dependencies
const cookieParser  = require('cookie-parser');
const express       = require('express');
const path          = require('path');
const wabs          = require('byu-wabs')('my-app-name');

// create the express app
const app = express();

// must parse cookies before wabs.init
app.use(cookieParser(wabs.config.encryptSecret));
app.use(wabs.init());

// serve index.html and static files
const publicDirectoryPath = '/path/to/app/public';
app.use(wabs.index({ render: publicDirectoryPath + '/index.html' }));
app.use(express.static(publicDirectoryPath))

// start listening for requests
app.listen(3000, function(err) {
    if (err) return console.error(err.stack);
    console.log('Server listening on port: 3000');
});
```

At this point you are ready to start your application and open a browser.

*[Table of Contents](#table-of-contents)*

## Server Middleware

This section covers the middlewares bundled with WABS and how to use them. It does not cover details about configuring the WABS instance. For that information check out the [Getting Started](#getting-started) section.

##### Middleware Table of Contents

- [authenticated](#authenticated) - An mid-route middleware for ensuring the user is authenticated.
- [brownie](#brownie) - Run brownie receiving and parsing middleware.
- [clientGrantProxy](#clientgrantproxy) - Middleware for proxying client requests.
- [index](#index) - Middleware for keeping authentication in sync and loading the index.html file.
- [init](#init) - A required initialization middleware.
- [login](#login) - A middleware for creating a login endpoint.
- [logout](#logout) - A middleware for creating a logout endpoint.
- [sync](#sync) - A middleware for synchronizing the current authentication / authorization state.

### authenticated

The authenticated middleware can be run mid route to ensure that a user is either authenticated or forbidden from accessing the route. Useful if you don't want a user to to access a protected route without being authenticated.

**Parameters**

- *options* - A configuration object.

    - *authenticate* - Whether to redirect the user to authenticate if they are not logged in. This can only occur for GET requests. Defaults to `false`.

**Returns** a middleware function.

```js
app.get('/protected', wabs.authenticated(), function(req, res) {
    res.send('Protected data');
});
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### brownie

This middleware provides legacy application interoperability where brownies are in use by listening for `POST` requests. If a `POST` is received then this middleware will read the body and attempt to decode it as a brownie payload.

**Parameters**

None

**Returns** a middleware function.

```js
app.use(wabs.brownie());
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### clientGrantProxy

The clientGrantProxy middleware can be used to proxy requests from the browser and use OAuth 2's client grant credentials to access a web service on another server. Note that client grant credentials are tied to your application and do not contain any information about the user, therefore it is best to use this as a proxy for endpoints where the user does not need to be authenticated.

**Parameters**

- *requestOptions* - A `Function` or a `String`.

    If a `Function` then the function will be called with the current request object as it's parameter. The function should return an object that will be passed to the [request (v2)](https://www.npmjs.com/package/request) module.

    If a `String` then this value will be used as the base URL for the request and the rest of the request will be forwarded to proxied endpoint.

**Returns** a middleware function.

In the following examples a request to `"/my-proxy-path/abc/123"` for this endpoint would proxy to `"https://api.byu.edu/my-endpoint/abc/123"`:

```js
app.use('/my-proxy-path', wabs.clientGrantProxy('https://api.byu.edu/my-endpoint'));
```

```js
app.use('/my-proxy-path', wabs.clientGrantProxy(function(req) {
    return {
        baseUrl: 'https://api.byu.edu/my-endpoint',
        body: req.body || '',
        headers: Object.assign({}, req.headers),
        method: req.method,
        qs: Object.assign({}, req.query),
        url: req.path
    }
});
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### index

This middleware is used to produce the index.html file, to receive brownies, and to synchronize authentication / authorization.

**Parameters**

- *options* - A configuration object.

    - *brownie* - A `Boolean` that is set to `true` to allow reception and decoding of brownies. Defaults to `true`.

    - *injectScript* - A `Boolean` that if set to `true` will inject the `<script>` tag into your `index.html` file that will cause the WABS client script to be downloaded.

    - *ignore* - A array of strings or regular expressions (`Array.<String|RegExp>`) or a `Function`.

        If `Array.<String|RegExp>` then each item in the array will be compared to the request path and if found to be a match will cause the index.html not to be returned.

        If a `Function` then the function will receive the current path and should return `true` if the path should not return the index.html.

    - *render* - REQUIRED. A `String` or a `Function`.

        If a `String` then this should be the file path to your index.html file.

        If a `Function` then the function will be called with two parameters: 1) request and 2) a callback function. The callback function should be called with two parameters: 1) the error (if any), 2) the final HTML content to send as your index.html content.

    - *sync* - A `Boolean` that if set to `true` will get the latest authentication / authorization before loading the index.html content. This behavior is recommended if you're building a single page app.

**Returns** a middleware function.

```js
app.use(wabs.index({ render: '/path/to/index.html' });
```

```js
app.use(wabs.index({
    render: function(req, callback) {
        const content = '<html><body>Hello, World!</body></html>';
        callback(null, content);
    }
});
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### init

This middleware must execute before any other wabs middleware.

**Parameters:** None

**Returns** a middleware function.

```js
app.use(wabs.init());
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### login

This middleware can be used to define a login endpoint. This middleware is not necessary if you only plan to use the client side script `wabs.auth.login()`.

**Parameters**

- *options* - An optional configuration object.

    - *failure* - A URL to redirect to if the login fails. This can be overwritten if the incoming request has a `failure` query parameter. Defaults to success value.

    - *gateway* - Whether to use the CAS gateway. Using the gateway will check to see if the user is logged in but will not display the login form if they are not logged in. This can be overwritten if the incoming request has a `gateway` query parameter set to `"true"` or `"false"`. Defaults to `false`.

    - *query* - An optional object for adding additional query parameters to the CAS login URL.

    - *success* - A URL to redirect to if the login success. This can be overwritten if the incoming request has a `success` query parameter. Defaults to `"/"`.

    - *wso2* - Whether the browser should be redirected to WSO2 after successful CAS authentication. Defaults to `true`.

**Returns** a middleware function.

```js
app.use('/login', wabs.login());
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### logout

This middleware can be used to define a logout endpoint. This middleware is not necessary if you only plan to use the client side script `wabs.auth.logout()`.

**Parameters**

- *options* - An optional configuration object.

    - *cas* - Set to `true` to have this middleware also log out of CAS. Defaults to `true`.

    - *cFramework* - Set to `true` to have this middleware also log out of the C-Framework. Defaults to `true`.

    - *redirect* - The URL to redirect to after logout. This value can be overwritten if the incoming request has a `redirect` query parameter. Defaults to `"/"`.

    - *wso2* - Set to `true` to have this middleware also log out of WSO2. Defaults to `true`.

**Returns** a middleware function.

```js
app.use('/logout', wabs.logout());
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

### sync

Middleware that will transparently redirect the request through CAS and WSO2 to get the latest authentication and authorization data.

**Parameters** None

**Returns** a middleware function.

In this example when the browser navigates to `"/some/path"` it will be redirected to CAS and WSO2 prior to calling the `routerHandler` function. This will help ensure that the current user's authentication and authorization is up to date.

```js
app.get('/some/path', wabs.sync(), function routeHandler(req, res) {
    // ...
});
```

*[Table of Contents](#table-of-contents)* | *[Middleware Table of Contents](#middleware-table-of-contents)*

## Client Script

The WABS client script is automatically added to your index file (immediately before your first script tag) when requested by a browser. This script file will finish executing prior to the execution of any of your scripts. If you have set either the `NODE_ENV` or `HANDEL_EVIRONMENT_NAME` to a value other than `"dev"` then this script will be minified. It provides the following functionality:

- Automatic synchronization of authenticated status between other WABS applications.
- Automatically refreshes the authenticated user's OAuth access token before expiration.
- Provides functionality to manually manage authentication and authorization.
- Easy access to get or set the brownie.
- Automatic re-encoding of the brownie.
- Automatic and manual sending of the brownie.
- Fires events for important changes in state.

##### Client Script Table of Contents

- [Events](#events) - Subscribe to events to keep your app authorization / authentication synchronized.
- [byu.ajax](#byuajax) - A small AJAX helper function
- [byu.auth.accessToken](#byuauthaccesstoken) - A getter for the current access token.
- [byu.auth.expires](#byuauthexpires) - A getter for the current access token expiration date.
- [byu.auth.login](#byuauthlogin) - A function to initiate a login.
- [byu.auth.logout](#byuauthlogout) - A function to initate a logout.
- [byu.auth.proxy](#byuauthproxy) - A function to make proxied AJAX requests that will use the WSO2 client grant token for authorization.
- [byu.auth.refreshToken](#byuauthrefreshtoken) - A function to refresh the access token.
- [byu.auth.request](#byuauthrequest) - A wrapper around [byu.ajax](#byuajax) that adds the code grant access token to the request and automatically retries if the token has expired.
- [byu.auth.sync](#byuauthsync) - A function to perform a authorization / authentication synchronization.
- [byu.navigateTo](#byunavigateto) - A function to POST brownie data to another page.
- [byu.user](#byuuser) - The currently logged in user.

### Events

WABS will emit events that can be captured at the document level:

```js
<script>
    document.addEventListener('wabs-auth-login', function(event) {
        console.log('User logged in: ' + byu.user.netId);
    });
</script>
```

These are the emitted events:

- **wabs** - This event will be emitted immediately after any other events. It can be used to capture all WABS events. The event `detail` property will contain the `name` of the original event as well as its `data`.

    ```js
    <script>
        document.addEventListener('wabs', function(event) {
            console.log('Event name: ' + event.detail.name);
            console.log('Event data: ' + event.detail.data);
        });
    </script>
    ```

- **wabs-auth-login** - Ths event is emitted when a user is authenticated. The access token may or may not be available at this point, but the event `detail` will tell whether or not it is `gettingAccessToken`. If set to false you may want to call `byu.auth.login()` which will begin the process of getting the accessToken.

    ```js
    <script>
        document.addEventListener('wabs-auth-login', function(event) {
            if (!event.detail.gettingAccessToken) byu.auth.login();
        });
    </script>
    ```

- **wabs-auth-logout** - This even is emitted when the user loses authentication.

    ```js
    <script>
        document.addEventListener('wabs-auth-logout', function() {
            console.log('User logged out');
        });
    </script>
    ```

- **wabs-access-token-update** - This event is emitted when the access token changes. That could mean there is a new access token or none at all.

    ```js
    <script>
        document.addEventListener('wabs-access-token-update', function() {
            console.log('New access token: ' + byu.auth.accessToken);
        });
    </script>
    ```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.ajax

A simple AJAX wrapper. If you're not using IE11 then just use [JavaScript fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). Also, this function a light AJAX implementation and is not intended to solve every use case, although it will work for most.

**Signature** `byu.ajax(options [, callback ])`

**Parameters**

- *options* - A `string` or an `Object` the defines the request. If a `string` then the value will be used as the request URL and all other default values will be kept. If an `Object` then the following properties can be set.

    - *body* - A `string` or an `Object`. If an `Object` then the value will automatically be serialized for transmission and the headers for `Content-Type` will automatically be set to `application/json`.

    - *headers* - An `Object.<string,string>` with name value pairs where the name represents the header name and the value is the header value. All header names will automatically be converted to lower case.

    - *method* - The HTTP method to use. Defaults to `"GET"`.

    - *url* - The URL to send the request to. This value is required.

- *callback* - An optional function to call once the request has completed. This function will receive the parameters: 1) body and 2) statusCode.

**Returns** The `XMLHttpRequest` instance that sent the request if the callback is provided or a promise if the callback parameter was omitted. The promise resolves to an object with the properties `body` and `status`.

```js
byu.ajax('http://someurl.com/', function(body, code) { ... });

byu.ajax({
    method: 'POST',
    url: 'http://someurl.com',
    headers: {
        'x-header': 'value'
    },
    body: {
        propertyName: 'propertyValue'
    }
}, function(body, code) { ... });
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.accessToken

Get the WSO2 access token for the authenticated user. Just because a user is authenticated doesn't mean that they also have an access token although most often they will.

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.expires

Get the date that the WSO2 access token expires.

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.login

Initialize a login sequence by redirecting the browser through the CAS login screen and the WSO2 authorization page.

**Signature** `byu.auth.login([ success ,] options ])`

**Parameters**

- *success* -The URL to navigate to after successful login. This parameter can be omitted while still providing the options parameter. Defaults to the current page URL.

- *options* - A `String` or an `Object`. If a `String` then this represents the URL to navigate to if authentication fails. If an `Object` then it has the following properties:

    - *failure* - The URL to navigate to if authentication fails. Defaults to the `success` URL value.

    - *popup* - Whether to use a popup window for login. Defaults to `false`.

**Returns** `undefined`

**Example**

```html
<button onclick="byu.auth.login()">Sign In</button>
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.logout

Initialize a logout sequence. This attempts to be a single sign-out as much as possible by logging out of CAS, WSO2, cFramework applications, and other WABS applications.

**Signature** `byu.auth.logout([[ redirect ,] options ])`

**Parameters**

- *redirect* - The URL to navigate to after logout. This parameter can be omitted while still providing the options parameter. Defaults to the current page URL.

- *options* - An object that specifies which services to log out of.

    - *cas* - Log out of CAS. Defaults to `true`.

    - *cFramework* - Log out of the cFramework. Defaults to `true`.

    - *popup* - Cause the log out to happen via a popup window (will not allow logging out of the cFramework). Defaults to `false`.

    - *wso2* - Log out of WSO2. Defaults to `true`.

**Returns** `undefined`

**Example**

```html
<button onclick="byu.auth.logout()">Sign Out</button>
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.proxy

Make an AJAX request that is proxied by the server. The server will add its own access token to the request.
Note that calling this function will not work unless the option `openProxy` on the constructor is set to `true`.

**Signature** `byu.auth.proxy( options [, callback ])`

**Parameters**

- *options* - A `String` or an `Object`. If a `String` then the request will use the value as the URL and all other options will be default values.

    - *body* - The body to send with the request.

    - *method* - The http method to use. Defaults to `"GET"`.

    - *headers* - An `Object` with name value pairs.

    - *url* - **REQUIRED** The URL to proxy against.

- *callback* - A callback to call when the request completes. The callback receives the response body and status code.

**Example**

```js
byu.auth.proxy('https://api.byu.edu/some/api', function(body, status) {
    console.log(body, status);
});
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.refreshToken

Manually refresh the WSO2 access token.

**Signature** `byu.auth.refreshToken([ callback ])`

**Parameters**

- *callback* - The function to call once the refresh request has completed.

**Returns** `undefined`

**Example**

```js
byu.auth.refreshToken(function(body, status) {
    console.log(body, status, byu.auth.accessToken);
});
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.request

Make an AJAX request that automatically adds the user's access token to the authorization header. The user *MUST* be logged in for this function to work. If the response for the request indicates an invalid access token then the access token is automatically refreshed and one more attempt is made.

**Signature** `byu.auth.request( options [, callback ])`

**Parameters**

- *options* - A `String` or an `Object`. If a `String` then the request will use the value as the URL and all other options will be default values.

    - *body* - The body to send with the request.

    - *method* - The http method to use. Defaults to `"GET"`.

    - *headers* - An `Object` with name value pairs.

    - *url* - **REQUIRED** The URL to proxy against.

- *callback* - An optional callback to call when the request completes. The callback receives the response body and status code. If omitted then a promise will be returned.

**Returns** A promise if the callback parameter was omitted. The promise resolves to an object with the properties `body` and `status`.

**Example**

```js
byu.auth.request('https://api.byu.edu/some/api', function(body, status) {
    console.log(body, status);
});
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.auth.sync

Synchronize the current authentication and authorization state. This will cause a popup window to appear briefly that will check with CAS for current authentication and will go through WSO2 to acquire the latest access token.

This function will be called automatically if any other WABS application signs in our out.

**Signature** `byu.auth.sync([ callback ])`

**Parameters**

- *callback* - If provided, the callback will be called after synchronization has completed and it will receive two paramters: 1) the current user, 2) the current access token.

**Returns** `undefined`

```js
byu.auth.request('https://api.byu.edu/some/api', function(user, accessToken) {
    if (user) {
        console.log('User logged in: ' + user.netId);
    } else {
        console.log('User not logged in.');
    }
});
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.navigateTo

Navigate while posting current brownie data to the receiving URL. Note that any links (`<a>`) with a target of `_blank` or that go to a C-Framework application will automatically call this function.

**Signature** `byu.navigateTo( url [, target [, callback ] ])`

**Parameters**

- *url* - The URL to navigate to.

- *target* - The window target to cause to navigate. Defaults to `_self`.

- *callback* - A function to call immediately prior to navigation. If an error occurs then this function will receive that error as its first parameter.

**Returns** `undefined`

```js
byu.navigateTo('https://myapp.byu.edu');
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*

### byu.user

Get the currently authenticated user. If not authenticated then this value will be `null`.

```js
console.log(byu.user);
```

*[Table of Contents](#table-of-contents)* |
*[Client Script Table of Contents](#client-script-table-of-contents)*
