Error: Invalid_Client - What?

Hi Apple Developers,


I'm facing a very bad issue because I read so many guides and tutorials and nothing works.

The result is always the same: {"error":"invalid_client"}


I get the code, identityToken and everything I need - except the call to https://appleid.apple.com/auth/token - because of invalid_client.


Here is my url for getting the code.

https://appleid.apple.com/auth/authorize?response_type=code&client_id=org.example.service&redirect_uri=https%3A%2F%2Fexample.org


So then I have the default workflow.

And after accepting / loggin in I will be redirected to my page.

https://example.org/?code=a277243e2ec324fb09ba1c3333a8e6576.0.abcde.u4xiTDP2qHXoNEaxrcrIGx


(When I'm using the JavaScript API I'll get other informations like state, code and id_token. I already tried it with the "code" there, too.)


Back to the main function.


This is my request for Apple.

  'client_id' => 'org.example.service',
  'client_secret' => JWT-Data encoded (OPENSSL_ALGO_SHA256) see below  'grant_type' => 'authorization_code',
  'code' => 'a277243e2ec324fb09ba1c3333a8e6576.0.abcde.u4xiTDP2qHXoNEaxrcrIGx'


JWT Header:

{
  "alg": "ES256",
  "kid": "1ABC2345DE"
}


JWT Payload:

{
  "iss": "1A234BCD56",
  "iat": 1571269964,
  "exp": 1571273564,
  "aud": "https://appleid.apple.com",
  "sub": "org.example.service"
}


Response:

{
  "error": "invalid_client"
}


The useless error message of the world.

I dont know why the client should be invalid.


I have a key in https://developer.apple.com/account/resources/authkeys/list with downloaded file name AuthKey_1ABC2345DE.p8. (means 1ABC2345DE is my key id)

Then I have a native iOS app with identifier "org.example" and a service with identifier "org.example.service".


Its not working with both ids and mixed different things.

Nothing. invalid_client.



Can anyone help me please? I'm sitting here for hours and getting only invalid_client 😭

Post not yet marked as solved Up vote post of Paedy Down vote post of Paedy
42k views

Replies

I developed the solution: https://gist.github.com/patrickbussmann/877008231ef082cc5dc4ee5ca661a641


The problem was the specific algorithm which Apple uses.



//edit:
Now I developed a oAuth client library extension for Sign in with Apple:
https://github.com/patrickbussmann/oauth2-apple

i think here you need to use bundle id, not service id.

For him, the service id is the correct one. Because he is getting the code for web login. But when you use an app to get the code, you should use bundle id instead.


as explained here: https://forums.developer.apple.com/thread/118135

I was getting invalid_client because of the incorrect content-type sending by axios. correct form type should be application/x-www-form-urlencoded
Post not yet marked as solved Up vote reply of DGHK Down vote reply of DGHK
  • I created a developrs account just so i can comment this comment: Thank you sir.

  • I was having the same issue, the problem was the wrong curl request. Below is the code which worked!

    curl_close ($ch);
  • Thank you very very much! Spent entire day trying to figure out what is wrong.

This library is throwing a lot of errors. https://github.com/patrickbussmann/oauth2-apple

For the start, the code redirect the page to apple website and it show the following screen.

"invalid_client"

Please suggest what to do.
In my case I re-generate a new key for Sign-in with Apple and it's fixed.
For folks still struggling with this: I had to wait 48h after creating my first key for it to be picked up by Apple servers. For the last two days I've been trying every single solution I could find on-line, thinking that I made a mistake somewhere. Nope.. what fixed it was time (or somebody at apple modifying something on their end). I invoked exactly the same curl request 10 minutes ago and now, getting two different responses from apple's api. EXACTLY the same request (including all parameters).

10 minutes ago: {"error":"invalid_client"}
1 minute ago: {"error":"invalid_grant"} (yes!!!)
now: success (after updating "code" to a fresh authorizationCode generated by my iOS app)

