0

I'm trying to validate the Connect2id set up with Go test and I'm getting following error.

"Client authentication failed: Missing client authentication","error":"invalid_client"

The full scenario output is look like below.

Feature: Test Identity Provider

  Scenario:                                                             # features/idp.feature:3
    Given identity provider 'hf1-idp.json'                               # main_test.go:72 -> *Scaffold
    When I request an access token as 'cc_test'                          # main_test.go:83 -> *Scaffold
    oauth2: cannot fetch token: 401 Unauthorized
Response: {"error_description":"Client authentication failed: Missing client authentication","error":"invalid_client"}
    Then the token should have a claim 'scope'                           # main_test.go:92 -> *Scaffold
    And the token should have a claim 'sub' with value 'dips-mra'        # main_test.go:106 -> *Scaffold
    And the token should have a claim 'hso:userid' with value 'dips-mra' # main_test.go:106 -> *Scaffold

My hf1-idp.json file look like below.

{
  "kind": "PING",
  "issuer": "https://my.issuer.com/c2id",
  "insecure": true,
  "clients": {
    "cc_test": {
      "flow": "clientcredentials",
      "id": "clientId",
      "secret": "",
      "scopes": ["openid", "solr"],
      "values": {
          "resource": ["https://my.solrnode1.com/solr/", "https://my.solrnode2.com/solr/"]
      }
    },

Connect2id works fine in the set up environment. As an example I get expected result when I run following Curl command with correct values

curl -k -s -H "Content-Type: application/json" -XPOST https://my.issuer.com/c2id/direct-authz/rest/v2 \
        -H "Authorization: Bearer ztucBearerToken" \
        -d '{
  "sub_session" : { "sub" : "alice" },
  "client_id"   : "clientId",
  "scope"       : [ "openid", "solr" ],
  "claims"      : [ "name", "email", "email_verified", "access_token:hso:subject:system", "access_token:hso:subject:id", "access_token:hso:subject:name", "access_token:hso:subject:role:system", "access_token:hso:subject:role:id", "access_token:hso:subject:role:name", "access_token:hso:subject:organization:system", "access_token:hso:subject:organization:id", "access_token:hso:subject:organization:name", "access_token:hso:subject:organization:child-organization:system", "access_token:hso:subject:organization:child-organization:id", "access_token:hso:subject:organization:child-organization:name", "access_token:hso:purpose:system", "access_token:hso:purpose:id", "access_token:hso:purpose:description", "access_token:hso:resource:system", "access_token:hso:resource:id" ]
}'

Updated with following codes

main_test.go

func (sc *Scaffold) readIdentityProvider(filename string) error {
    idp, err := idp.ReadIdentityProvider(context.Background(), "testdata/"+filename)

// More code goes here
}

provider.go

func ReadIdentityProvider(ctx context.Context, filename string) (*IdentityProvider, error) {
    config, err := readIdentityProvider(filename)
    if err != nil {
        return nil, err
    }

    return NewIdentityProvider(ctx, config)
}

func NewIdentityProvider(ctx context.Context, config *Config) (*IdentityProvider, error) {
    ctx = context.WithValue(ctx, oauth2.HTTPClient, &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                InsecureSkipVerify: config.Insecure,
            },
        },
    })
    provider, err := oidc.NewProvider(ctx, config.Issuer)

// More code goes here
}

oidc.go

func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
    wellKnown := strings.TrimSuffix(issuer, "/") + "/direct-authz/rest/v2"
    req, err := http.NewRequest("POST", wellKnown, nil)
    if err != nil {
        return nil, err
    }
    resp, err := doRequest(ctx, req)    // Herer I get 401 Unauthorized
    if err != nil {
        return nil, err
    }
// More code goes here
}
AnujAroshA
  • 4,623
  • 8
  • 56
  • 99
  • Can you post your code from `main_test.go`? The error `invalid_client`refers usually to a wrong/missing `client_id` or `client_secret` – SchCh Jun 17 '20 at 07:41
  • @SchCh updated the question with related Go code – AnujAroshA Jun 17 '20 at 09:42
  • Could you also include any relevant logs from tomcat/logs/c2id-server.log ? – Vladimir Dzhuvinov Jun 17 '20 at 11:35
  • @VladimirDzhuvinov connect2id runs inside a docker container and when I checked inside the container, the file content is empty. But I have `docker logs container_id` output, which is huge. Is there any specific thing that I need to find? – AnujAroshA Jun 17 '20 at 12:28

1 Answers1

0

You are missing the Bearer token in the request. (https://connect2id.com/products/server/docs/integration/direct-authz#error-401) When you curl you use the -H parameter to add the Authorization Bearer token -H "Authorization: Bearer ztucBearerToken"

You need to do the same in your Go application.

func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
    wellKnown := strings.TrimSuffix(issuer, "/") + "/direct-authz/rest/v2"
    req, err := http.NewRequest("POST", wellKnown, nil)

    bearer := "Bearer ztucBearerToken"
    req.Header.Add("Authorization", bearer)

    if err != nil {
        return nil, err
    }
    resp, err := doRequest(ctx, req)    // Herer I get 401 Unauthorized
    if err != nil {
        return nil, err
    }
// More code goes here
}

Some supportive facts

Similar SO discussion goes here.

To get rid of the

400 Bad Request: {"error_description":"Bad request: Invalid JSON: Unexpected token at position 0.","error":"invalid_request"}

what you have to do is pass necessary request body like below.

req, err := http.NewRequest("POST", wellKnown, bytes.NewBuffer(bytesRepresentation))

Fore more info visit, Golang documentation related to net/http

AnujAroshA
  • 4,623
  • 8
  • 56
  • 99
SchCh
  • 133
  • 1
  • 6
  • Ended up with this error `400 Bad Request: {"error_description":"Bad request: Invalid JSON: Unexpected token at position 0.","error":"invalid_request"}` – AnujAroshA Jun 18 '20 at 03:46