JavaScript custom resource-request implementation sample

A JavaScript sample for acquiring data from a protected resource by using the MobileFirst WLAuthorizationManager class.

The sample implements a standard OAuth flow: first, a resource request is sent without an access token. This request is expected to fail with an authorization error. Then, WLAuthorizationManager is used to obtain an access token for the resource's protecting scope, and the request is sent again with the obtained access token as an authorization header. The resource request is created by using a standard XMLHttpRequest object.


function sendCustomRequest() {
    sendRequest('http://localhost:3000/v1/apps/1234/test', null)
        .always(
            function(response) {
                alert(response);
            }
        );
}

/**
 * Sends a request with the provided access token to the specified protected-resource URL.
 **/
function sendRequest(url, accessToken) {
    // Use JavaScript promises for asynchronous operations
    var dfd = WLJQ.Deferred();

    // Create the custom resource request
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);

    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            var status = xhr.status;
            if (status >= 200 && status <= 299) {
                dfd.resolve(xhr.responseText);
            }
            else {
                var headers = xhr.getAllResponseHeaders();

                // Check whether access to the resource requires authorization
                if (WLAuthorizationManager.isAuthorizationRequired(status, headers)) {
                    if (status === 409) { // Server-conflict error
                        // Resend the request
                        sendRequest(url, accessToken)
                            .then(
                                function(response) {
                                    dfd.resolve(response);
                                },
                                function(error) {
                                    dfd.reject(error);
                                }
                            );
                    } else if (status === 401) { // Invalid access token, or no access token
                        // Check whether the access token is invalid
                        if (isInvalidTokenError(xhr)) {
                            // Clear the invalid access token
                            WLAuthorizationManager.clearAccessToken(accessToken).always(
                                function() {
                                    // Obtain a valid access token and resend the request
                                    resendWithAccessToken(null);
                                });
                        } else {
                            // Obtain a valid access token and resend the request
                            resendWithAccessToken(null);
                        }
                    } else { // status = 403 - insufficient-scope error
                        // Get the resource scope from the response
                        var scope = WLAuthorizationManager.getResourceScope(headers);
                        // Obtain an access token for the scope
                        resendWithAccessToken(scope);
                    }
                } else { // Unexpected error
                    dfd.reject("Failure - received response " + xhr.responseText);
                }
            }
        }
    };

    // If an access token was obtained, add the token to the request as an authorization header
    if (accessToken !== null) {
        xhr.setRequestHeader("Authorization", accessToken.asAuthorizationRequestHeader);
    }

    xhr.send();

    return dfd.promise();


    function resendWithAccessToken(scope) {
        WLAuthorizationManager.obtainAccessToken(scope)
            .then(
                function(accessToken) {
                    // The access token was obtained successfully.
                    // Construct the request again, and add the access token as an authorization header
                    sendRequest(url, accessToken)
                        .then(
                            function(response) {
                                dfd.resolve(response);
                            },
                            function(error) {
                                dfd.reject(error);
                            }
                        );
                },
                function(error) {
                    // Failed to obtain an access token. Reject the request.
                    dfd.reject(error);
                }
            );
    }
}

function isInvalidTokenError(xhr) {
    var authHeader = xhr.getResponseHeader('WWW-Authenticate');
    return (authHeader.indexOf("invalid_token") >= 0);
}