Adds OIDC support#1033
Conversation
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
|
I stand corrected, we need a custom approach here, which at the moment is bia PyJWT (though we might be able to do it manually is we don't want to take a dependency, but this should work as-is right now) |
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
3b3d768 to
908a117
Compare
|
Thanks for working on this. I'll try to dig into the changes and test them within the next few days. I do think that requiring every user to register a fork of Moonraker as an oauth app may be a show stopper. I don't think GitHub intends applications to use OAuth in this manner, and as we previously discussed it would seem to limit users to a single instance of Moonraker. I did take the time to re-familiarize myself with GitHub's oauth documentation, and I suspect we are going to have to implement the device flow. This would allow Moonraker to register a single app, and the client ID would be included in the source. There are still rate limits and other issues I need to work out, but its something I'm willing to try to tackle. I do suspect that some of the code in this PR will be applicable though. |
To be honest, I actually thought the whole device flow was not a standard, I see now it is https://datatracker.ietf.org/doc/html/rfc8628 So yeah, I fully agree with you, this might be the best course of action. I am fine with having pre-configured Client ID on the code base to make it easier for users, but I do believe we should also have that configurable for those who want to use a custom provider (I've seen a lot of self-hosting solutions on this by the way!) I might leave this one as is and take a look at how to implement the above RFC now... 😁 |
'Application' refers to individual deployments in the context of OAuth, and every user registering their own application is indeed how Github (and other OAuth providers) intend their service to be used.
The Name/Description fields only exist for user convenience - users running multiple instances of Moonraker are expected to register separate applications for each. This should implement a configurable group check if you intend it to be used with public OAuth providers - having access to any Github/Google/etc account would currently be enough to get access. Though we arguably shouldn't, using public OAuth providers to secure private applications is hard to do safely for individual users and tends to require provider-specific implementations. -- As a more general authentication note, we should strongly consider replacing the client-facing token flow with cookie-based sessions for OAuth - giving access tokens to a SPA (ie Fluidd/Mainsail) turns any XSS vulnerability it might have into a token compromise. The same issue applies to the existing authentication methods as well, though it'd represent a extensive breaking change for those. |
In general I agree that the application refers to deployments, at least with regard to the web/code flow. That said, its general use case is for web deployments, where users are not expected to register the application with their OAuth provider. The best analog I can give right now is VSCode. You can log in to GitHub through VSCode, presumably using an implementation of OAuth. It is not necessary for the user register their own instances of VSCode on GitHub. If users were required to do so then I suspect very limited subset would bother. In our use case the Device Flow solves this. Authentication can occur using a primary client ID, however it doesn't prohibit users from creating and registering their own if they wish. For example, a print farm may prefer to use their own client ID.
The front end should not need OAuth tokens. Authentication should be strictly between Moonraker and the OAuth Provider, the front end only needs the verification uri and the user code. Once the user is authenticated Moonraker would generate its own JWTs to be used by the front end for authorization. These tokens are relatively short lived unless the attacker manages to get a refresh token. Even in that scenario the damage is limited vs a compromised OAuth token. We need to avoid depending on cookies as we cannot assume a client is a web app running in a browser. This is another reason why the OAuth 2 device flow is the likely best fit for Moonraker. |
Adds OIDC support to Moonraker.
I have successfully tested this with both Github and Google, expect others will work too!
To test, you will need to create a new OAuth/OIDC configuration in some provider, though GitHub is rather easy:
On moonraker.conf, add this config:
[oidc github] client_id: XXXXXXX client_secret: XXXXXXX authorization_url: https://github.com/login/oauth/authorize token_url: https://github.com/login/oauth/access_token userinfo_url: https://api.github.com/user jwks_uri: https://token.actions.githubusercontent.com/.well-known/jwks scope: openid profile email redirect_uri: http://localhost:7125/access/oidc/callbackThis NodeJs script will help testing: https://gist.github.com/pedrolamas/9ebfbd835c10ffe2d626de2b0ffdac22
Just save the script somewhere and run with
node oidcTest.mjsthen follow the script instructions.Resolves #1008