Capability URLs grant access to a resource to anyone who has the URL. There are times when this is useful, for example one-shot password reset URLs, but overuse can be problematic as URLs cannot generally be kept secret. This document provides some good practices for web developers who wish to incorporate capability URLs into their applications.

This is a proposed Working Draft, towards a TAG Finding.

Introduction

There are two broad methods of controlling access to information that is published on the web:

  1. the server can have access control measures that require people accessing the content to provide the correct token(s) (such as a password) before the content is accessible
  2. the information can be published at an obscure or unguessable URL, and links to it only provided to people who have permission to access it

The URLs used in the second method are known as "capability URLs": an agent who possesses the URL is given the capability to access the information.

This document describes:

Example Capability URLs

Capability URLs are in widespread use. This section contains examples from the web where capability URLs are used.

Password Resets

When a user forgets their password to access a site, the site cannot simply tell them what their password is as this would require the site to store and transmit their password as plain text, which is extremely insecure.

The pattern that is usually used instead is that the user is sent an email that contains a link that provides the user who has received that link with enough permissions to reset their password. This example is from Dropbox:

  				Your Dropbox password recently expired. You can reset it here.
  			

In this case the capability URL is https://www.dropbox.com/l/Q8eJH22ft0ckDJDeff1Do10/password_reset. Anyone accessing this link is able to change the password for the user with whom the capability URL is associated.

Second Life

Reg API capabilities represent permissions to perform certain actions.
Using capability URLs – Linden Lab Official:Registration API

Within the Second Life API, user agents aren't required to provide credentials with each action that they wish to take. Instead, they submit a single form with a username and password and the response contains a set of capability URLs for different capabilities. For example:

<llsd>
  <map>
    <key>create_user</key>
    <string>https://cap.secondlife.com/cap/0/35ff3b8c-a30d-4d18-b29a-e3f7f6c79cb6</string>
 
    <key>check_name</key>
    <string>https://cap.secondlife.com/cap/0/6e528ba1-a8b0-4f6b-8b56-362ee6f5cef8</string>
 
    <key>get_last_names</key>
    <string>https://cap.secondlife.com/cap/0/be4e4d2e-c00a-46cd-bb8d-d17cb8e92c9b</string>
 
    <key>get_error_codes</key>
    <string>https://cap.secondlife.com/cap/0/e75f81a5-b7da-4480-8f95-b1cf9d2d680f</string>
  </map>
</llsd>
        

The documentation provides two guidelines for using these capability URLs:

  • Do not hard-code your capabilities URLs. Either code your capabilities URLs as constants, or better yet, obtain them at run-time. Capability URLs will expire eventually, so fresh ones are always better.
  • Keep your capability URLs secret! The capabilities granted to you are only meant for you. A capability URL is sensitive much like a password. Moreover, Linden Lab tracks the use of each capability.
Using capability URLs – Linden Lab Official:Registration API

Google Calendar

Google Calendar provides Private Addresses for XML and iCalendar formats of a calendar. These can be used by anyone within a feed reader or a calendar programme to provide access to the calendar, but users are warned "Your calendar's Private Address was designed for your use only, so be sure not to share this address with others." (from About the 'Private Address').

The help associated with Private Addresses similarly warns against sharing the URLs with others:

Help box reading 'Your calendar's Private Address is designed for your use only. All of your calendar information is available via your private links, so don't share this address with others. To change your Private Address and disable any previous access, click the Reset Private URLs link.'
Help associated with Private Address in Google Calendar

Github Gists

GitHub Gists support sharing and discussing versioned code and other files with other people. These can be created anonymously, and can be kept private. Access to private Gists is provided simply through sharing the URL for the Gist.

Gist page with a pop-up explaining 'Secret gists are hidden from search engines but visible to anyone you give the URL.'
A secret GitHub Gist

Doodle polls

Doodle enables users to create polls that can be accessed through URLs without users logging in. The URLs are provided to the administrator of the poll within the browser and through email. For example:

Doodle page providing URLs with a Participation link saying 'Send this link to anyone you wish to invite.' and an Administration link saying 'Access this link to change, close or delete this poll.'
Doodle page for a new poll

Flickr images

Private images on Flickr can be shared through Guest Passes which are generated for a given image on demand.

Flickr dialog saying 'Grab the link' for a Guest Pass and inviting the user to visit the Guess Pass History.
Flickr dialog for a new Guest Pass

Users can view the Guest Pass History which provides the option of expiring the current Guest Pass for the image.

Portion of a Guest Pass History on Flickr, showing the option to Expire the Guest Pass.
Flickr Guest Pass History

Reasons to Use Capabilty URLs

There are three rationales for using capability URLs evident in the examples described above.

No Login Required

