# Opera Widgets and Ajax: Connect to multiple servers

## Introduction

Scripts on Web pages cannot connect to any Web server other than the one the page was loaded from. This is known as the same-origin security policy and is a cornerstone of keeping the Web safe.

Opera Widgets have a more liberal security model, giving widgets the ability to contact multiple servers and opening up many interesting possibilities. This also opens up some additional potential attack vectors, however, but there are ways around them – you can lock your widgets down and prevent information from being sent to random Web sites. This article describes how to do cross-site Ajax requests inside widgets and gives an example of how it can be used.

## The same-origin security policy

Scripts running in Web pages may only download data from the server the page was loaded from. This is known as the same-origin security policy, and is in place to prohibit malicious scripts from getting or posting potentially sensitive data to other Web sites without the user’s knowledge.

Note that the scripts may have been downloaded from a different server than where the page was downloaded, but the script may still only connect to the server from which the page, the main document, was loaded.

The same-origin security policy of course applies to Ajax applications, which use XMLHttpRequest to read and write data from a Web server.

You can easily try an example out to see how the browser enforces this security policy. The following piece of JavaScript code will use `XMLHttpRequest` to read a Web page from `www.opera.com`:

    var xhr = new XMLHttpRequest ();
    xhr.open( 'GET', 'http://www.opera.com', false );
    xhr.send();

Try this snippet and the browser will execute your script and emit this message in your JavaScript error console:

    Javascript URL thread: "javascript:var xhr = new XMLHttpRequest ();xhr.open( 'GET', 'http://www.opera.com', false );xhr.se..."
    Error:
    name: Error
    message: Security violation

In this case `www.opera.com` is off limits to the script, because this document is not loaded from Opera’s `www` server.

As an additional exercise, re-try the example using the domain name of the server this page was loaded from as an argument to the `XMLHttpRequest` open method.

In order to work around the same-origin security policy, you can set up a service on your own Web server to proxy data to and from other Web servers. The Web page will then be able to indirectly contact multiple servers. Setting this up requires significant work, in particular to avoid misuse of the proxy by others. Widgets offer a way out of this by using only client-side Web technologies.

## The Opera Widgets security model

The Opera Widgets security model allows you to specify to which protocols, hosts, and ports the widget may connect. If no limitations have explicitly been defined, all hosts and ports may be contacted. Access restrictions are specified using the access element in the widgets’s `config.xml` file.

Opera Widgets may thus contact most servers by default. However, accessing file:// urls are not allowed and protocols other than http must be explicitly specified to be accessible.

In order to avoid security problems due to the fact that widgets may connect to multiple servers, each widget has a private cookie and document cache. See the following article on the widget security model for more details of this.

Note: Opera has submitted the widget specification for standardization at the W3C. It is likely that the security model will be changed as part of this work. For example, full network access will most likely be made opt-in.

## How to do cross-site XMLHttpRequests in widgets

No magic is needed to do cross-site `XMLHttpRequest@s in widgets. You just create an @XMLHttpRequest` object and open a connection to the desired host:

    var xhr = new XMLHttpRequest ();
    xhr.onreadystatechange = function () {
        if ( this.readyState == 4 )
        {
            switch ( this.status )
            {
                case 200:
                    handleData(xhr.responseText);
                    break;
                case 400:
                  //...
                //... Handle other cases
            }
        }
    }
    xhr.open( 'GET', 'http://www.opera.com/', false );
    xhr.send();

In this example a request is sent to Opera. The entire page will be available in the `responseText` property of the `xhr` object.

Contacting external servers for data is the cornerstone of many widgets. Examples include getting Web cam images, images from photo galleries, map data, traffic data, weather data, and more. The typical usage is contacting a server with a public XML-based API or scraping Web pages for information.

## Mashup Widgets – doing mashups in the client

Mashup web applications combine information from multiple web sites or servers into new, creative web applications.

Traditionally mashup applications are implemented on a Web server connecting to the source servers. Using Opera Widgets, mashup Web applications can be implemented entirely in the client.

Mashups often make use of data from publicly-available XML APIs from Web sites such as Facebook, Flickr, Google Maps, and so on. A good overview of such APIs can be found at the Programmable Web Web site.

## Other techniques and work

The W3C is doing work on standardizing cross-domain access. In the current draft, this is accomplished by sending special headers to allow a Web server to control what other servers the browser may connect to. See the draft on Access Control for Cross-site Requests for more details.

It is possible to lessen the cross-site security restrictions of most browsers by changing their settings. Versions of Internet Explorer up until version 5 allowed the user to define trusted sites or zones. Ajax calls to these sites would then be possible. Mozilla Firefox allows the user to set the `document.domain` property to a parent domain, allowing the script to access data from different subdomains.

## Resources

- Opera Widgets security model
- Wikipedia entry on Same origin policy.
- Wikipedia entry on XMLHttpRequest.
- Wikipedia entry on Cross-site scripting.
- Wikipedia entry on Mashups.
- Mozilla documentation on the same origin policy.
- Using the XML HTTP Request object, tutorial at jibbering.com.
- Programmable Web
- Access Control for Cross-site Requests, W3C Working Draft.