Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement oauth2 monitors #3119

Merged
merged 7 commits into from
Aug 2, 2023
Merged

Conversation

hegerdes
Copy link
Contributor

@hegerdes hegerdes commented May 2, 2023

⚠️⚠️⚠️ Since we do not accept all types of pull requests and do not want to waste your time. Please be sure that you have read pull request rules:
https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md#can-i-create-a-pull-request-for-uptime-kuma

Tick the checkbox if you understand [x]:

  • I have read and understand the pull request rules.

Description

In times of increasing security threats, securing sensitive data is becoming more and more important. Long-lived credentials pose an increasing risk. The Oauth2 standard tries to solve this and other threats by creating short-lived tokens that are only authorized to access specific parts (scopes) of the services. The list of Oauth2 providers is ever-growing (Azure AD, AWS Cognito, Google Auth, Facebook, GitHub...). Companies and individuals use these authentication techniques to provide a central user management level while also providing a low entry barrier for new users without sacrificing security.

Testing tool need to keep up with this development and support these authentication methods. For machine to machine communication the Oauth2 Spec suggest the Client-Credential Flow (explained here)

With this PR I want to implement the Oauth2 client-credential flow to support these new authentication methods. I already provided a example implementation since one of my clients needed it. It also implements the feature requested in #659 and #2280.

So far it was tested with:

The library is used (openid-client) is one of the recommended libs by the official oauth2 site and is created/maintained by one of the contributes of the oauth2 spec.

Fixes #659, #2280

Update:
Since the OAuth2 spec is so broad, I made the provided implementation more specific to allow for future changes without having to break old setups. I also added the missing error handling.

The following setup is implemented with this PR:

  • Oauth2 Client Credential Grant
    • with Authentication method: client_secret_basic
    • with Authentication method: client_secret_post

Not implemented are client_secret_jwt and private_key_jwt since both methods require continuous crafting and signing new JWTs that are based on user provided input and time. Providing a user interface supporting this is quiet hard, therefore hardly any other application support this out of the box, not even Postman. The usage of these not implemented authentication method is also quiet low so the effort needed to support these is not justified at the time of writing. More about these methods can be read heare.

The following providers don't support the client credential grant (yet):

  • Google Auth (currently use service accounts)
  • GitHub
    I added some docs below on how to set up the Azure AD provider.

Type of change

Please delete any options that are not relevant.

  • User interface (UI)
  • New feature (non-breaking change which adds functionality)

Checklist

  • My code follows the style guidelines of this project
  • I ran ESLint and other linters for modified files
  • I have performed a self-review of my own code and tested it
  • I have commented my code, particularly in hard-to-understand areas
    (including JSDoc for methods)
  • My changes generate no new warnings
  • My code needed automated testing. I have added them (this is optional task)

Screenshots (if any)

UI Demo:
image

@hegerdes hegerdes changed the title [empty commit] pull request for implement oauth2 monitor feat: Implement oauth2 monitors May 2, 2023
@DennisGaida
Copy link

Sorry for asking in a PR: Any way to hotpatch a docker-install or get a fresh docker install based on a PR? I don't have a npm build environment, but would love to give this a try.

@hegerdes
Copy link
Contributor Author

hegerdes commented May 3, 2023

Just to make it clear again: I opened this as a starting point for a discussion and as a reference.

But for quick testing it might be useful to provide a quick way to try it:
I can not provide a prebuild package myself but you can checkout my branch and run this Dockerfile:

FROM louislam/uptime-kuma:base-debian
WORKDIR /app

COPY package.json /app/
RUN npm install --force
COPY . .
RUN npm run build && chmod +x /app/extra/entrypoint.sh

EXPOSE 3001
VOLUME ["/app/data"]
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"]
CMD ["node", "server/server.js"]

Run docker build -t uptime-kuma-oauth . && docker run -it -p 3001:3001 uptime-kuma-oauth

cc: @DennisGaida

@louislam louislam added this to the 1.23.0 milestone May 15, 2023
@kzkvv
Copy link

kzkvv commented Jun 24, 2023

This feature will be very helpful for our team too, thank you!

@kzkvv
Copy link

kzkvv commented Jun 24, 2023

Checked this implementation with Keycloak - it works, thank you!
But looks like "scopes" field is not optional - I'm not sure is it correct in OAuth 2.0 flow or not.
image