A capability URL enables a user to access a service without having a login or password on that service. There are three situations where that is a particular advantage:

Forgotten Passwords

Users frequently forget their passwords, especially when their form is restricted based on length or types of characters that they contain. Sending a URL to users who forget their passwords is preferable to sending a password because:

  • sending a password would require the website to send (and possibly store) the password in plain text, which is a bad security practice
  • the capability URL can be disabled after it has been accessed, which means that even if the email or URL is shared later on, it doesn't provide ongoing access to the account
  • the capability URL can resolve to a page that forces the user to reset their password; if users were simply presented with a password or granted access to the entire system with the URL then they might not remember to reset their password

Low Friction Accounts

There are a proliferation of web-based services which provide for user accounts, to help record user preferences and history. Creating another user account can become a high burden for users, particularly when they don't expect to use the account very frequently.

Web-based applications that do not require user information in order to function may enable users to access the service without creating an account, or only prompt the user to create an account after they have used the service for a while.

Using capability URLs is beneficial to the more regular users of a web-based application because it enables them to collaborate with other people who are not regular users of the service. Regular users can create a resource and share a URL for that resource with their potential collaborators through another route (eg through email).

Capability URLs that are used to facilitate collaboration without requiring accounts are generally controlled by a regular user, who might wish to:

  • create different capability URLs for different people or groups that they wish to collaborate with
  • create different capability URLs for different types of action that they wish to permit on a resource (eg editing or commenting or viewing)
  • be able to revoke permissions for given capability URLs if they learn they have been shared outside the intended group

Websites without Accounts

Account management is seldom the main goal of a web-based application. Although it can be relatively easy for developers to plug in account management, there is an overhead involved: it can raise security concerns, and has legal implications because it involves storing personal data.

In some applications there is no risk of someone else deleting important work belonging to another user. This might be because the web application is not used to do important work. Or it might be that the application does not support destructive acts.

In these cases, it may be that the developer of a web application chooses to use capability URLs rather than supporting user accounts, letting them focus development on the main purpose of the application rather than account management.

Easy Onward Sharing

A second set of reasons for supporting capability URLs is that it enables those with whom access is originally shared to continue to share that access with their own network.

For example, if a user is trying to arrange a meeting between organisations, they might not know all the people who should attend the meeting from other organisations. Under a normal account-based method, the user would typically have to gather the information about who should attend the meeting before granting each of those individuals access to the system. With a capability URL, they only have to share the URL with a representative from each organisation, and trust that representative to pass on the URL to whichever colleagues need to take part.

Capability URLs can thus enable permissions to flow through networks more easily than they can with an account-based system.

Easy Client API

Authentication can be burdensome in HTTP APIs because HTTP is a stateless protocol and requires authentication tokens to be passed and processed on each transaction. This takes up both bandwidth and processing power, which can be a significant overhead for frequent, small, messages.

Capability URLs can be used instead. Clients:

  1. perform authentication as normal
  2. request a list of capability URLs to use for the rest of the session
  3. use those URLs without authentication

This removes the authentication cost on each transaction while keeping the exchanges fairly secure.

There are larger issues here about using HTTP for frequent, small, messages. Arguably, HTTP isn't an appropriate protocol in these circumstances, or other workarounds such as long polling or pipelined requests would work better.

Potential Issues

There are disadvantages to using capability URLs arising from the fact that the URLs were not originally designed to be used in this way.

Risk of Exposure

In general, applications that use URLs are not designed to treat them as sensitive information. URLs appear within URL bars, from which they can be copied easily. They appear within application logs, such as within web servers and in browser history.

There are more subtle routes for exposure too. If a link to another site is followed on a page accessed through a capability URL, that site may be notified of the capability URL through the Referer HTTP header. Third party scripts within a page accessed through a capability URL can access that URL and potentially record it elsewhere. Hosted services that synchronise browser histories, and browser plugin toolbars can easily get hold of URLs for pages that someone using them visits.

The method by which a user gets the capability URL in the first place may also be compromised, enabling an ISP or web-based email service to become aware of the URL. Capability URLs will also be exposed to URL shortening services such as t.co if they are shared via Twitter direct messages.

Any of these sources of URLs can be used by search engines and other crawlers, and may therefore result in pages protected through capability URLs being shown within search results.

In short, the risk of exposure of capability URLs is very high, particularly when they are accessed through a browser.

Detecting Compromises

It can be hard to detect when a capability URL has been compromised, because there is nothing to distinguish legitimate access from illegitimate access. Unexpected access might be detectable by examining the IP addresses or User-Agent strings in requests for the resource, but there is little else to go on.

Handling Compromises

