argoproj / argo-cd

Declarative Continuous Deployment for Kubernetes
https://argo-cd.readthedocs.io
Apache License 2.0
17.46k stars 5.3k forks source link

SSO issue with existing OIDC Provider #6857

Open cnukwas opened 3 years ago

cnukwas commented 3 years ago

Configured Argo with following OIDC configuration to work with our internal provider. Postman tool returns correct scopes but fails with Argo due to the way /authorize call is made as mentioned below.

OIDC configuration is below per Argo docs

oidcConfig: |
    name: SAFE
    issuer: https://myoidc.provider.com/
    clientID: abc123456sfsfsdfsdf
    clientSecret: sfsfsdffffffffff
    requestedScopes: ["openid", "argo-admin", "GroupA", "GroupB", "GroupC", "GroupCD1"]
    requestedIDTokenClaims:
      sub:
        essential: true
      email:
        essential: true

RBAC enforcement YAML with following configuration as per argocd-rbac.yaml

argocd-rbac-cm.yaml scopes data:

scopes: '[argo-admin, GroupA, GroupB, GroupC, GroupCD1]'

I see that Argo is making following call with correct scopes but is sending a + sign for delimiting requested scopes string. I believe it's supposed to encode space character as %20 not as a plus sign. Due to this, the APM tokens don't have correct scopes, leading to permission errors for any Argo functions after logging into web UI.

https://my.oidcprovider.com/authorize?claims=%7B%22id_token%22%3A%7B%22email%22%3A%7B%22essential%22%3Atrue%7D%2C%22sub%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&client_id=asddddddddddddddddddd&redirect_uri=https%3A%2F%2Fopenshift-gitops-server-openshift-gitops.apps.os-dev-test.com%2Fauth%2Fcallback&response_type=code&scope=openid+argo-admin+GroupA+GroupB+GroupC+GroupCD1&state=vexgRhBLqJ

To Reproduce

Configure Argo CD to use an existing OIDC provider as per the documentation and notice /authorize call made to the OIDC provider when requesting configured scopes. The call is sending plus signs instead of encoding space characters as %20. This is causing an issue on the provider end and not returning requested scopes.

Expected behavior

Return requested scopes, in this case GroupA, GroupB, GroupC and GroupCD1 in the scope.

Screenshots

N/A

Version

v2.0.5

Logs

Argo logs and argocd.token cookie token doesn't have requested scopes.
cnukwas commented 3 years ago

@jannfis thanks for the update. Surprised to see none else has reported this issue until now. Is there a rough estimate to have this fixed or any temporary workaround with a configuration override? Our internal dev team is open to fix this issue, but not sure how and when this would get to OpenShift version of Argo since we're using OpenShift GitOps operator. Should we contact Red Hat OpenShift team?

Thanks

jannfis commented 3 years ago

After a little research, I'm unsure about this being an issue with white space. Are you sure that your OIDC provider actually can process the scopes you specify - they seem to look a little weird to me, considering you specify some group names as scope.

Have you successfully got it working by manually issuing the request using %20 instead of + and inspecting the returned token?

cnukwas commented 3 years ago

We're using F5 APM and I see that scopes are returned correctly when tested using space delimited scopes using Postman tool. The scopes are not returned when I replace a space with plus sign for the requested scopes even with the Postman tool. I'm not sure how to test with the OIDC provider(APM) manually, let me know how to do that and will give that a try. On a side note, we found the plus sign issue by comparing other internal applications requests that are working versus Argo calls.

jannfis commented 3 years ago

Hey @cnukwas, I'm not very familiar with F5 APM but a little research suggests that it uses Okta as OIDC backend. Many people do integrate Argo CD successfully with Okta, but probably they set-up a little different. We do have community contributed docs for Okta integration at https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/okta/#oidc-without-dex

I think you need to put the groups into a dedicated scope (and then add claims for it), instead of having each group provided as its own scope as your example config above suggests.

cnukwas commented 3 years ago

We even reached out to F5 APM support and they have said that Argo implementation is not OAuth spec complaint with regards to the scopes. See Access Token Scope section. Okta groups maybe working different, our set up requires client application requesting explicit scopes, instead of returning all the groups the user is part of.

The value of the scope parameter is expressed as a list of space- delimited, case-sensitive strings. The strings are defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope.

cnukwas commented 2 years ago

Any idea when this issue will be fixed?

harrietgrace commented 1 year ago

@cnukwas I know this is a very old issue, but are you still using F5 APM as your Provider?

Looking at a couple of different aspects here - it could certainly be the groups issue as @jannfis mentioned above, but it may also be a restriction on the F5 APM side in how they decode their URLs.

The OAuth spec section you have linked to (RFC 6749, section 3.3) only specifies that scopes must be "space-delimited", it doesn't specify how to encode that space in a URL. Both %20 and + are valid encodings for a space, and both should be decoded back to a space - however I assume this depends on which library you're using to decode.

The Argo CD implementation uses the golang.org/x/oauth2 library to generate the URL with your data. That OAuth2 go library uses spaces as the delimiter between the scopes, and then goes on to use the net/url library to encode the scopes for the URL with plus signs for spaces. This is entirely compliant with RFC 6749 section 3.3.

If a Provider is using a decoding library that is expecting spaces to only ever be encoded into %20 then they're going to have issues with URLs that were encoded by that go library.