Integrating Account Lifecycle Management into a Custom App

Introduction

Groove.id can manage account lifecycle for your custom or in-house applications. This document describes the API you’ll use to make that happen.

Configuration

In the Groove.id console, add a new Custom application. Give it a name and an icon as desired. Note the app ID and the API Token; you’ll need them to authenticate to the service later. The API Token will not be visible again, and regenerating it will invalidate the old one.

The configuration process will ask you which of the following account lifecycle operations the application supports. (A later section of this document details each of these operations.)

  • Support for GetAccount and ListAccounts is required for lifecycle management integrations.
  • ListGroups, ListRoles, ListLicenses to list the various licenses available.
  • CreateAccount
  • Invite
  • DeleteAccount
  • EnableAccount & DisableAccount
  • SetUsername
  • AddRole & RemoveRole
  • SetRoles
  • AddLicense & RemoveLicense
  • AddGroup & RemoveGroup
  • SetProperty & ClearProperty

Identifiers

A User represents an actual person. Each person may have an Account which represents their access to a particular App.

Many applications have a unique way of identifying accounts within the application. This may be some opaque string or number, or an email address, or user name. We call this field the account Identifier. It is Groove.id’s job to use Account objects to manage the relationship between Users and each app’s identifier for a user. When implementing a custom lifecycle integration, you don’t deal with Groove.id Users, you only deal with account identifiers.

API Implementation

Groove.id sends account lifecycle management requests to your application via a WebSocket connection. Your application should initiate and maintain a connection to Groove.id at the following endpoint. Your request must include an Authorization header with your _apitoken. The _appid and _apitoken come from the Configuration step, above.

GET /apps/:app_id/lifecycle HTTP/1.0
Upgrade: websocket
Authorization: TOKEN :api_token

Message Structure

Groove.id will send your application messages over the WebSocket connection of the form:

{
    "Operation": string,  // the operation requested by Groove.id
    "Body": object        // operation-specific data
}

Your application should make the requested change and then must send one or more messages describing the result, of the form:

{
    "Status": statusCode,   // an HTTP-style status code, 200 for success, 4xx or 5xx for errors.
    "Error": string | null, // error message. Must be present if status >= 400, must not be present if status < 400.
    "Body": object          // operation-specific response data
}

If the operation requires multiple response messages, such as with the ListAccounts operations, each status must be 100 (“Continue”) until the final message, which should have a 2xx, 4xx or 5xx value for Status.

Operations

The remainder of this document describes each lifecycle operation.

GetAccount

Return the details of an account in the application.

{
    "Operation": "GetAccount",
    "Body": {
        "Identifier": "1234567" // the app-specific account identifier
    }
}

The body of the response contains an Account object.

{
    "Status": 200,
    "Body": {
        "Account": {
            // Note: you should not provide the `UserID` or `AppID` fields
            "Identifier": "1234567",  // the app-specific account identifier
            "State": "enabled",
            "Licenses": ["premium"],
            "Roles": ["admin", "ticket-creator"],
            "EmailAddress": "alice@example.com"
        }
    }
}

If the account does not exist, return status 404:

{
    "Status": 404
}

ListAccounts

Return the details of all accounts in the application.

{
    "Operation": "ListAccounts"
}

In response to the ListAccounts message, your application should send Groove.id a separate message for every account. The message format is identical to a GetAccount response:

{
    "Status": 100,
    "Body": {
        "Account": object // an Account object.
    }
}

When your application has encountered the final message, send a message with an empty body and a status of 204:

{
    "Status": 204
}

CreateAccount

Create a user account.

{
    "Operation": "CreateAccount",
    "Body": {
        "Account": {
            // Note: The UserID, AppID and Identifiers fields will not be present.
            "State": "enabled",
            "Licenses": ["premium"],
            "Roles": ["admin", "ticket-creator"],
            "EmailAddress": "alice@example.com"
        }
    }
}

Your application is expected to process the following fields in the Account, if the field applies to your application.

  • State, to the extent that the various states apply in your application
  • Licenses
  • Roles
  • Name
  • EmailAddress
  • Groups
  • Properties
  • Tags

