2

I am working with the CF API RESTful services. Trying to get an access token from cloud foundry's UAA API using https://login..../oauth/token web method.

I have verified that headers & body content is correct, but calling the api always returns a 400 error code with message missing grant type.

I have implemented this call in Objective-C, Swift & now Python. All tests return the same result. Here is my code example in Python:

import json
import requests
import urllib

params = {"grant_type": "password",
          "passcode": "xxx"
          }
url = "https://login.system.aws-usw02-pr.ice.predix.io/oauth/token"
headers = {"Authorization": "Basic Y2Y6", "Content-Type": "application/json", "Accept": "application/x-www-form-urlencoded"}

encodeParams = urllib.parse.urlencode(params)
response = requests.post(url, headers=headers, data=encodeParams)
rjson = response.json()
print(rjson)

Each time I run this, I get the response error invalid request, Missing grant type

Any help would be greatly appreciated.

1 Answers1

3

Your code mostly worked for me, although I used a different UAA server.

I had to make only one change. You had the Accept and Content-Type headers flipped around. Accept should be application/json because that's the format you want back, and Content-Type should be application/x-www-form-urlencoded because that's the format you are sending.

See the API Docs for reference.

import json
import requests
import urllib
import getpass

UAA_SERVER = "https://login.run.pivotal.io"

print("go to {}/passcode".format(UAA_SERVER))

params = {
    "grant_type": "password",
    "passcode": getpass.getpass(),
}

url = "https://login.run.pivotal.io/oauth/token"
headers = {
    "Authorization": "Basic Y2Y6",
    "Content-Type": "application/x-www-form-urlencoded",
    "Accept": "application/json"
}

encodeParams = urllib.parse.urlencode(params)
response = requests.post(url, headers=headers, data=encodeParams)
rjson = response.json()
print(json.dumps(rjson, indent=4, sort_keys=True))

I made a couple other minor changes, but they should affect the functionality.

  1. Use getpass.getpass() to load the passcode.
  2. Set the target server as a variable.
  3. Pretty print the JSON response.

The only other thing to note, is that the OAuth2 client you use must be allowed to use the password grant type. It looks like you're using the same client that the cf cli uses, so if your UAA server is part of a standard Cloud Foundry install that is likely to be true, but if it still doesn't work for you then you may need to talk with an administrator and make sure the client is set up to allow this.

halfer
  • 19,824
  • 17
  • 99
  • 186
Daniel Mikusa
  • 13,716
  • 1
  • 22
  • 28
  • Thank you for this feedback. I tried your suggestions and am still getting the error back Missing grant type. I was wondering the same as to whether or not my cloud foundry install would support the same client as CF CLI. I have tested this same call using postman against my environment and get a successful response with an access_token. So I am assuming it should work. – Guy Thornton Jan 27 '20 at 14:25
  • My next step in determining the problem, was to try this code on a different machine altogether in order to remove all limitations/restrictions imposed from company owned systems. Once I did, the code works as expected. – Guy Thornton Jan 27 '20 at 15:40