MF-1439 - Add support for Basic Authentication in HTTP Adapter (#1441)
* Add support for basic auth for HTTP adapter Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix API docs Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Inline BasicAuth check Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
This commit is contained in:
parent
5ac1203b55
commit
d6a3830ef4
43
api/http.yml
43
api/http.yml
|
@ -6,6 +6,9 @@ info:
|
|||
paths:
|
||||
/channels/{id}/messages:
|
||||
post:
|
||||
security:
|
||||
- jwtAuth: []
|
||||
- basicAuth: []
|
||||
summary: Sends message to the communication channel
|
||||
description: |
|
||||
Sends message to the communication channel. Messages can be sent as
|
||||
|
@ -13,22 +16,21 @@ paths:
|
|||
tags:
|
||||
- messages
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Authorization"
|
||||
- $ref: "#/components/parameters/ID"
|
||||
requestBody:
|
||||
$ref: "#/components/requestBodies/MessageReq"
|
||||
responses:
|
||||
'202':
|
||||
"202":
|
||||
description: Message is accepted for processing.
|
||||
'400':
|
||||
"400":
|
||||
description: Message discarded due to its malformed content.
|
||||
'403':
|
||||
"403":
|
||||
description: Message discarded due to missing or invalid credentials.
|
||||
'404':
|
||||
"404":
|
||||
description: Message discarded due to invalid channel id.
|
||||
'415':
|
||||
"415":
|
||||
description: Message discarded due to invalid or missing content type.
|
||||
'500':
|
||||
"500":
|
||||
description: Unexpected server-side error occurred.
|
||||
|
||||
components:
|
||||
|
@ -94,16 +96,15 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/SenMLRecord"
|
||||
|
||||
parameters:
|
||||
Authorization:
|
||||
name: Authorization
|
||||
description: Access token.
|
||||
securitySchemes:
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
jwtAuth:
|
||||
type: apiKey
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
format: jwt
|
||||
required: true
|
||||
name: Authorization
|
||||
parameters:
|
||||
ID:
|
||||
name: id
|
||||
description: Unique channel identifier.
|
||||
|
@ -116,11 +117,11 @@ components:
|
|||
requestBodies:
|
||||
MessageReq:
|
||||
description: |
|
||||
Message to be distributed. Since the platform expects messages to be
|
||||
properly formatted SenML in order to be post-processed, clients are
|
||||
obliged to specify Content-Type header for each published message.
|
||||
Note that all messages that aren't SenML will be accepted and published,
|
||||
but no post-processing will be applied.
|
||||
Message to be distributed. Since the platform expects messages to be
|
||||
properly formatted SenML in order to be post-processed, clients are
|
||||
obliged to specify Content-Type header for each published message.
|
||||
Note that all messages that aren't SenML will be accepted and published,
|
||||
but no post-processing will be applied.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
|
|
|
@ -8,16 +8,16 @@ The service is configured using the environment variables presented in the
|
|||
following table. Note that any unset variables will be replaced with their
|
||||
default values.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|--------------------------------|-----------------------------------------------------|-----------------------|
|
||||
| MF_HTTP_ADAPTER_LOG_LEVEL | Log level for the HTTP Adapter | error |
|
||||
| MF_HTTP_ADAPTER_PORT | Service HTTP port | 8180 |
|
||||
| MF_NATS_URL | NATS instance URL | nats://localhost:4222 |
|
||||
| MF_HTTP_ADAPTER_CLIENT_TLS | Flag that indicates if TLS should be turned on | false |
|
||||
| MF_HTTP_ADAPTER_CA_CERTS | Path to trusted CAs in PEM format | |
|
||||
| MF_JAEGER_URL | Jaeger server URL | localhost:6831 |
|
||||
| MF_THINGS_AUTH_GRPC_URL | Things service Auth gRPC URL | localhost:8181 |
|
||||
| MF_THINGS_AUTH_GRPC_TIMEOUT | Things service Auth gRPC request timeout in seconds | 1s |
|
||||
| Variable | Description | Default |
|
||||
| --------------------------- | --------------------------------------------------- | --------------------- |
|
||||
| MF_HTTP_ADAPTER_LOG_LEVEL | Log level for the HTTP Adapter | error |
|
||||
| MF_HTTP_ADAPTER_PORT | Service HTTP port | 8180 |
|
||||
| MF_NATS_URL | NATS instance URL | nats://localhost:4222 |
|
||||
| MF_HTTP_ADAPTER_CLIENT_TLS | Flag that indicates if TLS should be turned on | false |
|
||||
| MF_HTTP_ADAPTER_CA_CERTS | Path to trusted CAs in PEM format | |
|
||||
| MF_JAEGER_URL | Jaeger server URL | localhost:6831 |
|
||||
| MF_THINGS_AUTH_GRPC_URL | Things service Auth gRPC URL | localhost:8181 |
|
||||
| MF_THINGS_AUTH_GRPC_TIMEOUT | Things service Auth gRPC request timeout in seconds | 1s |
|
||||
|
||||
## Deployment
|
||||
|
||||
|
@ -53,7 +53,9 @@ Setting `MF_HTTP_ADAPTER_CA_CERTS` expects a file in PEM format of trusted CAs.
|
|||
|
||||
## Usage
|
||||
|
||||
HTTP Authorization request header contains the credentials to authenticate a Thing. The authorization header can be a plain Thing key
|
||||
or a Thing key encoded as a password for Basic Authentication. In case the Basic Authentication schema is used, the username is ignored.
|
||||
For more information about service capabilities and its usage, please check out
|
||||
the [API documentation](https://api.mainflux.io/?urls.primaryName=http-openapi.yml).
|
||||
the [API documentation](https://api.mainflux.io/?urls.primaryName=http.yml).
|
||||
|
||||
[doc]: https://docs.mainflux.io
|
||||
|
|
|
@ -37,6 +37,7 @@ type testRequest struct {
|
|||
contentType string
|
||||
token string
|
||||
body io.Reader
|
||||
basicAuth bool
|
||||
}
|
||||
|
||||
func (tr testRequest) make() (*http.Response, error) {
|
||||
|
@ -44,9 +45,13 @@ func (tr testRequest) make() (*http.Response, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", tr.token)
|
||||
}
|
||||
if tr.basicAuth && tr.token != "" {
|
||||
req.SetBasicAuth("", tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
}
|
||||
|
@ -70,6 +75,7 @@ func TestPublish(t *testing.T) {
|
|||
contentType string
|
||||
auth string
|
||||
status int
|
||||
basicAuth bool
|
||||
}{
|
||||
"publish message": {
|
||||
chanID: chanID,
|
||||
|
@ -85,6 +91,14 @@ func TestPublish(t *testing.T) {
|
|||
auth: "",
|
||||
status: http.StatusForbidden,
|
||||
},
|
||||
"publish message with basic auth": {
|
||||
chanID: chanID,
|
||||
msg: msg,
|
||||
contentType: contentType,
|
||||
auth: token,
|
||||
basicAuth: true,
|
||||
status: http.StatusAccepted,
|
||||
},
|
||||
"publish message with invalid authorization token": {
|
||||
chanID: chanID,
|
||||
msg: msg,
|
||||
|
@ -92,6 +106,14 @@ func TestPublish(t *testing.T) {
|
|||
auth: invalidToken,
|
||||
status: http.StatusForbidden,
|
||||
},
|
||||
"publish message with invalid basic auth": {
|
||||
chanID: chanID,
|
||||
msg: msg,
|
||||
contentType: contentType,
|
||||
auth: invalidToken,
|
||||
basicAuth: true,
|
||||
status: http.StatusForbidden,
|
||||
},
|
||||
"publish message without content type": {
|
||||
chanID: chanID,
|
||||
msg: msg,
|
||||
|
@ -123,6 +145,7 @@ func TestPublish(t *testing.T) {
|
|||
contentType: tc.contentType,
|
||||
token: tc.auth,
|
||||
body: strings.NewReader(tc.msg),
|
||||
basicAuth: tc.basicAuth,
|
||||
}
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", desc, err))
|
||||
|
|
|
@ -103,6 +103,10 @@ func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token := r.Header.Get("Authorization")
|
||||
if _, pass, ok := r.BasicAuth(); ok {
|
||||
token = pass
|
||||
}
|
||||
|
||||
payload, err := decodePayload(r.Body)
|
||||
if err != nil {
|
||||
|
@ -119,7 +123,7 @@ func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
|||
|
||||
req := publishReq{
|
||||
msg: msg,
|
||||
token: r.Header.Get("Authorization"),
|
||||
token: token,
|
||||
}
|
||||
|
||||
return req, nil
|
||||
|
|
Loading…
Reference in New Issue