REST Client Library API

Authentication

Ably clients can authenticate with Ably in one of two ways. They can use Basic Authentication or Token Authentication. Basic Authentication makes use of the customer’s API key) to connect with Ably. Token Authentication requires a server to provide an Ably Token, an Ably TokenRequest, an Ably JWT, or an External JWT with an embedded Ably-compatible token to the client. Token Authentication, in most cases, is the recommended strategy due to it providing robust access control and stringent security measures.

Understanding the Ably authentication schemes

This page of documentation is intended to describe the REST Authentication API and is not intended to explain in depth how Ably’s authentication works. If you are new to Ably and/or the authentication schemes, we strongly recommend that you get acquainted with the following first:

Tutorials

If you’re the kind of person who prefers to dive into code, we have client-server authentication tutorials.

Basic Authentication

Basic Authentication uses one of the API keys configured via the application dashboard as the authentication token. Basic Authentication is the simplest method to use but has some important limitations described in detail in the Basic Authentication documentation.

Here is a straightforward example of using Basic Authentication when instancing an Ably REST client library.

var rest = new Ably.Rest({ key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4' });
var rest = new Ably.Rest({ key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4' });
rest = Ably::Rest.new(key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4')
rest = AblyRest(key='xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4')
$rest = new Ably\AblyRest(array('key' => 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4'));
ClientOptions options = new ClientOptions();
options.key = "xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4";
AblyRest rest = new AblyRest(options);
AblyRest rest = new AblyRest("xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4");
let rest = ARTRest(key: "xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4")
ARTRest *rest = [[ARTRest alloc] initWithKey:@"xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4"];
client, err := ably.NewRestClient(ably.ClientOptions("xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4"))

Token Authentication

Token Authentication uses an Ably-compatible token to authenticate with Ably. This can be an Ably Token obtained via the REST API requestTokenRequestTokenrequest_token endpoint, an Ably JWT signed by your API key, or an External JWT object with an embedded Ably-compatible token.

Tokens are authentication credentials that are short-lived, and therefore they may more readily be distributed to clients where there is a risk of compromise. Tokens may also be issued with a particular scope – such as a limited set of access rights or capabilities or being limited to use by a specific clientIdClientId identity – and therefore token-based authentication provides the flexibility to implement access and identity control policies in the application. See the Token Authentication documentation for more details. To initialize the REST library to a previously obtained Ably Token or Ably JWT, set the :token or :token_detailstoken or token_detailsToken or TokenDetailstoken or tokenDetails attribute of ClientOptions to the token.

Token refresh using authUrl

Below is an example that creates an instance of a REST library using Token Authentication with a means to reissue tokens as required.

Typically, in a browser environment, the authUrlAuthUrl provided would be a URL relative to an endpoint under the same origin. This endpoint issues tokens to trusted clients. Client requests can, for example, be trusted based on session cookies.

const rest = new Ably.Rest({ authUrl: '/auth' });
const rest = new Ably.Rest({ authUrl: '/auth' });
rest = Ably::Rest.new(auth_url: '/auth')
rest = AblyRest(auth_url='/auth')
$rest = new Ably\AblyRest(array('authUrl' => '/auth'));
ClientOptions options = new ClientOptions();
options.authUrl = "/auth";
AblyRest rest = new AblyRest(options);
AblyRest rest = new AblyRest(new ClientOptions { AuthUrl = new Uri("/auth") });
ARTClientOptions *options = [[ARTClientOptions alloc] init];
options.authUrl = [NSURL URLWithString:@"/auth"];
ARTRest *rest = [[ARTRest alloc] initWithOptions:options];
let options = ARTClientOptions()
options.authUrl = NSURL(string: "/auth")
let rest = ARTRest(options: options)
authOpts := &ably.AuthOptions{
  AuthURL: "/auth",
}
clientOpts := &ably.ClientOptions{
  AuthOptions: authOpts,
}
client, err := ably.NewRestClient(clientOpts)

How to specify auth options

There are several auth options you can specify along with authUrl and authCallback:

  • authMethod – when authUrl is called, the default “GET” method will be used, unless “POST” is specified.
  • authHeaders – allows you to pass additional headers as required, depending on your use case.
  • authParams – allows you to pass additional query parameters, depending on your use case.
const rest = new Ably.Rest({ authUrl: "/auth", authMethod: "POST", authParams: { p1: param1, b: param2}, authHeaders: {h1: header1, h2: header2} });
const rest = new Ably.Rest({ authUrl: "/auth", authMethod: "POST", authParams: { p1: param1, b: param2}, authHeaders: {h1: header1, h2: header2} });

Token refresh using authCallback

For non-browser clients, an authentication callback is the preferred method of implementing token refresh, although browser clients can also use authCallback if the use case requires it. This relies on your application communicating securely with your own servers to obtain a token.

The following code sample shows an example of using an authCallback in a client:

const rest = new Ably.Rest({
  authCallback: (tokenParams, callback) => {
    // implement your callback here
  },
});
const rest = new Ably.Rest({
  authCallback: (tokenParams, callback) => {
    // implement your callback here
  },
});

Selecting an authentication mechanism

When deciding on which authentication method you will be using, it is recommended to bear in mind the principle of least privilege: a client should ideally only possess the credentials and rights that it needs to accomplish what it wants; this way, if the credentials are compromised, the rights that can be abused by an attacker are minimized.

The table below should be used as a rough guide as to what you should consider when choosing your authentication method. Many applications will most naturally use a mixed strategy: one or more trusted application servers will use basic authentication to access the service and issue tokens over HTTPS, whereas remote browsers and devices will use individually issued tokens:

Scenario Basic Token Description
Your scripts may be exposed No Yes If the script, program or system holding the key is exposed, for example on a user’s device, you should not embed an API key and instead use Token Authentication. If the script is on a secure environment such as your own server, an API key with Basic Authentication is fine.
Your connection may be insecure No Yes If there is a risk of exposure of the client’s credentials, either directly or over an insecure, or insecurely proxied, connection, Token Authentication should be used. If you are sure the connection is secure and unmediated, Basic Authentication is acceptable.
You have no server to control access Yes No If you do not have your own server to perform authentication and provide tokens to users, you’ll need to use Basic Authentication.
You require fine-grained access control No Yes If you need to provide privileges on a user-by-user basis, you’d be better using Token Authentication. If you only need a few access control groups, Basic Authentication is reasonable.
Users need restricted periods of access No Yes If you need users to only have access for a certain period of time, or the ability to revoke access, Token Authentication is needed. If users are able to always have access, Basic Authentication is acceptable.
Users need to identify themselves Partial Yes If the user can be trusted to identify itself, Basic Authentication is fine. If the user cannot be trusted however, Token Authentication is better as it allows for a trusted token distributor to identify the user instead.

Identified clients

When a client is authenticated and connected to Ably, they are considered to be an authenticated client. However, whilst an authenticated client has a verifiable means to authenticate with Ably, they do not necessarily have an identity. When a client is assigned a trusted identity (i.e. a client_idClientIdclientId), then they are considered to be an identified client and for all operations they perform with the Ably service, their client_idClientIdclientId field will be automatically populated and can be trusted by other clients.

We encourage customers to always issue tokens to clients so that they authenticate using the short-lived token and do not have access to a customer’s private API keys. Since the customer can then control the client_idClientIdclientId that may be used by any of its clients, all other clients can rely on the validity of the client_idClientIdclientId in published messages and of members present in presence channels.

The following example demonstrates how to issue an Ably TokenRequest with an explicit client_idClientIdclientId that, when used by a client, will then be considered an identified client.

var rest = new Ably.Rest({ key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4' });
rest.auth.createTokenRequest({ clientId: 'Bob' }, function(err, tokenRequest) {
  /* ... issue the TokenRequest to a client ... */
})
var rest = new Ably.Rest({ key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4' });
rest.auth.createTokenRequest({ clientId: 'Bob' }, function(err, tokenRequest) {
  /* ... issue the TokenRequest to a client ... */
})
rest = Ably::Rest.new(key: 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4')
token_request = rest.auth.create_token_request(client_id: 'Bob')
# ... issue the TokenRequest to a client ...
rest = AblyRest(key='xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4')
token_request = rest.auth.create_token_request(client_id='Bob')
# ... issue the TokenRequest to a client ...
$rest = new Ably\AblyRest(array('key' => 'xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4'));
$tokenRequest = $rest->auth->createTokenRequest(array('clientId' => 'Bob'));
# ... issue the TokenRequest to a client ...
ClientOptions options = new ClientOptions();
options.key = "xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4";
AblyRest rest = new AblyRest(options);
TokenParams tokenParams = new TokenParams();
tokenParams.clientId = "Bob";
TokenRequest tokenRequest;
tokenRequest = rest.auth.createTokenRequest(tokenParams, null);
/* ... issue the TokenRequest to a client ... */
AblyRest rest = new AblyRest(new ClientOptions {Key = "xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4"});
TokenParams tokenParams = new TokenParams {ClientId = "Bob"};
string tokenRequest = await rest.Auth.CreateTokenRequestAsync(tokenParams);
// ... issue the TokenRequest to a client ...
ARTRest *rest = [[ARTRest alloc] initWithKey:@"xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4"];
ARTTokenParams *tokenParams = [[ARTTokenParams alloc] initWithClientId:@"Bob"];
[rest.auth createTokenRequest:tokenParams options:nil
  callback:^(ARTTokenRequest *tokenRequest, NSError *error) {
    // ... issue the TokenRequest to a client ...
}];
let rest = ARTRest(key: "xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4")
let tokenParams = ARTTokenParams(clientId: "Bob")
rest.auth.createTokenRequest(tokenParams, options: nil) { tokenRequest, error in
  // ... issue the TokenRequest to a client ...
}
client, err := ably.NewRealtimeClient(ably.ClientOptions{("xVLyHw.6i47Lg:LKR4U5vO20hqsYzACzTnwPQS9ZU31fDjAp3TkekBEY4"))
params := &ably.TokenParams{
  ClientID: "Bob",
}
tokenRequest, err := client.Auth.CreateTokenRequest(params, nil)

API Reference

View the Authentication API Reference.


Need help?

If you need any help with your implementation or if you have encountered any problems, do get in touch. You can also quickly find answers from our knowledge base, and blog.