argoproj / argo-cd

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

SSO for Existing OIDC Provider returning 401 because of missing client secret #2932

Closed jl431 closed 4 years ago

jl431 commented 4 years ago

My setup is running Argocd 1.3.6. I'm able to login via the web browser via SSO with no problem. However, when I attempt to login using the CLI, I get the following error:

$ argocd login argocd-dev.mycompany.com --sso --username me@mycompany.com
WARNING: server certificate had error: x509: certificate is valid for ... Proceed insecurely (y/n)? y
Opening browser for authentication
INFO[0003] RequestedClaims: map[groups:essential:true ] 
Performing authorization_code flow login: https://login.windows.net/.../oauth2/authorize?access_type=offline&claims=%7B%22id_token%22%3A%7B%22groups%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&client_id=...&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fauth%2Fcallback&response_type=code&scope=openid+profile+email+groups&state=SACdbDdlaC
FATA[0005] oauth2: cannot fetch token: 401 Unauthorized
Response: {"error":"invalid_client","error_description":"AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.\r\nTrace ID: 0e3cc8df-2a95-4440-b71a-2d21ca860000\r\nCorrelation ID: adbccf25-c119-4f4f-9dec-c425acbbdd5e\r\nTimestamp: 2019-12-31 02:45:49Z","error_codes":[7000218],"timestamp":"2019-12-31 02:45:49Z","trace_id":"0e3cc8df-2a95-4440-b71a-2d21ca860000","correlation_id":"adbccf25-c119-4f4f-9dec-c425acbbdd5e","error_uri":"https://login.windows.net/error?code=7000218"} 

I followed the documentation here: https://argoproj.github.io/argo-cd/operator-manual/sso/#existing-oidc-provider

    config:
    url: https://argocd-dev.mycompany.com
    oidc.config: |
      name: Azure
      clientID: ...
      cliClientID: ...
      clientSecret: ...
      issuer: https://sts.windows.net/.../
      # Optional set of OIDC claims to request on the ID token.
      requestedIDTokenClaims: {"groups": {"essential": true}}

Being able to login via the UI, but not via the CLI leads me to believe this is a bug. Am I missing anything obvious in my config? I'm happy to provide any config that maybe useful for debug.

Version details

  argocd: v1.3.6+89be1c9
  BuildDate: 2019-12-10T22:48:19Z
  GitCommit: 89be1c9ce6db0f727c81277c1cfdfb1e385bf248
  GitTreeState: clean
  GoVersion: go1.12.6
  Compiler: gc
  Platform: darwin/amd64
argocd-server: v1.3.6+89be1c9
  BuildDate: 2019-12-10T22:47:48Z
  GitCommit: 89be1c9ce6db0f727c81277c1cfdfb1e385bf248
  GitTreeState: clean
  GoVersion: go1.12.6
  Compiler: gc
  Platform: linux/amd64
  Ksonnet Version: v0.13.1
  Kustomize Version: Version: {Version:kustomize/v3.2.1 GitCommit:d89b448c745937f0cf1936162f26a5aac688f840 BuildDate:2019-09-27T00:10:52Z GoOs:linux GoArch:amd64}
  Helm Version: v2.15.2
  Kubectl Version: v1.14.0

In commands/login.go, it appears oauth2conf.ClientSecret is never getting populated. func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCConfig, oauth2conf *oauth2.Config, provider *oidc.Provider) (string, string) { ...

I've just verified this bug doesn't appear in v1.2.0, but does in 1.3.0.

devstein commented 4 years ago

I'm also facing this issue. See my post in the slack channel https://argoproj.slack.com/archives/CASHNF6MS/p1577923783162400

@jl431 Thanks for making an issue!

zeph commented 4 years ago

confirmed on 1.4.2 as well, I will closed my bug https://github.com/argoproj/argo-cd/issues/3054 as duplicate of this

zeph commented 4 years ago

@devstein how to get invited to such slack argoproj org?

devstein commented 4 years ago

@zeph https://argoproj.github.io/community/join-slack

zeph commented 4 years ago

tnx @devstein

Subreptivus commented 4 years ago

Maybe this will save someone some time. In my case the problem was with Azure AD. Starting from v.1.3.x argocd-cli will perform authorization_code flow if provider supports it. In case of Azure AD (the same is true for Google), there are two kinds of platforms supported: web applications and mobile and desktop applications (so called public in terms of Google). In authorization_code flow you need to specify client_secret when requesting the token (second phase), but argocd-cli aren't doing that (because they don't want to show that in console) for web application platform. So for Azure AD, you just need to add mobile and desktop applications platform with Redirect URI: http://localhost:8085/auth/callback, or create separate one and use cliClientID with it's id in argocd configmap.

