Search code examples
restoauthfitnessespring-security-oauth2

FitNesse RestFixture test fails to get access token


I have REST application with Spring OAuth2 authorization. I test it with FitNesse RestFixture test (I added token from curl response and last GET operation works successfully):

| Table:smartrics.rest.fitnesse.fixture.RestFixture | http://10.76.243.103:8080 |
| GET | /<root>/version | | | 2.2.1 |
| setBody |grant_type=password&username=test&password=test123&scope=data+compute|
| setHeader |Authorization : Basic dGVzdDo4YmE5MjRjZS0wNThhLTQ3Y2YtOGQ4Mi02ZWY1N2Y4NzdiNmQ=|
| setHeader |Content-Type : application/x-www-form-urlencoded|
| POST | /<oauth-provider>/oauth/token | | | |
| setHeader |Authorization : Bearer fd947659-cf17-4ded-b2e8-698395c201df|
| GET | /<root>/schemas | | | | 

And I failed to get access token on POST operation with issue {"error":"unauthorized","error_description":"Full authentication is required to access this resource"}:

| POST | /<oauth-provider>/oauth/token | 401 | <responce> | {"error":"unauthorized","error_description":"Full authentication is required to access this resource"} |

Where responce is:

Server : Apache-Coyote/1.1
X-Content-Type-Options : nosniff
X-XSS-Protection : 1; mode=block
Cache-Control : no-cache, no-store, max-age=0, must-revalidate
Pragma : no-cache
Expires : 0
X-Frame-Options : DENY
Cache-Control : no-store
Pragma : no-cache
WWW-Authenticate : Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"
Content-Type : application/json;charset=UTF-8
Transfer-Encoding : chunked
Date : Thu, 27 Nov 2014 11:17:56 GMT

If I perfrom same action with curl utility I got access_token successfully:

curl -X POST -v -u test:8ba924ce-058a-47cf-8d82-6ef57f877b6d --data 'username =test&password=test123&grant_type=password&scope=data+compute' 'http://10.76.24 3.103:8080/parseq/oauth/token' -k

* About to connect() to 10.76.243.103 port 8080 (#0) 
* Trying 10.76.243.103...
* Adding handle: conn: 0x4c3388
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x4c3388) send_pipe: 1, recv_pipe: 0
* Connected to 10.76.243.103 (10.76.243.103) port 8080 (#0)
* Server auth using Basic with user 'test'

> POST /parseq/oauth/token HTTP/1.1 
> Authorization: Basic dGVzdDo4YmE5MjRjZS0wNThhLTQ3Y2YtOGQ4Mi02ZWY1N2Y4NzdiNmQ= 
> User-Agent: curl/7.30.0 
> Host: 10.76.243.103:8080 
> Accept: */* 
> Content-Length: 69 
> Content-Type: application/x-www-form-urlencoded 
>
* upload completely sent off: 69 out of 69 bytes
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1; mode=block 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache < Expires: 0 
< X-Frame-Options: DENY 
< Cache-Control: no-store 
< Pragma: no-cache 
< Content-Type: application/json;charset=UTF-8 
< Transfer-Encoding: chunked 
< Date: Thu, 27 Nov 2014 09:20:39 GMT 
< {"access_token":"fd947659-cf17-4ded-b2e8-698395c201df","token_type":"bearer","re fresh_token":"564aa6ca-0afa-4519-a907-e7027053bb35","expires_in":40317,"scope":" compute data"}
* Connection #0 to host 10.76.243.103 left intact

Can anyone advice me how to debug or fix it?

Thanks In Advance!


Solution

  • I launched tcpdump to check what exactly I send from my curl request (as descibed in Use TCPDUMP to Monitor HTTP Traffic):

    sudo tcpdump -A -s 0 'tcp port 8080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
    

    I launched it on server machine.

    I found that curl automatically added Content-Type header:

    08:55:30.504594 IP <my client DNS name>.53655 > cherry.http-alt: Flags [P.], seq      1801770313:1801770631, ack 3280862118, win 67, length 318
    E..fE.@.q..q
    B r
    L.g....kd.I....P..C....POST /<oauth provider>/oauth/token HTTP/1.1
    Authorization: Basic dGVzdDo4YmE5MjRjZS0wNThhLTQ3Y2YtOGQ4Mi02ZWY1N2Y4NzdiNmQ=
    User-Agent: curl/7.30.0
    Host: 10.76.243.103:8080
    Accept: */*
    Content-Length: 69
    Content-Type: application/x-www-form-urlencoded
    
    username=test&password=test123&grant_type=password&scope=data+compute
    08:55:30.508697 IP cherry.http-alt > <my client DNS name>.53655: Flags [P.], seq 1:563, ack 318,   win 237, length 562
    E..ZPB@.@...
    L.g
    B r........kd..P...*...HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    X-Content-Type-Options: nosniff
    X-XSS-Protection: 1; mode=block
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0
    X-Frame-Options: DENY
    Cache-Control: no-store
    Pragma: no-cache
    Content-Type: application/json;charset=UTF-8
    Transfer-Encoding: chunked
    Date: Thu, 27 Nov 2014 13:55:30 GMT
    
    ae
    {"access_token":"fd947659-cf17-4ded-b2e8-698395c201df","token_type":"bearer","refresh_token":"564aa6ca-0afa-4519-a907-e7027053bb35","expires_in":23826,"scope":"compute data"}
    
    08:55:30.508937 IP cherry.http-alt > <my client DNS name>.53655: Flags [P.], seq 563:568, ack 318, win 237, length 5
    

    Also I've checked what exactly I send from my FitNesse test:

    08:33:36.598429 IP 10.76.243.55.39600 > cherry.http-alt: Flags [P.], seq 102:347, ack 335, win   237, options [nop,nop,TS val 859086469 ecr 41658573], length 245
    E..)..@.@...
    L.7
    L.g........r..............
    34...{..POST /<oauth provider>/oauth/token HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    User-Agent: Jakarta Commons-HttpClient/3.1
    Host: 10.76.243.103:8080
    Content-Length: 69
    
    grant_type=password&username=test&password=test123&scope=data+compute
    08:33:36.599047 IP cherry.http-alt > 10.76.243.55.39600: Flags [P.], seq 335:974, ack 347, win 235, options [nop,nop,TS val 41658578 ecr 859086469], length 639
    

    And I found that Authorization header is missed in my request from FitNesse. It looks like sequential using of setHeader() methods leads to overwriting of headers. So, I changed my FitNesse test to use setHeaders() method to setup some headers in one table row (as described in How can you set headers with dynamic value in the RestFixtureConfig rest fixture.default.headers):

    | setBody |grant_type=password&username=test&password=test123&scope=data+compute|
    | setHeaders |!-Authorization: Basic dGVzdDo4YmE5MjRjZS0wNThhLTQ3Y2YtOGQ4Mi02ZWY1N2Y4NzdiNmQ=
    Content-Type: application/x-www-form-urlencoded-!|
    | POST | /parseq/oauth/token | 200 | | | 
    

    And now it works fine.