@hegerdes
Copy link
Contributor Author

Thanks for testing and for the feedback @kzkvv

But looks like "scopes" field is not optional - I'm not sure is it correct in OAuth 2.0 flow or not.

Per spec the scope param is optional. Because of this I removed the required field from the fronted. But there are other things to consider here.

Since it is not provided in the fronted, the backend and the function receives undefined which is not optimal.
Even if it es optional in the spec, the provider may (in fact most of the time) needs it. We will have this info only after the first try.

I have the following solutions in mind:

  • Make scope required in the fronted again (not a fan of this personally)
  • Default to an empty sting for scope (not sure how every provider handles this)
  • Only add the scope to the client.grant(...) request if provided (preferred solution right now)

In all cases I will forward any oauth/oidc error to the monitor and the user can fix the monitor settings.

Any suggestions?

@CommanderStorm
Copy link
Collaborator

CommanderStorm commented Jul 8, 2023

Could you add Fixes #2280 to the description?
@hegerdes

@louislam
Copy link
Owner

louislam commented Jul 9, 2023

Trying to test it using Google oauth, but no luck. Did I do something wrong?

URL: https://example.com

I tried Desktop and Web Application.

@hegerdes
Copy link
Contributor Author

Trying to test it using Google oauth, but no luck. Did I do something wrong?

@louislam No, you did nothing wrong. I messed up:

The time I created the initial draft and tested it with Azure and Google I must have made a mistake. Google does not support the OAuth2 client credential grant, yet. Currently they use Service Accounts which are not compatible with the OAuth2 spec. However, there is a plan to integrate that into the GCP. I was either in some kind of preview program or tested with the wrong grant type. Unfraternally I cant verify that anymore since I final splitted my personal and development Google account and I did the testing with the old one :/

I retested my Azure setup to make sure I avoid any mistakes. if you want I can provide some instructions within the next few days on how to setup the provider and a demo app to help people to test it and get started. The Azure provider setup is not the without some gotchas.

Thanks for pointing this out. I'm truly sorry for this mistake.

@louislam
Copy link
Owner

@hegerdes Understand and never mind, no need to apologize. Since I don't have Azure AD or Keycloak. And @kzkvv had tested it. I trust you guys in this case.

@hegerdes
Copy link
Contributor Author

Thanks for understanding.

I will provide a small example here anyway(in the coming days), since I know getting started with oauh is hard.
As far as I know you don't need an actual subscription for Azure AD. All you need is a Microsoft account and you can log into azure and go the the AAD. There is definitely no cost for this, only some premium features require a subscription.

I don't know abou you time plannings with uptime kuma 1.23 but if you have no hurry just wait a little and maybe some else might provide additional feedback. Total up to you, I have no preference here

@louislam
Copy link
Owner

You can check the 1.23.0 milestone, probably not be released soon.
https://github.com/louislam/uptime-kuma/pulls?q=is%3Aopen+is%3Apr+milestone%3A1.23.0

@louislam louislam added the question Further information is requested label Jul 14, 2023
@hegerdes
Copy link
Contributor Author

hegerdes commented Jul 23, 2023

Setting up a OAuth2 Provider

Azure AD

For setting up a Azure AD OAuth2 client you need a Microsoft or a MS work account. As far as I know the is no need to provide a payment method and no cost associated with the free tier of AAD.

  1. Then you need to log into https://portal.azure.com, go to the AAD and choose App Registrations from the left side blade.
  2. Create a new App Registration
  3. Choose a name and select single tenant mode - you can leave the redirect URL empty
  4. Note the client id
  5. Go to Expose an API and add a Application ID URI and give it a name and remember it - leave the api prefix
  6. Go to App Roles and create a new App Role, while choosing Applications in the Allowed member type
  7. Go to API Permissions and click Add Permissions. Choose My APIs and select the created app role
  8. If needed grant admin consent
  9. Go to Certificates and Secrets and create new client secret

Now you have setup a the Azure AD provider!
With this you can test the token request with Postman.

  1. Create a new Postman Web-Request
  2. Go to Authorization and choose OAuth2
  3. Select Client Credentials grant
  4. Fill in the Token URL: https://login.microsoftonline.com/{{AZURE_TENNET_ID}}/oauth2/v2.0/token
  5. Fill in the client id from Azure App registration overview from step 4
  6. Fill in the client secret from step 9
  7. Fill in the scope with the content you choose from step 5 and add the postfix /.default. It schuld look like this: api://{{MY_APP_ROLE_URI}}/.default
  8. Now you can request a token

