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

Hard Coded OIDC scopes limit IDP control of scopes #5725

Closed
jon-nfc opened this issue Jan 23, 2024 · 11 comments · Fixed by #5856
Closed

Hard Coded OIDC scopes limit IDP control of scopes #5725

jon-nfc opened this issue Jan 23, 2024 · 11 comments · Fixed by #5856

Comments

@jon-nfc
Copy link

jon-nfc commented Jan 23, 2024

Is your feature request related to a problem? Please describe.
The current implementation of oidc auth has hard coded client scopes. my requests to the IDP (keycloak, in my case) has the following scopes in the URL scope=openid%20profile%20email%20groups apart from oidc the other scope names should be customizable.

Why? as this enables the IDP to be setup to suit so as to limit what information is passed to a client, regardless of what's requested. This is a must considering privacy and in some areas mandated by legislation as it is in my country when dealing with personal information. Although there is an argument to be made that a group is not personal information, however that depends on which side of the fence you site on.

use case as an example:

  • users/groups stored within ldap.
  • IDP is synced with ldap. users and groups.
  • any requirement for profile scoped information which deviates from a standard profile scope gets it's own scope created specifically to suit the application using the info and only contains what is required for the application, this includes additional required information for the token requested
  • any requirement for a group scope will not use the standard group scope. all groups the user is part of are not required for authorization. a custom group scope is created with the client roles used as the "groups" for the application. This aids significantly as token can easily be larger that is allowed for a url and/or cookie. this is dependent upon the application however.

Describe the solution you'd like
to be able to specify the oidc scope names. no hard coded scope names outside of oidc. What information is required from the IDP be documented. This will aid in setting up scopes in accordance with what ever policy the IDP uses and provide what is required to be within the token from the IDP. The reality is, as long as what is required for meshcentral from the IDP is known, a single scope could be used, splitting the scope up is not required.

Describe alternatives you've considered
There is no alternative. There is an exception, using the hard coded group scope which generally will contain all of the groups the user is part of. However this is not a solution as the token is too large and passing personal information not required by an application is not within the confines of limiting access to personal information as is a requirement from my end. In the same light, if another application is using that "group scope" one of the two applications will receive information not required for it to function. I'm aware of group filtering, however the client is still passed information not required by it, so is also not an option.

Additional context
Add any other context or screenshots about the feature request here.

On a side note, credit to the developer(s) of meshcentral. It's not often that I test a product for implementation and when doing so come across an issue that needs to be resolved and that there already be an existing feature to solve that problem. As it stands now, this is the only issue that I've found. I do hope that you are proud of what you have achieved because if I was just to say I was impressed, would be an understatement. great work.

@si458
Copy link
Collaborator

si458 commented Jan 23, 2024

Thanks for the request, I'm going to sound like a complete noob here now
Do u have any guides on setting up/connecting to a free oidc provider?
I have never used one before, but if I got it working I could look at making the enhancement request for you! I just need some sort of guides to point me in the direction of understanding it and setting it all up

@jon-nfc
Copy link
Author

jon-nfc commented Jan 23, 2024

Thanks for the request, I'm going to sound like a complete noob here now

All good. I'll help any way I can.

Do u have any guides on setting up/connecting to a free oidc provider?

what in particular? how to setup the IDP? how a client should connect?

I have never used one before, but if I got it working I could look at making the enhancement request for you! I just need some sort of guides to point me in the direction of understanding it and setting it all up

if you could clarify what in particular you need, I could point you in the right direction or even provide aid in setting up (guide, docker-compose file etc)

@si458
Copy link
Collaborator

si458 commented Jan 23, 2024

Docs/guides to all of it really? Sorry my knowledge of authentication stuff is abit slim to say the least. Docker examples would be good as I can set it up on my server and then get my dev meshcentral to talk to it!

@jon-nfc
Copy link
Author

jon-nfc commented Jan 23, 2024

happy to provde a docker-compose file for you that will contain the following services: keycloak and postgres. Keycloak is an open source IDP that offers SAML and OIDC and postgres is the DB that it uses. I'll also provide a screen cast of setting up an OIDC client and as per the use case in OP. same same for the required config.json entries to connect to it. This'll provide a local IDP that you can test against within dev.

