Application Keys Plugin

Added in version 1.3.10.

The OctoPrint Application Keys Plugin comes bundled with OctoPrint.

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. 11 The plugin’s confirmation generated for a new application key request.

Key management via user settings

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

Global key management via settings

Fig. 13 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 an Authorization request to the Server to start the authorization process.

  4. The Server triggers a confirmation dialog for the User on the Webinterface (unused here) and returns an endpoint to the App to poll for a decision in the Location header of an HTTP 201 Created and an Authorization response (unused here).

  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

Workflow with redirect to auth dialog

Added in version 1.8.0.

Instead of asking the user to open the full blown OctoPrint interface to confirm the request, since OctoPrint 1.8.0 there also exists the alternative of redirecting the user to a basic auth dialog that allows logging in and confirming the request in a light-weight dialog. To implementat that, follow these 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 an Authorization request to the Server to start the authorization process.

  4. The Server triggers a confirmation dialog for the User on the Webinterface (unused here) and returns an endpoint to the App to poll for a decision in the Location header of an HTTP 201 Created and an Authorization response.

  5. The App opens a browser window with the provided auth_dialog URL for the user to log in and confirm the request. At the same time the App also 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 logs in and either accepts or denies the access request which makes the auth dialog 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 Auth Dialog 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->>App: 201, Location: /plugin/appkeys/request/<app_token>, auth_dialog: <auth_dialog> note over User, Server: Step 5 App-->>Auth Dialog: open new browser window with auth_dialog URL loop Poll for decision App->>Server: GET /plugin/appkeys/request/<app_token> Server->>App: 202 end note over User, Server: Step 6 & 7 User->>Auth Dialog: Logs in alt User accepts User-->>Auth Dialog: Allow access Auth Dialog->>Server: POST /plugin/appkeys/decision/<user_token>, (True) Server->>Auth Dialog: 204 App->>Server: GET /plugin/appkeys/request/<app_token> Server->>App: 200, api_key else User denies User-->>Auth Dialog: Deny access Auth Dialog->>Server: POST /plugin/appkeys/decision/<user_token>, (False) Server->>Auth Dialog: 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 Authorization 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.

Returns a Authorization response and HTTP 201 Created with the Location header set to the endpoint to poll for a decision.

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.

Requires the PLUGIN_APPKEYS_GRANT permissions and a recent credentials check.

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 the PLUGIN_APPKEYS_ADMIN permission, fetches a list of all* application keys and pending requests registered in the system for any user.

If the additional optional parameter app is provided, only the key for the specified application identifier and the current user will be returned. A user with the PLUGIN_APPKEYS_ADMIN``permission may also specify the ``user parameter to fetch the key for the specified application identifier and a different 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 the PLUGIN_APPKEYS_ADMIN permission.

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 identified by the associated application identifier provided in the app parameter. Keys for other users but the current one can be revoked by admins with the additional user parameter to specify the user id.

generate

Generates a new application key for the user, using the application identifier provided as parameter app. Keys for other users but the current one can be generated by admins with the additional user parameter to specify the user id.

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

Requires user rights and a fresh credentials check.

Deprecated since version 1.10.0: Revoking a key by supplying the key itself has been deprecated as of OctoPrint 1.10.0. Use app and optionally user instead.

Example revoke request

Revokes the key associated with app id test for the current user.

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

{
  "command": "revoke",
  "app": "test"
}
HTTP/1.1 204 No Content

Example revoke request by an admin for a different user

Revokes the key associated with the app id test for user user.

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

{
  "command": "revoke",
  "app": "test",
  "user": "user"
}
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",
  "app": "My awesome application 1.0"
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "app_id": "My awesome application 1.0",
  "user_id": "me",
  "api_key": "abcdef1234567890"
}
JSON Parameters:
  • command (string) – The command to issue, either revoke or generate

  • app (string) – revoke & generate commands: The application identifier of the key to revoke or generate.

  • user (string) – revoke & generate commands: The user name for which to revoke or generated a key associated with the provided app id. If not provided, the current user’s name will be used.

  • key (string) – revoke command: The key to revoke. Revoking by providing the key itself has been deprecated as of OctoPrint 1.10.0. Use app and optionally user instead.

Status Codes:

Data model

Authorization 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

Authorization response

Name

Multiplicity

Type

Description

app_token

1

str

Application token to use to poll for the decision.

auth_dialog

1

str

An URL with which a dedicated auth dialog can be used for the user to log into and authorize the request.

Key response

Name

Multiplicity

Type

Description

api_key

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.getKey(app, user, opts)

Retrieves the key information the given app and optional other user. The key must belong to the current user, or the current user must have the PLUGIN_APPKEYS_ADMIN permission.

See Fetch list of existing application keys for more details.

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

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 the PLUGIN_APPKEYS_ADMIN permission.

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 the PLUGIN_APPKEYS_ADMIN permission.

See Issue an application key command for details.

Deprecated since version 1.10.0: revokeKey has been deprecated. Use revokeKeyForApp instead.

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.revokeKeyForApp(app, user, opts)

Revokes the key for the given app and optional other user. The key must belong to the current user, or the current user must have the PLUGIN_APPKEYS_ADMIN permission.

See Issue an application key command for details.

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

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.