Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

Authentication and Authorization

Farshid Tavakolizadeh edited this page Oct 29, 2020 · 3 revisions

LinkSmart Border Gateway (BGW) can authenticate and authorize access to HTTP, MQTT and WebSocket services for users defined in an OpenID Connect (OIDC) provider. Simple rules providing some basic authorization (see below for details) can be maintained in the backend of the OIDC provider as user or group attributes. These rules need to be provided to BGW in the access token as a custom claim.

Authentication

HTTP

Browser

If anonymous access to an endpoint accessed via browser is not allowed, Border Gateway provides the OAuth2 / OpenID Connect "Authorization Code Flow" (sometimes referred to as "Standard Flow"). You will be re-directed to your OpenID Connect provider to log in.

Basic Auth

>>> How to: send credentials in header.<<<

  1. User provides username/password in the REST request.
  2. BGW intercepts the request and negotiates with an OpenID Connect provider for an access token. This implements the OAuth2 / OpenID Connect "Resource Owner Password Credentials Flow".
  3. If the token is valid and the authorization rules provided in the access token allow the requested resource, BGW forwards the request to the API endpoint.

Bearer Token

Bearer token is especially useful if you are using a framework like Angular. You can set up keycloak-angular with "Standard Flow" (= "Authorization Code Flow") and connect to any REST APIs over endpoints protected by Border Gateway. Border Gateway will validate the access token while Angular is handling login, token refresh etc.

You can also obtain a bearer token manually:

>>> How to: use Bearer authentication in Postman <<<

  1. User directly negotiates with an OpenID Connect server for an access token. Example via curl for Keycloak (OAuth2 / OpenID Connect "Resource Owner Password Credentials Flow"):
curl -d "client_id=bgw_client" -d "username=<username>" -d "password=<password>" -d "grant_type=password" "<token_endpoint_of_your_openid_connect_provider>"
  1. User provides the access token in the REST request to BGW.
  2. BGW intercepts the request and validates the access token and the authorization rule inside it .
  3. If the token is valid and the authorization rules provided in the access token allow the requested resource, BGW forwards the request to the API endpoint.

MQTT

If you open an MQTT connection via Border Gateway, you can deliver username and password as defined in the MQTT standard. Border Gateway will take these user credentials to the OpenID Connect provider and obtain an access token including the authorization rules. The token is validated and the authorization rules checked against the requested method (PUB / SUB) and topic. When the request is allowed it is forwarded to the MQTT broker.

You can also deliver an access token (as described above for HTTP) in the MQTT username field. Leave the password field empty if you do. The token will then be validated and the authorization rules checked against the requested method (PUB / SUB) and topic.

WebSocket

By default the BGW WebSocket proxy expects that you use protocol MQTT over WebSockets so the data is forwarded to the BGW MQTT proxy and authenticated and authorized there. You can configure the WebSocket proxy to forward to any upstream server though. In this case, you need to provide your credentials in the query parameters of the URL to the WebSocket proxy. You can use either one of these two options:

  • Access token (see above how to obtain it from your OpenID Connect provider). The access token will be validated in the method verifyClient of ws package before the WebSocket connection is established. If everything is ok, the WebSocket connection is established, otherwise rejected. After the lifespan of the access token is over, you will be disconnected when the next data transfer is being attempted.
let ws = new WebSocket("wss://<your_domain>:<your_port>/<your_path>?access_token=<access_token>);
  • Basic authentication with username / password. The WebSocket connection to the proxy server will be established in any case, then the WebSocket proxy server will contact your OpenID Connect provider in its connection event. Messages are queued until the authorization process is finished. If successful, the queued messages will be sent to the upstream WebSocket service otherwise the socket is closed and the messages are discarded. The connection will stay open without a time limit.
let ws = new WebSocket("wss://<your_domain>:<your_port>/<your_path>?basic_auth=<base64_encoding_of_<username>:<password>>);

Authorization

Border Gateway also offers some basic authorization capabilities. Authorization rules are defined as user and / or group attributes in the OpenID Connect Provider´s backend (see Deployment).

Rule Syntax

PROTOCOL**/METHOD/DOMAIN/PORT/**PATH

where:

  • PROTOCOL is the transfer protocol (currently HTTP, HTTPS, MQTT or WS)

  • METHOD is the method in regards to the protocol, e.g. GET,POST,DELETE for HTTP and PUB,SUB for MQTT. For WebSocket connections only CONNECT is supported.

  • DOMAIN is the fully qualified domain name (FQDN)

  • PORT

    • Case MQTT / WS: TCP port of the target / upstream service
    • Case HTTPS: In a standard deployment the BGW External Interface will add headers "x-forwarded-proto" and "x-forwarded-host" (including port) and forward to the BGW HTTP proxy so in the rules regarding HTTP services you need to use protocol HTTPS and port 443 in your rule definitions. If you deploy a BGW HTTP Proxy without the BGW External Interface, you can configure your web server (e.g. nginx) to set headers "x-forwarded-proto" and "x-forwarded-host" and define rules in the same way.
    • Case HTTP: If you do not use TLS at all or cannot configure your web server to set headers "x-forwarded-proto" and "x-forwarded-host", you need to use HTTP in your rule definitions and the TCP port of BGW HTTP proxy.
  • PATH is resource information and may contain slashes itself. For HTTP and WebSocket, it is the resource path (e.g. confluence/display/COM). For MQTT, it is the topic.

Loosely based on MQTT topic specification: https://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices

In summary:

  • Every slash adds a new section. E.g.: a/b consists of two sections and a/b/ consists of three sections last of which contains an empty string.
  • Strings are case-sensitive
  • A plus + is a single section wildcard. E.g.: a/+ matches a/b but not a/b/ and a/b/c
  • A hash # is a multi-section wildcard and may only be used in the end. E.g.: a/# matches all a/b and a/b/ and a/b/c

Examples

  1. Rule HTTPS/GET/demo.linksmart.eu/443/sc HTTPS/GET/demo.linksmart.eu/443/sc/#

Allows:

  • HTTP method GET
  • using HTTPS
  • on domain demo.linksmart.eu
  • port 443
  • on path sc and starting with sc
  1. Rule HTTPS/+/demo.linksmart.eu/443/#

Allows:

  • all HTTP methods
  • using HTTPS
  • on domain demo.linksmart.eu
  • port 443
  • on any path
  1. Rule HTTPS/+/demo.linksmart.eu/443/sc/admin

Allows:

  • all HTTP methods
  • using HTTPS
  • on domain demo.linksmart.eu
  • port 443
  • on path sc/admin
  1. Rule HTTPS/#

Allows:

  • everything over HTTPS
  1. Rule MQTT/CON/mosquitto/1883/# MQTT/SUB/mosquitto/1883/nagios/test

Allows:

  • Connecting to MQTT broker on backend host mosquitto (e.g. in a user-defined Docker network)
  • Subscribing to topic nagios/test
  1. Rule WS/CONNECT/localhost/5059/#

Allows:

  • WebSocket connection to upstream service at localhost:5059