diff --git a/amqtt/contrib/http.py b/amqtt/contrib/http.py index bb53ff4..2883401 100644 --- a/amqtt/contrib/http.py +++ b/amqtt/contrib/http.py @@ -137,46 +137,27 @@ class HttpAuthPlugin(BaseAuthPlugin, BaseTopicPlugin): @dataclass class Config: - """Configuration for the HTTP Auth & ACL Plugin. - - Members: - - host *(str) hostname of the server for the auth & acl check - - port *(int) port of the server for the auth & acl check - - user_uri *(str) uri of the topic check (e.g. '/user') - - topic_uri *(str) uri of the topic check (e.g. '/acl') - - request_method *(RequestMethod) send the request as a GET, POST or PUT - - params_mode *(ParamsMode) send the request with json or form data - - response_mode *(ResponseMode) expected response from the auth/acl server. STATUS (code), JSON, or TEXT. - - user_agent *(str) the 'User-Agent' header sent along with the request - - ParamsMode: - - for user authentication, the http server will receive in json or form format the following: - - username *(str)* - - password *(str)* - - client_id *(str)* - - for superuser validation, the http server will receive in json or form format the following: - - username *(str)* - - for acl check, the http server will receive in json or form format the following: - - username *(str)* - - client_id *(str)* - - topic *(str)* - - acc *(int)* client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4) - """ + """Configuration for the HTTP Auth & ACL Plugin.""" host: str """hostname of the server for the auth & acl check""" port: int """port of the server for the auth & acl check""" user_uri: str + """URI of the topic check (e.g. '/user')""" topic_uri: str + """URI of the topic check (e.g. '/acl')""" request_method: RequestMethod = RequestMethod.GET - params_mode: ParamsMode = ParamsMode.JSON - response_mode: ResponseMode = ResponseMode.JSON + """send the request as a GET, POST or PUT""" + params_mode: ParamsMode = ParamsMode.JSON # see docs/plugins/http.md for additional details + """send the request with `JSON` or `FORM` data. *additional details below*""" + response_mode: ResponseMode = ResponseMode.JSON # see docs/plugins/http.md for additional details + """expected response from the auth/acl server. `STATUS` (code), `JSON`, or `TEXT`. *additional details below*""" with_tls: bool = False + """http or https""" user_agent: str = "amqtt" - + """the 'User-Agent' header sent along with the request""" superuser_uri: str | None = None + """URI to verify if the user is a superuser (e.g. '/superuser'), `None` if superuser is not supported""" timeout: int = 5 + """duration, in seconds, to wait for the HTTP server to respond""" diff --git a/docs/plugins/http.md b/docs/plugins/http.md index 12604ea..382691c 100644 --- a/docs/plugins/http.md +++ b/docs/plugins/http.md @@ -1,49 +1,97 @@ -# Authentication & Topic Access via external HTTP server +# Authentication & Authorization via external HTTP server -`amqtt.contrib.http.HttpAuthTopicPlugin` +`amqtt.contrib.http.HttpAuthPlugin` -If clients accessing the broker are managed by another application, implement API endpoints -that allows the broker to check if a client is authenticated and what topics that client -is authorized to access. +If clients accessing the broker are managed by another application, it can implement API endpoints +that respond with information about client authenticated and topic-level authorization. + +!!! info "browser-based mqtt over websockets" + + One of the primary use cases for this plugin is to enable browser-based applications to communicate with mqtt + over websockets. + + !!! warning + Care must be taken to make sure the mqtt password is secure (encrypted). + + For more implementation information: + + ??? info "recipe for authentication" + Provide the client id and username when webpage is initially rendered or passed to the mqtt initialization from stored + cookies. If application is secure, the user's password will be hashed should be encrypted and cannot be used to + authenticate a client. Instead, the application should create an encrypted password (eg jwt) which the server + can then verify when the broker contacts the application. + + ??? example "mqtt in javascript" + Example initialization of mqtt in javascript: + + import mqtt from 'mqtt'; + const url = 'https://path.to.amqtt.broker'; + const options = { + 'myclientid', + connectTimeout: 30000, + username: 'myclientid', + password: '' // encrypted password + }; + try { + const clientMqtt = await mqtt.connect(url, options); + +See the 'Request and Response Modes' section below for details on `params_mode` and `response_mode`. ::: amqtt.contrib.http.HttpAuthPlugin.Config options: show_source: false heading_level: 4 + extra: + class_style: "simple" -**Configuration** +[//]: # (manually creating the heading so it doesn't show in the sidebar ToC) +

Params and Response Modes

-- `host` *(str) hostname of the server for the auth & acl check -- `port` *(int) port of the server for the auth & acl check -- `user_uri` *(str) uri of the user auth check (e.g. '/user') -- `topic_uri` *(str) uri of the topic check (e.g. '/acl') -- `request_method` *(RequestMethod) send the request as a GET, POST or PUT -- `params_mode` *(ParamsMode) send the request with json or form data -- `response_mode` *(ResponseMode) expected response from the auth/acl server. STATUS (code), JSON, or TEXT. -- `user_agent` *(str) the 'User-Agent' header sent along with the request +Each URI endpoint will receive different information in order to determine authentication and authorization; +format will depend on `params_mode` configuration attribute (`json` or `form`).: -Each endpoint (uri) will receive the information needed to determine authentication and authorization (in either -json or form data format, based on the `params_mode`) +*For user authentication, the request will contain:* -For user authentication (`user_uri`), the http server will receive in json or form format the following: - username *(str)* - password *(str)* - client_id *(str)* -For superuser validation (`superuser_uri`), the http server will receive in json or form format the following: +*For superuser validation, the request will contain:* + - username *(str)* -For acl check (`acl_uri`), the http server will receive in json or form format the following: +*For acl check, the request will contain:* + - username *(str)* - client_id *(str)* - topic *(str)* - - acc *(int)* client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4) + - acc *(int)* : client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4) +All endpoints should respond with the following, dependent on `response_mode` configuration attribute: -The HTTP endpoints can respond in three different ways, depending on `response_mode`: +*In `status` mode: -1. STATUS - allowing access should respond with a 2xx status code. rejection is 4xx. - if a 5xx is received, the plugin will not participate in the filtering operation and will defer to another topic filtering plugin to determine access -2. JSON - response should be `{'ok':true|false|null, 'error':'optional reason for false or null response'}`. - `true` allows access, `false` denies access and `null` the plugin will not participate in the filtering operation -3. TEXT - `ok` allows access, any other message denies access. non-participation not supported with this mode. + - status code: 2xx (granted) or 4xx(denied) or 5xx (noop) + +!!! note "5xx response" + **noop** (no operation): plugin will not participate in the filtering operation and will defer to another + topic filtering plugin to determine access. if there is no other topic filtering plugin, access will be denied. + +*In `json` mode:* + + - status code: 2xx + - content-type: application/json + - response: {'ok': True } (granted), {'ok': False, 'error': 'optional error message' } (denied) or { 'error': 'optional error message' } (noop) + +!!! note "excluded 'ok' key" + **noop** (no operation): plugin will not participate in the filtering operation and will defer to another + topic filtering plugin to determine access. if there is no other topic filtering plugin, access will be denied. + +*In `text` mode:* + + - status code: 2xx + - content-type: text/plain + - response: 'ok' or 'error' + +!!! note "noop not supported" + in text mode, noop (no operation) is not supported \ No newline at end of file