zeph commented 4 years ago

@Subreptivus solution works for keycloak too, it needs (client's scope) public p.s. on top of the damn offline_access role to be defined on the Realm level https://www.keycloak.org/docs/4.8/server_admin/#_offline-access

Sharathmk99 commented 4 years ago

After enabling Azure SSO, admin user stops working. Able to successfully authenticate admin user, but getting 401 error for other APIs. Do i need to add any other policy for admin user?

Existing policy,

policy.default: role:readonly
policy.default: role:readonly
policy.csv: |
  p, role:org-admin, applications, *, */*, allow
  p, role:org-admin, clusters, get, *, allow
  p, role:org-admin, repositories, get, *, allow
  p, role:org-admin, repositories, create, *, allow
  p, role:org-admin, repositories, update, *, allow
  p, role:org-admin, repositories, delete, *, allow
  g, "${var.argo_cd_azure_ad_group_admin}", role:org-admin
judexzhu commented 4 years ago

@zeph If you don't mind, may I know how you have this fix(or workaround) for Keycloak.

Do you mean we need to create a "public" client-scope for the realm? and add this client-scope to client(which I did, but still not working)

image

I also have added "http://localhost:8085/auth/callback" to the "Valid Redirect URIs". Give the user "offline_access" realm role.

but seems it didn't generate the offline token image

login via UI is fine but always failed from CLI image

onelapahead commented 4 years ago

See follow-up comment below


Similarly when trying to do this via Okta, I followed @Subreptivus 's advice for making a public client. ~In Okta speak its an SPA app.~ Its a native app. Only issue I'm encountering is Okta requires PKCE for public clients to do the auth code flow, but it seems the CLI does not support it:

$ argocd login --insecure --grpc-web --sso argocd.example.com
Opening browser for authentication
INFO[0002] RequestedClaims: map[groups:essential:true ] 
Performing authorization_code flow login: https://dev-*****.okta.com/oauth2/******/v1/authorize?access_type=offline&claims=%7B%22id_token%22%3A%7B%22groups%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&client_id=0oaaqeuntucmCcCJ94x6&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fauth%2Fcallback&response_type=code&scope=openid+profile+email+groups+offline_access&state=lLkFhKoUqV
FATA[0004] invalid_request: PKCE code challenge is required when the token endpoint authentication method is 'NONE'. 
Screen Shot 2020-04-30 at 12 20 14 PM Screen Shot 2020-04-30 at 12 20 45 PM

I'm trying to figure out to disable PKCE for public clients in Okta, but is this on the roadmap for the CLI? Should I open a separate issue for PKCE support?

onelapahead commented 4 years ago

Derp making some progress. Okta has several different ways to create an OIDC app, and each allows you to edit the app in different ways. SPA was the wrong type which makes perfect sense. You just need to make a native app and register HTTP callbacks:

Screen Shot 2020-04-30 at 4 21 25 PM

However with the public client it still requires PKCE. And then if I try to disable it, it gives me a client secret which gets a 401:

$ argocd login --insecure --grpc-web --sso argocd.company.com
Opening browser for authentication
INFO[0003] RequestedClaims: map[groups:essential:true ] 
Performing authorization_code flow login: https://dev-******.okta.com/oauth2/*****/v1/authorize?access_type=offline&claims=%7B%22id_token%22%3A%7B%22groups%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&client_id=0oaaqvhe2lctthkIe4x6&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fauth%2Fcallback&response_type=code&scope=openid+profile+email+groups+offline_access&state=zQcFSJZjDZ
FATA[0004] oauth2: cannot fetch token: 401 Unauthorized
Response: {"error":"invalid_client","error_description":"Client authentication failed. Either the client or the client credentials are invalid."} 

So cliClientSecret is not a config field. The CLI always tries to do a public client auth code grant. According to my Okta support engineer you cannot disable PKCE without then needing to use client ID/secret so I think this needs to be a separate issue for the CLI to support PKCE.

johnpekcan commented 4 years ago

I believe I'm having similar issues with Amazon Cognito as @hfuss . I believe he's asked these questions in the slack channel as well:

so for the ArgoCD CLI: is it supposed to be a public client which participates in the auth code flow? if so, it seems like it will need to support PKCE for IDPs like Okta and Cognito or is it supposed to be an implicit client and are we configuring argocd and/or the IDP incorrectly?

mbarrien commented 4 years ago

A potential solution for anyone watching this issue.

I got PKCE integrated into the argocd login CLI command. I verified that the code worked using Okta (successfully got login and interacted with our Argo CD deployment). Okta setup required setting up a separate OAuth application of "Native" type that is separate from the the Web application type for the Argo CD web UI. This code is untested on any other provider (e.g. dex, Azure, Cognito) so I don't know if the additional fields passed to the servers may interfere with their operation. (Even though the RFC7636 says these fields shouldn't interfere, who knows what happens in practice.) There are also no unit tests.

Unfortunately, due to work priorities, I don't think I have the bandwidth to push this all the way through to a mature PR at the moment. But if anyone else in the community wants to run with this change and write the tests, verify compatibility and merge it in, go for it.

The code can be found at https://github.com/chanzuckerberg/argo-cd/commits/pkce-1.6 (This tested implementation is branched off of release-1.6 branch. There is an untested pkce branch in the same repo that is branched off of master.)

cslovell commented 3 years ago

I had this issue and it drove me nuts. What I discovered was that I had to restart the argo-server pod after creating a new key-value pair in the secret configuration:

I started the pod with a reference to the non-existed $oidc.keycloak.clientSecret:

oidc.config: |
    name: Keycloak
    issuer: https://example.com/auth/realms/cluster-admins
    clientID: argo-cd
    clientSecret: $oidc.keycloak.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]
    logoutURL: https://example.com/auth/realms/cluster-admins/protocol/openid-connect/logout?redirect_uri=https://example.com

I then followed the instructions here to set up keycloak, adding the new key-value pair to the secret config file. However, the logs of the argo server showed it was not finding the key at all.

I deleted the pod, triggering a restart, and everything worked.

jurgen-weber-deltatre commented 2 years ago

@zeph If you don't mind, may I know how you have this fix(or workaround) for Keycloak.

Do you mean we need to create a "public" client-scope for the realm? and add this client-scope to client(which I did, but still not working)

image

I also have added "http://localhost:8085/auth/callback" to the "Valid Redirect URIs". Give the user "offline_access" realm role.

but seems it didn't generate the offline token image

login via UI is fine but always failed from CLI image @judexzhu Did you get this working? I am trying all of these things also but only the UI works. Keycloak v15

The error I receive is

oauth2: cannot fetch token: 401 Unauthorized
Response: {"error":"unauthorized_client","error_description":"Client secret not provided in request"}
jurgen-weber-deltatre commented 2 years ago

so, as far as I can tell.. if you want the CLI to work.. access_type == public in the keycloak client.

You may consider that dangerous but keycloak argues

https://www.keycloak.org/docs/latest/server_admin/#_oidc-auth-flows

Another important aspect of this flow is the concept of a public vs. a confidential client. Confidential clients are required to provide a client secret when they exchange the temporary codes for tokens. Public clients are not required to provide this client secret. Public clients are perfectly fine so long as HTTPS is strictly enforced and you are very strict about what redirect URIs are registered for the client. HTML5/JavaScript clients always have to be public clients because there is no way to transmit the client secret to them in a secure manner. Again, this is ok so long as you use HTTPS and strictly enforce redirect URI registration

Moep90 commented 2 years ago

I had this issue and it drove me nuts. What I discovered was that I had to restart the argo-server pod after creating a new key-value pair in the secret configuration:

I started the pod with a reference to the non-existed $oidc.keycloak.clientSecret:

oidc.config: |
    name: Keycloak
    issuer: https://example.com/auth/realms/cluster-admins
    clientID: argo-cd
    clientSecret: $oidc.keycloak.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]
    logoutURL: https://example.com/auth/realms/cluster-admins/protocol/openid-connect/logout?redirect_uri=https://example.com

I then followed the instructions here to set up keycloak, adding the new key-value pair to the secret config file. However, the logs of the argo server showed it was not finding the key at all.

I deleted the pod, triggering a restart, and everything worked.

solved it for me.

kubectl get po -n <argocd-ns> |grep Running | grep -v redis | awk '{print $1}' |xargs -I {} kubectl delete po -n <argocd-ns> {}
tarun9715m commented 2 years ago

getting this:-

FATA[0011] oauth2: cannot fetch token: 401 Unauthorized Response: {"error":"invalid_client","error_description":"Invalid client credentials."}

my oidc-config:-

oidc.config: | name: google issuer: https://dex.testing.in clientID: argocd clientSecret: C1NABUFDIHRS78 public: true requestedScopes:

mhumeSF commented 2 years ago

@tarun9715m I created a second okta app just for cli sso login