Skip to content

Cosmo Router incorrectly checks the wrong "scopes" claim #645

@rickpasetto

Description

@rickpasetto

Component(s)

router

Component version

0.74.0

wgc version

0.45.0

controlplane version

cloud

router version

0.74.0

What happened?

Description

The @requiresScopes feature appears to be looking for a JWT claim called scopes, but RFC 8693 specifies that the claim should be called scope (singular). This appears to perhaps be a typo in authentication.go, around line 55, on branch main.

Steps to Reproduce

I reproduced this by setting up a simple Keycloak server in Docker along with Wundergraph.

  • Create a JWT with the following claims (for example):
...
"scope": "email profile read:value",
...
  • Create a subgraph with the @requiresScopes parameter, e.g.
type Query {
  hello: String! @requiresScopes([["read:value"]])
}
  • Create a federated graph pointed at this subgraph
  • Start the Wundergraph Cosmo Router with the config pointed at the Keycloak instance.
  • Using the valid JWT as indicated above in the "Authorization" header, try doing a query:
query {
  hello
}

(assuming you have a federated query set up like this)

Expected Result

Normal results of the query

Actual Result

Incorrect "Unauthorized" error:

{
  "errors": [
    {
      "message": "Unauthorized"
    }
  ],
  "data": null,
  "extensions": {
    "authorization": {
      "missingScopes": [
        {
          "coordinate": {
            "typeName": "Query",
            "fieldName": "hello"
          },
          "required": [
            [
              "read:value"
            ]
          ]
        }
      ],
      "actualScopes": []
    }
  }
}

Environment information

Setting up for this issue requires a bit of work. You'll need (at least):

  • Docker
  • a wundergraph supergraph setup

I've attached a zip file with the following files:

wundergraph/
├── docker-compose.keycloak.yml
├── docker-compose.wundergraph.yml
├── hello
│   ├── Dockerfile
│   ├── hello.js
│   ├── package-lock.json
│   └── package.json
├── realm-export.json
├── test.graphql
└── wundergraph.config.yml

Hopefully this is enough config to set up keycloak and wundergraph in Docker. You'll need to start everything by running:

WUNDERGRAPH_API_TOKEN=<your_api_token> docker compose -f atp/docker-compose.keycloak.yml -f atp/docker-compose.wundergraph.yml -f atp/docker-compose.hello.yml up --build --wait

Then, open keycloak's dashboard: http://localhost:8181/
Go to Realm Settings, choose Action (drop-down) -> Partial Import, then pick the realm-export.json file.
Now, copy the client secret by going to Clients -> Credentials -> Client Secret. Copy this and save it for later.

Now, open up http://localhost:9001/, and try doing:

query Hello {
  hello
}

You should get:

  "errors": [
    {
      "message": "unauthorized"
    }
  ],
  "data": null

This is expected. However, obtain a token by doing this (from the client secret above):

curl --location 'http://localhost:8181/auth/realms/master/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=hello-client' \
--data-urlencode 'username=admin' \
--data-urlencode 'password=admin' \
--data-urlencode 'client_secret=<client_secret>'

Hopefully, if you have everything set up right, you should see some output like this:

{"access_token":"<ACCESS_TOKEN>","expires_in":60,"refresh_expires_in":... }

Copy <ACCESS_TOKEN> and add this to your header in the GraphQL query:

"Authorization": "Bearer <ACCESS_TOKEN>"

Now, you see the result:

{
  "errors": [
    {
      "message": "Unauthorized"
    }
  ],
  "data": null,
  "extensions": {
    "authorization": {
      "missingScopes": [
        {
          "coordinate": {
            "typeName": "Query",
            "fieldName": "hello"
          },
          "required": [
            [
              "read:value"
            ]
          ]
        }
      ],
      "actualScopes": []
    }
  }
}

...which is wrong, because the admin user does have the read:value scope.

I hope this is enough detail.

wundergraph.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions