Soteria is responsible for Authentication and Authorization of every request sent to EMQ. The following configuration in HOCON format, configure EMQ to use HTTP Service for Authentication and Authorization.
{
mechanism = password_based
backend = http
enable = true
method = post
url = "https://127.0.0.1:8080/v2/auth"
body {
username = "${username}"
password = "${password}"
token = "${username}"
clientid = "${clientid}"
}
headers {
"Content-Type" = "application/json"
"X-Request-Source" = "EMQX"
}
}
{
type = http
enable = true
method = post
url = "https://127.0.0.1:32333/v2/acl"
body {
username = "${username}"
topic = "${topic}"
action = "${action}"
}
headers {
"Content-Type" = "application/json"
"X-Request-Source" = "EMQX"
}
}
We are using the Authentication HTTP Service and Authorization HTTP Service plugins of EMQ for forwarding these requests to Soteria and doing Authentication and Authorization. EMQ has caching mechanism, but it sends requests almost for each Publish message to Soteria. PS: On Subscribe we have only one message from client that need authorization and other messages are coming from server.
Soteria supports having multiple vendors at the same time. Means you can use single cluster for multiple companies at the same time and validate their tokens and control accesses.
company: "<<company_name>>"
driver_salt: ""
passenger_salt: ""
passenger_hash_length: 15
driver_hash_length: 15
allowed_access_types: ["pub", "sub"]
keys:
iss-0: "key-value"
iss-1: "key-value"
iss_entity_map:
0: "entity-0"
1: "entity-1"
default: "default-entity"
iss_peer_map:
0: "peer-0"
1: "peer-1"
default: "default-peer"
jwt:
iss_name: "iss"
sub_name: "sub"
signing_method: "RS512"
topics:
- topic1
- topic2
- ...
driver_salt
,passenger_salt
, passenger_hash_length
, driver_hash_length
are used for HashIDManager.
This component only works for passenger and driver issuers.
The following is a mapping that associates vendors (companies) with the keys used for opening JWT tokens. If symmetrical keys are utilized, it is important to use their base64 representation. It should also be noted that Soteria only requires public keys in cases where asymmetrical keys are employed.
These two configuration map iss to entity and peer respectively.
Note: default case is required
iss_entity_map:
0: "driver"
1: "passenger"
default: "none"
iss_peer_map:
0: "passenger"
1: "driver"
default: "none"
In the example above, we have two maps for entity & peer maps. As it's clear for entity structure 0 and 1 is mapped to driver and passenger, respectively. Vice Versa, for peer structure it can be seen that 1 and 0 is mapped to driver and passenger. We have also the default key for both two cases.
In the topic example, we have an accesses section in which 0 is mapped to 2 and 1 is mapped to -1 which can be interpreted as a map from IssEntity's Keys to Access Types. In the other words this structure means:
- Driver has a Pub access on topic
- Passenger has a None access on topic (No Access)
This is the JWT configuration. iss_name
and sub_name
are the name of issuer
and subject in the JWT token's payload respectively.
signing_method
is the method that is used to sign the JWT token.
Here are list of different signing methods
- ES384
- RS512 *
- PS512
- RS384 *
- HS256 *
- HS384 *
- RS256 *
- PS384
- ES256
- ES512
- EdDSA
- HS512 *
- PS256
Note: only the methods with
*
are supported for now.
type: "<<Name>>"
template: "<<regex template>>"
hash_type: 0|1
accesses:
iss-0: "<<access>>"
iss-1: "<<access>>"
Topic template is a string consist of Variables and Functions and regular expressions.
Variables and Function are replaced first, and then the whole template will compile as a regular expression. The end result will be compared against the requested topic.
This is template topic given in vendor:topics[#]:template
.
- type: driver_location
template: ^{{.company}}/driver/{{.sub}}/location$
accesses:
0: "2"
1: "-1"
^{{.company}}/driver/{{HashID .hashType .sub (IssToSnappID .iss)}}/location/[a-zA-Z0-9-_]+$
After parsing the template we get something like this
// company=snapp
// hashType=0
// sub=D96ZbvJakLp4PYd
// iss=0
^snapp/driver/D96ZbvJakLp4PYd/location/[a-zA-Z0-9-_]+$
Now if the requested topic match the created topic it is considered as a valid topic for that particular user.
requested_topic: snapp/driver/D96ZbvJakLp4PYd/location/23fw49vxd
created_topic_regex: ^snapp/driver/D96ZbvJakLp4PYd/location/[a-zA-Z0-9-_]+$
These are the variables available to use in the topic templates.
-
iss
issuer obtained from JWT token -
sub
subject obtained from JWT token -
hashType
Hash type field defined in topic template configurationHashType Value HashID 0 MD5 1 -
company
company field defined in vendor configuration
These are the function available to use in the topic templates.
IssToEntity(iss string) string
convertiss
obtained from JWT token to defined entity inissEntityMap
IssToPeer(iss string) string
convertiss
obtained from JWT token to define peer inissPeerMap
IssToSnappID(iss string) string
convertiss
obtained from JWT token tosnappid.audience
HashID(hashType int, sub string, snappID snappid.audience)
generatedhashID
for the givensubject
base on thehashType
andsnappid.audience
Note: snappid.audience
only is available for issuer 0 and 1 which are for driver and passenger respectively.
List of all types of access on a topic.
Access | Value |
---|---|
Subscribe | 1 |
Publish | 2 |
Subscribe & Publish | 3 |
None | -1 |
Use any value for issuer but if you have an entity called Driver
or Passenger
,
we recommend use the following issuers for them.
Issuer | Value |
---|---|
Driver | 0 |
Passenger | 1 |