Just be patient. Wait for 48h after creating your first key at https://developer.apple.com/account/resources/authkeys/list
We got this resolved by going into the More > Configure and adding our domain, making sure the SPF tick is green (if its not green, do a quick google to find out how to fix it for your config). After this, we stopped getting invalid_client errors.
The thing that made us stumble on this was it didn't appear important on account of it saying it was for the emails - we skimmed over it thinking we could come back to it later..
  • Thank you so much! this was the reason for invalid_client error for us

Add a Comment

I know this is old, but I wanted to share my solution. I was using requests-oauthlib (python library) to fetch the token. I had to pass include_client_id=True in the call to OAuth2Session.fetch_token().

I've tried all the method above, but none of it works, just wondering does anyone know if there are more potential solutions for this invalid_client issue

In my case the issue was that when generating client secret (which is signed JWT) I was not attaching private key id ("kid") to JWT header. The funny thing is that it was working without providing "kid" when I had only one private key generated in developer console. When generated another one only the newest one was working without attaching "kid" to JWT so it seems that when verifying client secret (which is signed JWT) Apple takes the latest private key to check signature when "kid" is not present in JWT.

Here is how I generate ClientSecret passed to apple token endpoint (c#):

private static string GenerateAppleClientSecret(AppleSettings appleSettings)
{
    string iss = appleSettings.AccountTeamId;
    string aud = appleSettings.Authority;
    string sub = appleSettings.ClientId;
    var now = DateTime.UtcNow;

    var ecdsa = ECDsa.Create();
    ecdsa.ImportPkcs8PrivateKey(Convert.FromBase64String(appleSettings.PrivateKey), out _);

    JwtHeader jwtHeader = new JwtHeader(new SigningCredentials(new ECDsaSecurityKey(ecdsa), SecurityAlgorithms.EcdsaSha256));
    jwtHeader.Clear();
    jwtHeader.Add("alg", "ES256");
    jwtHeader.Add("typ", "JWT");
    jwtHeader.Add("kid", appleSettings.PrivateKeyId);

    JwtPayload jwtPayload = new JwtPayload(
        iss,
        aud,
        new List<Claim>()
        {
            new Claim("sub", sub),
        },
        now,
        now.Add(TimeSpan.FromMinutes(5))
    );

    var jwt = new JwtSecurityToken(jwtHeader, jwtPayload);
    return new JwtSecurityTokenHandler().WriteToken(jwt);
}
  • Yes main challenge is getting the JWT token right. If anyone confused can see this post from medium. https://medium.com/@abdulmomen130/how-to-figure-out-the-sign-in-with-apple-token-revocation-requirements-after-june-30th-d16a4f6262c8

Add a Comment

In my case my secret was expired due to max lifetime is 6 months, I recreated secret token using ruby script on my .p8 certificated and error invalid_client was fixed

I was having the same issue, the problem was the wrong curl request. Below is the code which worked!

$ch = curl_init('https://appleid.apple.com/auth/token');
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($reqDataArray));
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
            $serverOutput = curl_exec($ch);

            curl_close ($ch);

In our case, it turned out that the token expiration was more than 180 days.

Be careful because of this invalid_client error could be misleading (as always Apple's error messages)

$postParams = array(
    &#039;code&#039; =&gt; ...,
    &#039;client_id&#039; =&gt; ...,
    &#039;client_secret&#039; =&gt; ...,
    &#039;grant_type&#039; =&gt; &#039;authorization_code&#039;,
    &#039;redirect_uri&#039; =&gt; ...,
);

$curl = curl_init(&#039;https:&#x2F;&#x2F;appleid.apple.com&#x2F;auth&#x2F;token&#039;);

&#x2F;&#x2F; never pass params as just array for apple without stringifying via http_build_query()
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postParams));

When you will use just curl_setopt($curl, CURLOPT_POSTFIELDS, $postParams); it is valid POST request but another type than Apple expects but lazy apple developers are not able to provide error that this type of POST request is unsupported.