Client

Type {{#dataTypeArticle objectTypeId}}{{objectTypeId}}{{/dataTypeArticle}}
Datastore Type {{#dataTypeArticle datastoreTypeId}}{{datastoreTypeId}}{{/dataTypeArticle}}
Supports {{#article "security/authorities"}}authorities{{/article}}, {{#article "security/permissions"}}permissions{{/article}}, {{#article "transfer"}}transfer{{/article}}

Configuration

Clients maintain a configuration that you can adjust or consult as you create, update and query for them.

The following table presents you the configuration properties.

Property Type Default Read-Only Description
key text (auto-generated) Read-Only The authentication grant key.
secret text (auto-generated) The authentication grant secret.
scope array ["api"] An array of strings that define the scopes of access that the user must have granted the caller in order to use this Client.

The Cloud CMS driver requires the following scope: api.
authorizedGrantTypes array An array of Strings which define the OAuth2 authorization flows that are supported by this Client.

Valid values are: authorization_code, implicit, password and refresh.
registeredRedirectUri text If provided, this is the required redirect URI to be used for the "authorizaton code" flow. It is not required. OAuth2 allows the redirect URI to be passed in by the originating authorize request. However, if you want tighter security, you can specify the redirect URI here and enforce redirects only back to known pages.
domainUrls array If you're using Open Driver authentication, then this is an array of URLs which identify valid HTTP "Referrer" (spelling) headers for the incoming request. This allows for a safety check to help ensure that the client application is running at a known address.

Note: This is only a safeguard. But it isn't foolproof. It's still possible for malicious clients to fake HTTP "Referrer" headers if they wanted to. If you detect misuse of Client keys, you can disable the client and issue a new one.
allowOpenDriverAuthentication boolean Whether to enable "Open Driver" authentication. Open Driver authentication does not require the client secret to be present for client authorization in the "password" flow. Instead, it checks for valid domain URLs for the hosted application.
allowAutoApprovalForImplicitFlow boolean If true, then Cloud CMS will automatically approve the requested scopes when the user authenticates in the "implicit" flow. Normally, a successful authentication will take the user to a confirmation page where they can authorize the requested scopes. This skips that step. After authenticating, the scopes are automatically approved and the browser is redirected to the redirect URI.
isTenantDefault boolean false Read-Only Whether this Client is the default Client for the tenant. Every Tenant has a default Client and it is best-practice not to share this Client information with anyone except the administrator of your platform.
defaultTenantId text Read-Only If this Client is the default Client for a Tenant, then this is the ID of that Tenant.
enabled boolean true Whether this grant is enabled

Create a Client

You can create as many Clients as you would like. Each Client is essentially a "door" with a lock that lets anyone who has the keys sign on to your platform. Each Client has a public key and a private secret. For a fully-secure authorization flow, the application that aspires to sign on as the Client will need to provide the key and secret during the authorization handshake.

Here is how you create a Client:

platform.createClient();

The key and secret are generated for us. You cannot specify the key and/or secret by hand. In fact, this is a really important detail since the server uses an encryption algorithm to generate the secret (using a cipher that is unique per platform).

Here we create a Client that only allows for the "authorization_code" (3-legged) flow. If an application tries to authorize with this Client using any other OAuth2 flow, they'll be rejected. This example also contains a preconfigured redirect uri for a known entry page that we trust.

platform.createClient({
    "authorizedGrantTypes": ["authorization_code"],
    "registeredRedirectUri": "http://www.myserver.com"
});

And here is an example of a Client that utilizes the "Open Driver" authentication scheme. This is a Cloud CMS supported variation of the "password" flow whereby we do not require the client secret to authenticate. Thus, we don't need the client secret anywhere in the source code of the application. This is ideal for HTML5 and JavaScript applications running in the browser.

In place of the client secret, we check the incoming domain URL to identify the application. The domainUrls array lets us define valid domain URLs on which the application may be running.

platform.createClient({
    "authorizedGrantTypes": ["password"],
    "allowOpenDriverAuthentication": true,
    "domainUrls": ["http://www.mycompany.com", "https://www.mycompany.com"]
});

Update a Client

To update, all you have to do is make changes to your Client and fire away.

// assume we have a domain user
var user = ...;

// assume we have a client
var client = ...;

platform.createAuthenticationGrant({
    "domainPrincipalId": user.getDomainId(),
    "principalId": user.getId(),
    "clientId": client.getId()
}).update({
    "title": "iPad Application"
}).then(function() {
    console.log("The title of this auth grant is: " + this.getTitle());
});

You are not allowed to update the key or secret fields. These are Read-Only. If you'd like to change the key or secret, you must create a new Client.

Delete a Client

When you delete an Client, any users of any applications that were authenticated using the Client's credentials will no longer have access to your platform. They'll be shut down. The server will additionally clean up any OAuth2 access or refresh tokens.

Thus, the effect is pretty much instantaneous.

authgrant.del();

Disabling

As an alternative to deleting, you might opt to disable the Client. The effect is basically the same but you will have the option to re-enable or reuse the Client at some point in the future. It's really up to you.

authgrant.set("enabled", false);
authgrant.update();

Read a Client

You can read a Client by its _doc ID field.

// assume we have a client Id
var clientId = "4b5b685c980c10f98beb";

platform.readClient(clientId);

List Clients

You can retrieve a list of Clients for your platform quite easily. The following code hands back the full list.

platform.listAuthenticationGrants();

You can then iterate over the list to pick at what you'd like.

platform.listAuthenticationGrants().each(function() {
    console.log("Authentication Grant title: " + this.get("title"));
});

Retrieving the full list is potentially an expensive operation, depending how many items you have. The more your retrieve, the more data goes over the wire and so forth. Thus, you might wish to paginate your call and retrieve a subset of the total list at a time.

Here is an example that retrieves in pages of size 10. It starts on the second page (by skipping to starting index 20). It also sorts by the title field in a descending sequence.

platform.listAuthenticationGrants({
    "limit": 10,
    "skip": 20,
    "sort": { "title": -1 }
}).each(function() {
    console.log("Authentication Grant title: " + this.get("title"));
});

You don't have to have all of the pagination parameters (limit, skip and sort). You might only want to include one or two. It's up to you.

Query Clients

You can run custom queries against your Clients to find exactly what you're looking for. Here is a query that looks for Clients which are disabled.

platform.queryAuthenticationGrants({
    "enabled": false
});

Here is that same query followed by an iteration over the result map.

platform.queryAuthenticationGrants({
    "enabled": false
}).each(function(id) {
    console.log("Found an Authentication Grant: " + id + " with title: " + this.get("title"));
});

Finally, you can mix queries with pagination to reduce data over the wire and speed up performance. Here is that same query with some pagination thrown in. We limit to pages of size 10 and sort by title.

platform.queryAuthenticationGrants({
    "enabled": false
},{
    "limit": 10,
    "skip": 20,
    "sort": {
        "title": -1
    }
}).each(function(id) {
    console.log("Found an Authentication Grant: " + id + " with title: " + this.get("title"));
});