You must include the application specific identifier for the new account in the response message. Groove.id will send that as the Identifier in future messages.

{
    "Status": 201,  // "Created"
    "Body": {
        "Identifier": "1234567" // app-specific account identifier for the new account.
    }
}

Invite

Invite a user to the application.

{
    "Operation": "Invite",
    "Body": {
        "Email": "alice@example.com" // the user's email address.
    }
}

If the application supports it (and not all do), you should respond with a unique identifier for the account. Groove.id will send that as the account’s identifier in future messages.

{
    "Status": 200,
    "Body": {
        "Identifier": "1234567" // app-specific account identifier for the new account (optional)
    }
}

DeleteAccount

Delete an account in the application.

{
    "Operation": "DeleteAccount",
    "Body": {
        "Identifier": "1234567" // app-specific account identifier to delete
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

EnableAccount

Enable an existing account in the application.

{
    "Operation": "EnableAccount",
    "Body": {
        "Identifier": "1234567" // app-specific account identifier to enable
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

DisableAccount

Disable an existing account in the application.

{
    "Operation": "DisableAccount",
    "Body": {
        "Identifier": "1234567" // app-specific account identifier to disable
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

SetUsername

Set the username for an account in the application.

{
    "Operation": "SetUsername",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "Username": "alice42"
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

AddRole

Add a role to an account in the application.

{
    "Operation": "AddRole",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "Role": "ticket-creator" // role identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

RemoveRole

Remove a role from an account in the application.

{
    "Operation": "RemoveRole",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "Role": "ticket-creator" // role identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

SetRoles

Set an account’s roles in the application. The set of roles in this message should replace any roles currently applied to the account.

{
    "Operation": "SetRoles",
    "Body": {
        "Identifier": "1234567",             // app-specific account identifier
        "Roles": ["ticket-creator", "admin"] // an array of string role identifiers
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

AddLicense

Add a license to an account in the application.

{
    "Operation": "AddLicense",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "License": "premium"     // license identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

RemoveLicense

Remove a license from an account in the application.

{
    "Operation": "RemoveLicense",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "license": "premium"     // license identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

AddGroup

Add a group to an account in the application.

{
    "Operation": "AddGroup",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "Group": "HR Managers"   // group identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

RemoveGroup

Remove a group from an account in the application.

{
    "Operation": "RemoveGroup",
    "Body": {
        "Identifier": "1234567", // app-specific account identifier
        "Group": "HR Managers"   // group identifier
    }
}

On success, your application should respond with status 204:

{
    "Status": 204, // "No Content"
}

ListGroups

List the available groups

{
    "Operation": "ListGroups",
}

In response to the ListGroups message, your application should send Groove.id a separate message for each available group. The message format is a document containing a AppGroup:

{
    "Status": 100,
    "Body": {
        "Group": {
            "ID": "S-1234",
            "Name": "Administrators"
        }
    }
}

When your application has encountered the final group, send a message with an empty body and a status of 204:

{
    "Status": 204
}

ListRoles

List the available groups

{
    "Operation": "ListRoles",
}

In response to the ListRoles message, your application should send Groove.id a separate message for each available role. The message format is a document containing a AppRole:

{
    "Status": 100,
    "Body": {
        "Role": {
            "ID": "super-admin",
            "Name": "Super Admin"
        }
    }
}

When your application has encountered the final group, send a message with an empty body and a status of 204:

{
    "Status": 204
}

ListLicenses

List the available groups

{
    "Operation": "ListLicenses",
}

In response to the ListLicenses message, your application should send Groove.id a separate message for each available license. The message format is a document containing a AppLicense:

{
    "Status": 100,
    "Body": {
        "License": {
            "ID": "gold",
            "Name": "Gold"
        }
    }
}

When your application has encountered the final group, send a message with an empty body and a status of 204:

{
    "Status": 204
}
Last modified May 12, 2020: refactor docs (d7a7a5c1d)