Let me know if this suits, if helpful and on you notifying I'll get it created.

although TBH, the minimalist change required is to provide an option within config.json to set the scope names, if none specified, then the default values be used. from the documentation side of the house, what ever claim names are part of the requested scopes be documented as this would then enable scopes to be setup in accordance with IDP policy and it be known what meshcentral needs to function. To aid in This if you build dev containers (using docker at the moment), I am happy to test as soon as it's available so as to catch any bugs etc prior to release. or an alternative the PR git url so that I could clone and build and run locally to test.

@si458
Copy link
Collaborator

si458 commented Jan 23, 2024

Sure plz do share! My email is on my github profile.
Currently every time we push to the master branch github actions already creates a master docker image for people to test! Then when we do a release it does a number release too! ghcr.io/ylianst/meshcentral:master

@jon-nfc
Copy link
Author

jon-nfc commented Jan 23, 2024

righto, I'll keep you posted. I'll post it to the issue so you only have to look in one place. FYI, its just past midnight here so may not be completed tonight, however will have it to you within 24-hours. Thanks for the assistance and your time!!

@si458
Copy link
Collaborator

si458 commented Jan 23, 2024

No rush at all! I like fixing bugs/enhancements with meshcentral as it's an amazing tool!

@jon-nfc
Copy link
Author

jon-nfc commented Jan 23, 2024

@si458,

Update. here's what I've got so far.

Assumptions made in relation to this config:

  • that mesh central is using and can be reached on dns name assist.local, if this is your local machine editing /etc/hosts will suffice

    if this is not the case, then everywhere in any of the config files below that have dns name assist.local will need to be updated to the dns name chosen. localhost can't be used with keycloak as it will not pass the token to the client as part of the auth request/response.

  • keycloak is deployed on the same machine as meshcentral as it's setup to be accessed on localhost.

    Currently having issues getting keycloak to pass the token to meshcentral over http/80. which normally would be a security issue, however in dev not so much.
    It may end up being a problem which requires that a reverse proxy be setup to do the TLS termination for keycloak to work. at this stage, leave it with me if you cant figure out the reverse-proxy set-up yourself and I'll work on this again after some sleep.

docker-compose.yaml

sets up keycloak instance in dev mode. which requires no external database

---
# docker pull keycloak/keycloak:21.1.1-0

version: '3.3'
services:

  keycloak:
    image: keycloak/keycloak:21.1.1
    restart: always
    hostname: keycloak
    command: start-dev
    ports:
      - "8080:8080"
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
      KC_HOSTNAME: localhost
      KC_HOSTNAME_PORT: 8080
    volumes:
      - keycloak_data:/opt/keycloak


volumes:

  keycloak_data:
