Google service account access token request: "Required parameter is missing: grant_type"
<p><strong>UPDATE:</strong> Solved. I was indeed making a basic mistake, among other things. My usage of the <code>session.headers.update</code> function was incorrect; instead of <code>session.headers.update = {foo:bar}</code>, I needed to be doing <code>session.headers.update({foo:bar})</code>. Additionally, I changed the following section of code:</p>

<p>From this:</p>

<pre><code>payload = urllib.parse.urlencode({
    "grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer", 
    "assertion": str(token)
})
</code></pre>

<p>To this:</p>

<pre><code>    payload = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&amp;assertion=" + token.decode("utf-8")
</code></pre>

<p>The code now works as intended.</p>

<hr>

<p><strong>Original question below</strong></p>

<p>I've seen several hits on SO and Google about this problem; none of them have helped, although I've certainly made sure to double-check my code to make sure I'm not guilty of the same problems they detail. The problems people tend to have involve passing the POST data as parameters or POSTing to the wrong URL, which I'm not doing, as far as I can tell. Additionally, most of the hits I've found involve 3-legged OAuth2 involving users; I've found comparatively few hits pertaining to service accounts and JWTs, which differ enough from the user flow that I'm concerned about how relevant they are to my problem.</p>

<hr>

<p>I'm trying to get an access token from the Google Authentication server for a service account. I've generated my JWT and now want to POST to the server to receive back my access token. I've set the headers according to the documentation described <a href="https://developers.google.com/identity/protocols/OAuth2ServiceAccount" rel="nofollow">here</a>, under "Making the access token request," and as far as I can tell, my request is up to spec, but Google responds back with a 400 response, and the following JSON:</p>

<pre><code>{'error': 'invalid_request', 'error_description': 'Required parameter is missing: grant_type'}
</code></pre>

<p>Here's the code causing the problem:</p>

<pre><code># Returns the session, now with the Host and Authorization headers set.
def gAuthenticate(session):
    token = createJWT()
    session.headers.update = {
        "Host": "www.googleapis.com", 
        "Content-Type": "application/x-www-form-urlencoded"
    }
    payload = urllib.parse.urlencode({
        "grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer", 
        "assertion": str(token)
    })
    response = session.post("https://www.googleapis.com/oauth2/v4/token", data = payload)

    session.headers.update = {"Authorization": "Bearer " + response.json()["access_token"]} 
    return session
</code></pre>

<p>I'm having a lot of strange issues with this code. First of all, if I don't <code>urllib.parse.urlencode</code> my dictionary (i.e. simply <code>payload = {dictionary}</code>), I get only a <code>Bad Request / 'invalid_request'</code> error, which I assume from the less specific error message means that this is less acceptable than what I'm currently doing. Why do I have to do this? Isn't Requests supposed to encode my data for me? I've never had this problem when POSTing with Requests before.</p>

<p>Second, examining the prepared request before it's sent reveals that my headers aren't being correctly set, despite the header update. Neither of the headers I've added to the request are being transmitted. </p>

<p>I've examined the request body and it looks to be identical (except of course the content of the JWT) to the one that Google provides as an example in the documentation.</p>

<p>All of this leads me to believe that I'm making a very basic error somewhere, but I haven't had any success finding it. What am I doing wrong here? Links to any helpful documentation would be extremely appreciated; thanks for your time and attention.</p>

<p>Try "grant_type": "authorization_code".  And add grant type as header.</p>

<p>Also, check this link - <a href="http://stackoverflow.com/questions/32919099/accessing-google-oauth-giving-invalid-grant-type-bad-request?rq=1">Accessing Google oAuth giving invalid grant_type (Bad request)</a></p>

python google-api python-requests google-oauth google-oauth2