mosquitto-go-auth
mosquitto-go-auth copied to clipboard
Add oauth2/openid-connect backend
Summary
The branch contains a new backend enabling authentication and authorization using an oauth2/openid-connect server.
Clients can either
- hand over client credentials, i.e.
client_id
and aclient_secret
(client_credentials-oauth2-specification) or - pass an
access_token
(access_token-oauth2-specification)
Note The code is based on this project which implements the mosquitto-go-auth plugin backend.
Access Token Authentication
If the backend receives the password oauthbearer_empty_password
it assumes the username to be an access_token
. Mosquitto seems to not allow empty passwords. If this can be changed the placeholder password could be removed. When using this option the the client has to reconnect using a new access_token
after the old access_token
has expired.
Client Credentials Authentication
Any other combination of username
and password
is assumed to be a client_id
/client_secret
-pair and is used to obtain an access_token
s from the authorization server regularly. Therefore client do not have to reconnect after token expiry in this case.
Requesting Topic Permissions
In both cases the available access_token
is used to request the servers /userinfo
-endpoint (userinfo-openid-specificaton). The backend expects the response of this request to look like
{
"sub": "<username>",
"mqtt": {
"topics": {
"read": ["/test/#", "/test/read/#],
"write": ["/test/#","/test/write/#]
},
"superuser": false
}
}
which contains the allowed topics for reading and writing corresponding to the provided access_token
.
Tests
Tests are implemented by using a mock oauth2 server.
Hi, @imperaton, and thanks for the contribution!
Just a heads-up: I don't have the time to go over it right now, so it might take me some days to review it.
Thank you for the review. I'll add some modifications.
In case of your remarks regarding the cache and the pointer I have some further questions, as written above.
Hi @imperaton,
I'm a user of mosquitto-go-auth-oauth2, and I'm really interested to have such a feature directly in mosquitto-go-auth
.
I have some remarks on your PR:
- As scopes are optional, if no scope are provided, no scope should be send to Oauth2 server instead of 'all'. If user want 'all' scope, he should set
oauth_scopes
accordingly. I know that the same problem is in mosquitto-go-auth-oauth2 too, I've just made a PR, - Your PR only support Client Credentials flow, which seems, in my opinion, really restrictive, as only confidential clients should use Client Credentials flow. I prefer the way the original plugin works, with a user context. Maybe you should allow both functions ?
* As scopes are optional, if no scope are provided, no scope should be send to Oauth2 server instead of 'all'. If user want 'all' scope, he should set `oauth_scopes` accordingly. I know that the same problem is in [mosquitto-go-auth-oauth2](https://github.com/gewv-tu-dresden/mosquitto-go-auth-oauth2) too, I've just made a [PR](https://github.com/gewv-tu-dresden/mosquitto-go-auth-oauth2/pull/12),
Seems reasonable to me. I changed it.
* Your PR only support Client Credentials flow, which seems, in my opinion, really restrictive, as only confidential clients should use Client Credentials flow. I prefer the way the original plugin works, with a user context. Maybe you should allow both functions ?
In mosquitto-go-auth-oauth2 two methods are supported:
- Using Client Credentials as mqtt-username and -password
- three-legged oauth2-flow using a oauth2-token as mqtt-username and an empty password
see GetUser-Function.
I replicated this behaviour with the single change, that the mqtt-password oauthbearer_empty_password
must be specified if the mqtt-username should be interpreted as oauth2-token. I did this because Mosquitto doesnt seem to allow empty passwords anymore.
I wonder if mosquitto would allow the go-auth-plugin to receive the contents of a mqtt 5.0 AUTH-Pacakage. This could be used by clients to send oauth2-tokens regularly so that the client does not have to reconnect if the current token expired.
I replicated this behaviour with the single change, that the mqtt-password
oauthbearer_empty_password
must be specified if the mqtt-username should be interpreted as oauth2-token. I did this because Mosquitto doesnt seem to allow empty passwords anymore.
You're right, I missed those ones.
You can use Password grant type too: username + password + client id + client secret. That's the flow I was talking about. So, it seems there is 3 supported methods.
I just checked your code, it seems that it can handle password grant type. So it's only the documentation that does not contain all possible flows.
I'll try to test all the flows today or tomorrow.
I just checked your code, it seems that it can handle password grant type. So it's only the documentation that does not contain all possible flows.
I'll try to test all the flows today or tomorrow.
My bad, password grant type doesn't work. For example, client secret read from config file is missing from your PR, see here.
@Booyaabes Yes, I dropped the username + password
flow in favor of the client credentials
flow.
I did this because I needed a permanent method (when using token a reconnect is necessary periodically) for authentication/authorization of trusted services which access their own resources. The right method for this is the `client credentials see (i.e. see this source).
OAuth2 has been designed to not give an application hold on users username/password
-combinations. This source states the method should not be used in practice.
If one one wants to tie mosquitto topic access to users (corresponding to persons) the application should obtain an access token by redirecting to keycloak (authorization code grant). The use of such an access token is supported with the current state of the mosquitto-go-auth
oauth2-backend.
Furthermore I cannot support the both methods at the same time, since mosquitto-go-auth
can't tell if it received a client_id/client_secret- or username/password-pair. Therefore I am pleading for leaving the authorization flows as they are right now.
Yes, you're right @tilmann-bartsch.
I tested the plugin again with a minimal setup to be sure everything works as aspected:
https://github.com/tilmann-bartsch/mqtt-oauth2-test
@iegomez The Merge Request should be ready now.
@tilmann-bartsch @Booyaabes sorry again for the time taken, I'm just checking on my latest review to see if you're still interested in going forward with this PR. If not, no worries and thank you again; I'll take a new look and try to finish it up in that case.
Cheers!
@tilmann-bartsch @Booyaabes I've been doing a cleanup of the repo these past few days and just wanted to check again on this.
@iegomez Thank for the comments you made in one of the previous replies. Unfortunately I was not able to go forward with the PR in the last months and the situation won't change until September.
Still I would be happy to see the PR finished if you have the time for it.