oidc client for keycloak - client.json
  1. save this as a .json
  2. import by , navigating to keycloak http://localhost:8080/
  3. login with admin/admin.
  4. click on clients, left hand nav bar
  5. click import. middle of screen.
  6. navigate to the saved json file and leave the defaults as are set.
  7. click save.
{
  "clientId": "https://assist.local/",
  "name": "Mesh Central",
  "description": "",
  "rootUrl": "https://assist.local/",
  "adminUrl": "https://localhost/",
  "baseUrl": "",
  "surrogateAuthRequired": false,
  "enabled": true,
  "alwaysDisplayInConsole": false,
  "clientAuthenticatorType": "client-secret",
  "secret": "8OWRcXpThUAlsHpO6KHxA1vsbioF2Z1d",
  "redirectUris": [
    "/oidc-callback*",
    "*"
  ],
  "webOrigins": [],
  "notBefore": 0,
  "bearerOnly": false,
  "consentRequired": false,
  "standardFlowEnabled": true,
  "implicitFlowEnabled": false,
  "directAccessGrantsEnabled": false,
  "serviceAccountsEnabled": true,
  "authorizationServicesEnabled": true,
  "publicClient": false,
  "frontchannelLogout": true,
  "protocol": "openid-connect",
  "attributes": {
    "client.secret.creation.time": "1706009078",
    "oauth2.device.authorization.grant.enabled": "false",
    "backchannel.logout.revoke.offline.tokens": "false",
    "use.refresh.tokens": "true",
    "oidc.ciba.grant.enabled": "false",
    "backchannel.logout.session.required": "true",
    "client_credentials.use_refresh_token": "false",
    "acr.loa.map": "{}",
    "require.pushed.authorization.requests": "false",
    "tls.client.certificate.bound.access.tokens": "false",
    "display.on.consent.screen": "false",
    "token.response.type.bearer.lower-case": "false"
  },
  "authenticationFlowBindingOverrides": {},
  "fullScopeAllowed": true,
  "nodeReRegistrationTimeout": -1,
  "protocolMappers": [
    {
      "name": "Client Host",
      "protocol": "openid-connect",
      "protocolMapper": "oidc-usersessionmodel-note-mapper",
      "consentRequired": false,
      "config": {
        "user.session.note": "clientHost",
        "userinfo.token.claim": "true",
        "id.token.claim": "true",
        "access.token.claim": "true",
        "claim.name": "clientHost",
        "jsonType.label": "String"
      }
    },
    {
      "name": "Client ID",
      "protocol": "openid-connect",
      "protocolMapper": "oidc-usersessionmodel-note-mapper",
      "consentRequired": false,
      "config": {
        "user.session.note": "client_id",
        "userinfo.token.claim": "true",
        "id.token.claim": "true",
        "access.token.claim": "true",
        "claim.name": "client_id",
        "jsonType.label": "String"
      }
    },
    {
      "name": "Client IP Address",
      "protocol": "openid-connect",
      "protocolMapper": "oidc-usersessionmodel-note-mapper",
      "consentRequired": false,
      "config": {
        "user.session.note": "clientAddress",
        "userinfo.token.claim": "true",
        "id.token.claim": "true",
        "access.token.claim": "true",
        "claim.name": "clientAddress",
        "jsonType.label": "String"
      }
    }
  ],
  "defaultClientScopes": [
    "web-origins",
    "acr",
    "profile",
    "groups",
    "email"
  ],
  "optionalClientScopes": [
    "offline_access"
  ],
  "access": {
    "view": true,
    "configure": true,
    "manage": true
  }
}
truncated meshcentral config.yaml

this is whats needed to be added to the meshcentral config.json file to setup the client to connect to the keycloak using oidc.

note: the client secret matches the keycloak config above.

{
  "domains": {
    "": {
      
      "authStrategies": {
        "oidc": {
          "issuer": "http://localhost:8080/realms/master",
          "authorizationURL": "http://localhost:8080/realms/master/protocol/openid-connect/auth",
          "clientid": "https://assist.local/",
          "clientsecret": "8OWRcXpThUAlsHpO6KHxA1vsbioF2Z1d",
          "callbackURL": "https://assist.local/oidc-callback",
          "tokenURL": "http://localhost:8080/realms/master/protocol/openid-connect/token",
          "userInfoURL": "http://localhost:8080/realms/master/protocol/openid-connect/userinfo",
          "groups": {
            "required": [
              "user"
            ],
            "siteadmin": [
              "administrator"
            ],
            "sync": {
              "enabled": true
            }
          },
          "newAccounts": true
        }
      }
    }
  }
}

Video guides

Screencast guides for keycloak. they're webm, so no sound. If I click through too fast, just pause the video/rewind. keycloak docs can be found at https://www.keycloak.org/guides#server should you require it.

Create client scope

client-scope-creation.webm

Addendum: do enable multi-valued in the mapper

Addendum to scope name

keycloak-scope-group-name-addendum.webm

Adding roles to client and to a user

adding-roles-to-client.webm

If this is enough to get you started, please let me know. In the same token also, if what I've provided is lacking let me know where and I'll adjust/add to accordingly.

@jon-nfc
Copy link
Author

jon-nfc commented Jan 31, 2024

any update on this issue?

@si458
Copy link
Collaborator

si458 commented Jan 31, 2024

sorry havnt looked at it yet, i will have a look this week when i can

@mstrhakr
Copy link
Contributor

This will be fixed by #5856

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

Successfully merging a pull request may close this issue.

3 participants