This token can be used to access applications protected with oauth authentication. It can be inspected using jwt.io. An possibility is to protect any website put behind a reverse proxy like nginx or traefik that is configured with the oauth2 proxy

If you have an application that is configured with the oauth2 proxy you can put in its URL into uptime-kuma and transfer the settings from the Postman parameters into uptime-kuma. Uptime-kuma should obtain a token from azure and will use it to access the url in the monitor settings.

@louislam
Copy link
Owner

louislam commented Aug 2, 2023

@hegerdes

Thanks. It is working.

image

@louislam louislam merged commit 42b5d30 into louislam:master Aug 2, 2023
@kdubb1337
Copy link

kdubb1337 commented Aug 20, 2023

@hegerdes thanks for adding this much needed feature, I've been waiting for it to be released.

I'm trying to use it with Auth0 behind an oauth2-proxy. I was able to generate an access token from the CLI following the client credentials flow, but it seems I need to add an extra field called audience to get it work (see image).

Do you think we should add an extra 'meta' field that would allow for custom parameters to be set depending on the provider?

image

@hegerdes
Copy link
Contributor Author

Thanks for raising this @kdubb1337.

This is one of the main problems that the OAuth2/OIDC standard has. It is too open for providers to implement.

The audience field strictly speaking is a:

value that identifies the Authorization Server as an intended audience. The Authorization Server MUST verify that it's an intended audience for the token. The Audience SHOULD be the URL of the Authorization Server's Token Endpoint.

The description form Auth0 (see here) sounds more like the scope field that is covered by the OAauth2 rfc6749. While Auth0 is not strictly violating the standard, they are not 100% compliant either - and do definitely not follow the most common way of implementing it.

I definitely could add an extra field for arbitrary headers to set for the auth request but that would open the door for a lot more not common ways of handling OAuth and I don't know if this is wise - specially in the first iteration of this feature.

Can you please check if Auth0 accepts the request with scope instead of audience. Maybe they implemented it for compatibility but did not document it

@kdubb1337
Copy link

@hegerdes I was able to bypass it by setting a default audience, now it will work without setting the audience which is good enough for me. I'm still getting some error on the monitor but I will look into that further.

I'll update with an Auth0 guide if I get it working. I'd like to put it in a docs/wiki area so people have a place to find how to do their specific oauth2 provider, since these will grow and have their unique quirks.

@sullivan1337
Copy link

sullivan1337 commented Dec 5, 2023

I actually just ran into needing a different audience than the URL as well.

When attempting to integrate with an OAuth endpoint there are 2 different audience options, dependent on which version of their backend auth you are using..
Has there been any other thought to adding back an optional OAuth Audience input like the allowed OAuth Scope today?

@modem7 modem7 mentioned this pull request Dec 10, 2023
2 tasks
@chakflying chakflying removed the question Further information is requested label Dec 27, 2023
@obkgroove21
Copy link

Sorry, am I blind? Where do I find the settings to setup keycloak in the Uptime-Kuma-Admin-UI?

@CommanderStorm
Copy link
Collaborator

You can configure the oauth2 montor authentification in the respecitve Http monitors Authentification section.
Screenshot:

image

Note

Since you asked for how to setup keycloak and seached in the settings part, you are likely referring to user management. That is not CURRENTLY a feature we have, but likely will in the future.
This is tracked in these issues:

@obkgroove21
Copy link

Ah got it. Yes you are right, I was looking for Keycloak-Login. Now I understand what this PR is offering.
Thanks :)

@Whity07
Copy link

Whity07 commented Dec 31, 2024

Hi sorry, i dont see the feature here? Did i miss anything? Please keep me updated.
image

@hegerdes
Copy link
Contributor Author

The feature implemented OAuth2 for monitors, not for logging in and manage uptimekuma itself via OAuth2. This is a seperat (pending) feature.

Go to monitors create a new and when you add auth to the monitoring target you can select OAuth2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

oAuth2 support for HTTP Monitors (Authorization Providers)
10 participants