If a capability URL does leak out to unwanted recipients, the person who originally granted access through that URL needs to be able to revoke it. This is exactly the same as needs to happen in normal account-driven access control. However, capability URLs tend to be designed to be the same for everyone who has the given capability, and therefore revoking the capability URL has an impact on all those who had it. Conversely, in account-based access control it tends to be possible to target the withdrawal of rights on a single user.

It would be possible to design systems that use capability URLs in a more targetted way: that enable users to generate multiple URLs for the same capability and to pass those on to different people. This would enable targetted revocation of access rights when a particular URL is compromised.

Web Architecture

Capability URLs encode a combination of a resource and access privileges for that resource. This leads to separate URLs being used to refer to the same resource (but with different permissions about what can be done with it). For example, Google Calendar provides different URLs for the same iCalendar representation of a calendar for public and private use.

Using multiple URLs for the same resource runs contrary to good practice:

Good practice: Avoiding URI aliases
A URI owner SHOULD NOT associate arbitrarily different URIs with the same resource.
Architecture of the World Wide Web, Volume One

However, the main reason for avoiding URI aliases is based on sharing of the URI: it is better for everyone linking to, or talking about, the same resource to refer to it with the same URL, as this creates a more coherent network. Unlike normal URLs, capability URLs are oriented around only limited sharing. In these circumstances, having multiple aliases is not an issue.

What may need to be considered, however, is how to transition from providing access to a resource through capability URLs and taking it public, using a normal URL. This is discussed further in .

Beyond the Single Page

All the examples of capability URLs described in are self-contained: once a user has accessed a page through a capability URL, they are able to do all they need to do within that page. Capability URLs are less easy to use in applications that require the user to access multiple pages, because each of those pages must be accessed through a (different) capability URL.

Recommendations

This section outlines recommendations about when and how to use capability URLs within web applications.

Application Design

The use of capability URLs should not be the default choice in the design of a web application because they are only secure in tightly controlled circumstances. However, in we outlined three situations in which capability URLs are useful:

If you are considering using capability URLs, you should consider other options, the costs of implementing them and the risks of using capability URLs instead. For example:

If you have decided to use capability URLs, depending on the level of risk associated to the discovery of a capability URL, you should employ as many of the following security measures as possible:

When capability URLs are used, they should be used within an appropriate HTTP verb to enable a relevant action. For example, an HTTP GET on a capability URL should not result in side effects such as the deletion of a resource. Capability URLs should encode access permissions for a resource, not actions on that resource.

When capability URLs expire, servers should respond to the URL with either a 410 Gone or a 404 Not Found response. In practice, there is little difference between these responses: a 410 Gone response requires the application to keep track of which capability URLs have been supported in the past; although this is more work for the application, it does prevent the reassignment of that capability URL to a new resource.

Capability URL Design

Capability URLs must be unique, but they should also avoid being guessable. For example, if capability URLs are generating using a URL like https://example.org/access/{number} and number is merely a sequentially increasing integer, it would be incredibly easy to scan through possible numbers to locate new information.

Good unique URLs include an unguessable unique identifier such as a UUID.

UI Design Considerations

There is currently no way for built-in user interfaces, such as the location bar of a browser, to detect when a page is being accessed through a capability URL as opposed to a normal URL.

To prevent the capability URL from being visible in the location bar, you can use the replaceState() method to replace the displayed URL with the canonical URL. However, this prevents the capability URL from being bookmarked by the user. In addition, if you do this, you should make sure the capability URL is replaced back into the history when the page is unloaded, otherwise it will not be possible for the user to navigate back to the page by navigating through their history.

Users who are provided with capability URLs to share with others should be informed of the consequences of those URLs being shared widely. Pages should describe what people who get the URL can do with it, and explain the ways in which these URLs can be shared safely.

Canonical URLs

As outlined in , servers should have a single canonical URL for a resource when there are several capability URLs that are used to provide access to that resource. This URL may be accessible by users who have the correct access privileges (granted through an account).

Canonical URLs may be used:

One possible application pattern is for capability URLs to redirect (with a 302 Found) to the canonical URL and for the server to use the Referer header, set through the redirect, to determine the level of access granted to the user. This has the advantage of not exposing the capability URL within the browser bar or within the server logs of linked to servers. However, browsers may be set to not expose the Referer header (for security reasons) in which case this method will not work.

If content is served directly from pages accessed through capability URLs, these pages can link to the canonical URL for the resource through rel="canonical" either in the metadata for the page (a <link> element) or within a Link header on the resource.

If the capability URLs refer to a resource that is later made public, they should respond with a 301 Moved Permanently providing a redirection to the normal, public, canonical URL.

Future Work

Following the above analysis, the TAG thinks that it would be useful to investigate adding a Content Security Policy directive or a separate HTTP header that indicates that the requested URL is a capability URL. A browser could then protect the URL in various ways such as: