dexidp / website

Dex website
https://dexidp.io
Apache License 2.0
12 stars 65 forks source link

Following connectors/local example results in "Invalid client credentials" #183

Open SimonTheLeg opened 1 week ago

SimonTheLeg commented 1 week ago

Following the guide at https://dexidp.io/docs/connectors/local/, I am running into some issues:

If you copy the example from the Obtaining a token section and set it up with sqllite as storage...

issuer: http://localhost:8080/dex
storage:
  type: sqlite3
  config:
    file: sqlite/dex.db
# Setup clients
staticClients:
  - id: public-client
    public: true
    name: 'Public Client'
    redirectURIs:
      - 'https://example.com/oidc/callback'
  - id: private-client
    secret: app-secret
    name: 'Private Client'
    redirectURIs:
      - 'https://example.com/oidc/callback'
# Set up an test user
staticPasswords:
  - email: "admin@example.com"
    # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
    hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

# Enable local users
enablePasswordDB: true
# Allow password grants with local users
oauth2:
  passwordConnector: local

You will get

❯ dex serve dex-config.yaml
time=2024-09-18T18:55:12.589+02:00 level=INFO msg="Version info" dex_version=v2.41.1 go.version=go1.22.6 go.os=darwin go.arch=amd64
invalid Config:
        -       must supply a HTTP/HTTPS  address to listen on

Which is a bit unconvenient, but still can be fixed easily by adding the web.http section to the config:


issuer: http://localhost:8080/dex
storage:
  type: sqlite3
  config:
    file: sqlite/dex.db
# Setup clients
staticClients:
  - id: public-client
    public: true
    name: 'Public Client'
    redirectURIs:
      - 'https://example.com/oidc/callback'
  - id: private-client
    secret: app-secret
    name: 'Private Client'
    redirectURIs:
      - 'https://example.com/oidc/callback'
# Set up an test user
staticPasswords:
  - email: "admin@example.com"
    # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
    hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

# Enable local users
enablePasswordDB: true
# Allow password grants with local users
oauth2:
  passwordConnector: local

web:
  http: 127.0.0.1:8080

And then dex starts

❯ dex serve dex-config.yaml
time=2024-09-18T18:56:27.263+02:00 level=INFO msg="Version info" dex_version=v2.41.1 go.version=go1.22.6 go.os=darwin go.arch=amd64
time=2024-09-18T18:56:27.263+02:00 level=INFO msg="config issuer" issuer=http://localhost:8080/dex
time=2024-09-18T18:56:27.296+02:00 level=INFO msg="config storage" storage_type=sqlite3
time=2024-09-18T18:56:27.296+02:00 level=INFO msg="config static client" client_name="Public Client"
time=2024-09-18T18:56:27.296+02:00 level=INFO msg="config static client" client_name="Private Client"
time=2024-09-18T18:56:27.297+02:00 level=INFO msg="config connector: local passwords enabled"
time=2024-09-18T18:56:27.297+02:00 level=INFO msg="config using password grant connector" password_connector=local
time=2024-09-18T18:56:27.298+02:00 level=INFO msg="config refresh tokens rotation" enabled=true
time=2024-09-18T18:56:27.308+02:00 level=INFO msg="keys expired, rotating"
time=2024-09-18T18:56:27.384+02:00 level=INFO msg="keys rotated" next_rotation=2024-09-18T22:56:27.372Z
time=2024-09-18T18:56:27.385+02:00 level=INFO msg="listening on" server=http address=127.0.0.1:8080

However you still will not be able to to run the curl examples from the Public Client or Private Client section at the bottom of the document

# side-note the hash comment in the middle of the line also breaks shells like zsh, so I have removed it here
curl -L -X POST 'http://localhost:8080/dex/token' \
-H 'Authorization: Basic cHVibGljLWNsaWVudAo=' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=openid profile' \
--data-urlencode 'username=admin@example.com' \
--data-urlencode 'password=admin'

{"error":"invalid_client","error_description":"Invalid client credentials."}

At first I thought this was due to the fact that in the config the password is actually set to "password" and not "admin", but still the same issue

❯ curl -L -X POST 'http://localhost:8080/dex/token' \
-H 'Authorization: Basic cHVibGljLWNsaWVudAo=' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=openid profile' \
--data-urlencode 'username=admin@example.com' \
--data-urlencode 'password=password'
{"error":"invalid_client","error_description":"Invalid client credentials."}

I have also tried both variations with 'username=admin', but with the same result.

Can you advise how to get retrieving the token using curl to work? Happy to contribute this back to the guide in addition to the adaptations I made above.

SimonTheLeg commented 3 days ago

Okay I finally figured out how it works. The Authorization header seemed to be the issue. The following works

❯ curl -L -X POST 'http://localhost:8080/dex/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=openid email' \
--data-urlencode 'username=admin@example.com' \
--data-urlencode 'password=password' \
--data-urlencode 'client_id=public-client'

Will create a Docs PR tomorrow :)