Application Keys Plugin

The OctoPrint Application Keys Plugin comes bundled with OctoPrint (starting with version 1.3.10).

It implements a workflow for third party apps or clients to obtain an application specific API key from OctoPrint to interact with it on a user’s behalf, via confirmation of the user through OctoPrint’s web interface. Existing keys can be managed on a per-user base as well as globally by administrators.

Confirmation

Fig. 10 The plugin’s confirmation generated for a new application key request.

Key management via user settings

Fig. 11 Users can manage the application specific API keys registered to their account via their user settings.

Global key management via settings

Fig. 12 Administrators can manage all application specific API keys registered to any user.

Workflow

The workflow to receive an API key for a third party client/an app via the Application Keys Plugin should consist of the following steps:

  1. The User opens the App and gets prompted to enter or select an instance URL. Optionally (recommended!) the User also enters their username which is also their user ID into the App.
  2. The App probes for workflow support on the Server. If this request doesn’t get an HTTP 204 No Content the App needs to direct the user to an alternative manual workflow (copy-paste API key) and abort this one. Otherwise it proceeds to the next step.
  3. The App sends a key request to the Server to start the authorization process.
  4. The Server triggers a confirmation dialog for the User on the Webinterface and returns an endpoint to the App to poll for a decision in the Location header of an HTTP 201 Created.
  5. The App uses the obtained request specific endpoint to poll for a decision every second. An HTTP 202 Accepted signals that no decision has been made yet.
  6. The User either accepts or denies the access request which makes the Webinterface send a decision request to the Server.
  7. If the User accepted the request, the App receives an HTTP 200 OK with an attached API key response. If they deny it, the App will receive an HTTP 404 Not Found.
sequenceDiagram participant User participant App participant Webinterface participant Server note over User, Server: Step 1, 2 & 3 User->>App: enters URL of instance to connect to and optional user_id App->>Server: GET /plugin/appkeys/probe alt Workflow unsupported Server->>App: 404 App->>User: alternative workflow, copy-paste key manually else Workflow supported App->>Server: POST /plugin/appkeys/request, (app_name, user_id) note over User, Server: Step 4 Server-->>Webinterface: plugin message for "appkeys" w/ (app_name, user_token, user_id) Webinterface-->>User: Display confirmation dialog Server->>App: 201, Location: /plugin/appkeys/request/<app_token> note over User, Server: Step 5 loop Poll for decision App->>Server: GET /plugin/appkeys/request/<app_token> Server->>App: 202 end note over User, Server: Step 6 & 7 alt User accepts User-->>Webinterface: Allow access Webinterface->>Server: POST /plugin/appkeys/decision/<user_token>, (True) Server->>Webinterface: 204 App->>Server: GET /plugin/appkeys/request/<app_token> Server->>App: 200, api_key else User denies User-->>Webinterface: Deny access Webinterface->>Server: POST /plugin/appkeys/decision/<user_token>, (False) Server->>Webinterface: 204 App->>Server: GET /plugin/appkeys/request/<app_token> Server->>App: 404 end end

API

Probe for workflow support

GET /plugin/appkeys/probe

Probes for support of the workflow.

Normally returns an HTTP 204 No Content, indicating workflow availability. If a different status code is returned (usually an HTTP 404 Not Found), the plugin is disabled or not installed. Fall back to manual api key exchange.

Status Codes:

Start authorization process

POST /plugin/appkeys/request

Starts the authorization process.

Expects a Key request as request body.

The app parameter should be a human readable identifier to use for the application requesting access. It will be displayed to the user. Internally it will be used case insensitively, so My App and my APP are considered the same application identifiers.

The optional user parameter should be used to limit the authorization process to a specified user. If the parameter is left unset, any user will be able to complete the authorization process and grant access to the app with their account. E.g. if a user me starts the process in an app, the app should request that name from the user and use it in the user parameter. OctoPrint will then only display the authorization request on browsers the user me is logged in on.

JSON Parameters:
 
  • app – application identifier to use for the request, case insensitive
  • user – optional user id to restrict the decision to the specified user
Status Codes:
  • 201 Created – authorization process started, polling URL to query can be found in Location header

Poll for decision on existing request

GET /plugin/appkeys/request/<str:app_token>

Endpoint generated per authorization request to poll for the result.

Returns an HTTP 202 Accepted while no decision has been made yet, an HTTP 200 OK and a Key response if access has been granted and an HTTP 404 Not Found if the request has been denied or timed out.

Note

The request will be considered stale and deleted internally if the polling endpoint for it isn’t called for more than 5s.

Status Codes:
  • 200 OK – access granted, API key in response body
  • 202 Accepted – no decision has been made yet, continue polling
  • 404 Not Found – access denied or request timed out

Decide on existing request

POST /plugin/appkeys/decision/<str:user_token>

Endpoint to decide on the authorization request.

Expects a Decision request as request body.

Returns an HTTP 204 No Content on success.

JSON Parameters:
 
  • decision – boolean value to indicate whether to confirm (True) or deny (False) access
Status Codes:

Fetch list of existing application keys

GET /api/plugin/appkeys

Fetches a list of existing application keys and pending requests registered in the system for the current user.

If the additional optional parameter all is provided and the user has administrator rights, fetches a list of all* application keys and pending requests registered in the system for any user.

Returns a 200 OK with a List response in the body upon success.

Query Parameters:
 
  • all – Fetch all application keys and pending requests from all users. Requires administrator rights.

Issue an application key command

POST /api/plugin/appkeys

Application key commands allow revoking existing application keys and manually generating new ones. The available commands are:

revoke
Revokes an existing application key. Must belong to the user issuing the command, unless the user has admin rights in which case they make revoke any application key in the system. Expects the key in question as parameter key.
generate
Generates a new application key for the user, using the application identifier provided as parameter app.

Upon success, a status code of 204 No Content and an empty body is returned.

Requires user rights.

Example revoke request

Revokes the (fictional) key aabbccddeeff112233445566.

POST /api/plugin/appkeys HTTP/1.1
Host: example.com
Content-Type: application/json
X-Api-Key: abcdef...

{
  "command": "revoke",
  "key": "aabbccddeeff112233445566"
}
HTTP/1.1 204 No Content

Example generate request

Generates a new key for application identifier “My awesome application 1.0”.

POST /api/plugin/appkeys HTTP/1.1
Host: example.com
Content-Type: application/json
X-Api-Key: abcdef...

{
  "command": "generate",
  "key": "My awesome application 1.0"
}
HTTP/1.1 204 No Content
JSON Parameters:
 
  • command (string) – The command to issue, either revoke or generate
  • key (string) – revoke command: The key to revoke
  • app (string) – generate command: Application identifier for which to generate a key
Status Codes:

Data model

Key request

Name Multiplicity Type Description
app 1 str Application identifier to use for the request
user 0..1 str User identifier/name to restrict the request to

Key response

Name Multiplicity Type Description
apikey 1 str the API key generated for the application

Decision request

Name Multiplicity Type Description
decision 1 boolean True if the access request it to be granted, False otherwise

List response

Name Multiplicity Type Description
keys 1 list of key list entries Keys registered in the system
pending 1 list of pending list entries Currently pending authorization requests

Key list entry

Name Multiplicity Type Description
api_key 1 str API key
app_id 1 str Application identifier
user_id 1 str User ID of the key’s owner

Pending list entry

Name Multiplicity Type Description
app_id 1 str Application identifier
user_id 0..1 str optional: User ID of user who can grant or deny request
user_token 1 str Token to grant or deny request

JavaScript Client Library

OctoPrintClient.plugins.appkeys.getKeys(opts)

Retrieves registered keys and pending requests for the current user.

See Fetch list of existing application keys for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.getAllKeys(opts)

Retrieves registered keys and pending requests for all users.

Needs administrator rights.

See Fetch list of existing application keys for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.generateKey(app, opts)

Generates a key for the given app and the current user.

See Issue an application key command for details.

Arguments:
  • app (string) – Application identifier
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.revokeKey(key, opts)

Revokes the given key. The key must belong to the current user, or the current user must have administrator rights.

See Issue an application key command for details.

Arguments:
  • key (string) – Key to revoke
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.decide(token, decision, opts)

Decides on an existing authorization request.

See Decide on existing request for more details.

Arguments:
  • token (string) – User token for which to make the decision, as pushed to the client via the socket.
  • decision (boolean) – Whether to grant access (true) or not (false).
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.probe(opts)

Probes for workflow support.

See Probe for workflow support for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.request(app, opts)

Starts a new authorization request for the provided app identifier.

See Start authorization process for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.requestForUser(app, user, opts)

Starts a new authorization request for the provided app and user identifiers.

See Start authorization process for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.checkDecision(token, opts)

Polls for a decision on an existing authorization request identified by token.

See Poll for decision on existing request for more details.

Arguments:
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

OctoPrintClient.plugins.appkeys.authenticate(app, user, opts)

Convenience function that probes for support, issues a request and then automatically starts polling for a decision on the returned polling endpoint every 1s, until either a positive or negative decision is returned. On success the returned promise is resolved with the generated API key as argument. If anything goes wrong or there is no support for the workflow, the promise is rejected.

Example usage

OctoPrint.plugins.appkeys.authenticate("My App", "some_user")
    .done(function(api_key) {
        console.log("Got our API key:", api_key);
    })
    .fail(function() {
        console.log("No API key for us");
    })
Arguments:
  • app (string) – Application identifier
  • user (string) – Optional user identifier
  • opts (object) – Additional options for the request
Returns Promise:
 

A jQuery Promise for the request’s response

Source code

The source of the Application Keys plugin is bundled with OctoPrint and can be found in its source repository under src/octoprint/plugins/appkeys.