nhosoya / omniauth-apple

OmniAuth strategy for Sign In with Apple
MIT License
260 stars 99 forks source link

Can't use Sign In With Apple JS #68

Closed wilg closed 1 year ago

wilg commented 3 years ago

As far as I can tell, the reason is that omniauth-apple generates a authorize url with response_type=code and Sign in with Apple JS generates one with response_type=code%20id_token. Manually changing the omniauth-apple url in the browser to have the response_type=code%20id_token also fails with the same error.

The error is:

ERROR -- omniauth: (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: 
{"error":"invalid_client"}

So this error seems to be originating somewhere in the omniauth oauth2 implementation: https://github.com/omniauth/omniauth-oauth2/blob/master/lib/omniauth/strategies/oauth2.rb

Seems like the answer is to support the response_type=code%20id_token thing but I'm not sure how...

https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/incorporating_sign_in_with_apple_into_other_platforms

atomgas commented 3 years ago

adding this to options works for me


authorized_client_ids: [ apple_client_id ]
wilg commented 3 years ago

Oh interesting, what is apple_client_id?

wilg commented 3 years ago

Oh wait i have that nvm

wilg commented 3 years ago

Thanks @atomgas that worked!

Sadat97 commented 3 years ago

Hello, am having the same issue is apple_client_id the same as the CLIENT_ID ?

wilg commented 3 years ago

@Sadat97 yes, for me it was

Sadat97 commented 3 years ago

weird i used it, and still the issue is happening to be honest it also shows nonce mismatch also before this error in the logs. any ideas on how to fix this ?

atomgas commented 3 years ago

complete fix, all constants are prefixed with APPLE_ since I have more then one CLIENT_ID

# config/initializers/omniauth.rb
# 
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :apple, APPLE_CLIENT_ID, "",
           {
             scope: "email name",
             team_id: APPLE_TEAM_ID,
             key_id: APPLE_KEY_ID,
             pem: APPLE_PRIVATE_KEY,
             callback_path: "/redirect",
             provider_ignores_state: true,
             authorized_client_ids: [ APPLE_CLIENT_ID ],
           },
  ....
end

to fix the nonce mismatch issue

# app/helpers/application_helper.rb
  # CLIENT_ID from Apple for web
  def apple_client_id
    Rails.application.credentials.apple_client_id_web
  end

  # use this in HTML or JS
  def apple_signin_nonce
    session["omniauth.nonce"] ||= SecureRandom.urlsafe_base64(16)
    session["omniauth.nonce"]
  end
Sadat97 commented 3 years ago

isn't # CLIENT_ID from Apple for web the same as APPLE_CLIENT_ID?

atomgas commented 3 years ago

yes

wilg commented 3 years ago

FWIW I was able to eliminate provider_ignores_state: true with this fix: https://github.com/nhosoya/omniauth-apple/pull/66

RStankov commented 3 years ago

I have the same issue and the suggested fix doesn't work?

provider :apple,  APPLE_CLIENT_ID, '', {
  scope: 'email name', 
  team_id: APPLE_TEAM_ID, 
  key_id: APPLE_KEY_ID, 
  pem: APPLE_PRIVATE_KEY, 
  authorized_client_ids: [APPLE_CLIENT_ID], 
  provider_ignores_state: true 
}

I still get

ERROR -- omniauth: (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client:

I don't use AppleJS, I just have a button posting to /auth/apple. All seems to go well, till invalid_credentials.

I'm, I missing something?

wilg commented 3 years ago

I had to make a new client ID for my server, separate from my iOS app.

RStankov commented 3 years ago

@wilg I have a separate - "Services ID" and use it "Identifier" field as APPLE_CLIENT_ID and still doesn't work :(

wilg commented 3 years ago

Strange, the only difference between your set up and mine is I specify redirect_uri as well

RStankov commented 3 years ago

@wilg, I found the issue the APPLE_KEY_ID was wrong 🤦‍♂️.

Then I started getting, due to JWT token taking too much time:

{"error":"invalid_grant","error_description":"The code has already been used."}):
andreierdoss commented 3 years ago

I have the same issue and I can't figure out what is causing it. I tried all suggestions. Is there a way to debug this?

Also does anyone have better documentation on integrating Devise + Omniauth + Apple sign in? I'm wondering if I'm missing something.

Started POST "/users/auth/apple/callback" for ... at 2021-05-01 14:01:06 +0300 (apple) Callback phase initiated. (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: {"error":"invalid_client"} Processing by OmniauthCallbacksController#failure as HTML Parameters: {"state"=>"xxx", "code"=>"xxx"}

mzibara commented 3 years ago

@andreierdoss I have stopped receiving this error after getting domain name SPF checked under Certificates, Identifiers & Profiles -> More. Make sure this is the same domain you are registering your service ID with

alea12 commented 2 years ago

@RStankov Were you able to solve this? I'm facing a similar situation.

I, [2022-05-06T13:39:29.768202 #66384]  INFO -- omniauth: (apple) Callback phase initiated.
E, [2022-05-06T13:39:30.291136 #66384] ERROR -- omniauth: (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_grant: The code has already been used.
{"error":"invalid_grant","error_description":"The code has already been used."}
taco-chen commented 2 years ago

Downgrade the OmniAuth gem from 2.1.0 to 2.0.4 solved the following error to me.

ERROR -- omniauth: (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: 
{"error":"invalid_client"}

In the mean while, I directly drop the Apple JS and use the following code to create popup window for Sign in with Apple

// this is to prevent from triggering the safari native login dialog which will break the auth flow
const applePopup = window.open("/", "Login", [PARAMS_FOR_WIDTH_AND_HEIGHT]);

if (applePopup) {
  applePopup.location = encodeURI("https://appleid.apple.com/auth/authorize?client_id=[CLIENT_ID]&redirect_uri=[CALLBACK_URL]&response_type=code&scope=email name&response_mode=form_post");
  applePopup.focus();
}
return false;

Finally, handle the callback url (popup) with sign_in @user, and the popup should send the access_token back to the opener.

dli1022 commented 2 years ago

Hi I'm Dan and I'm using omniauth-apple 1.0.2, and omniauth 2.0.4 and tried all of the advice in this thread but am still consistently getting this error: ERROR -- : (apple) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: { "error": "invalid_client" } Omniauth for Facebook and Google works fine, just having trouble with Apple. Here are the omniauth.rb settings:

provider :apple, ENV['APPLE_CLIENT_ID'], '', { scope: 'email name', team_id: ENV['APPLE_TEAM_ID'], key_id: ENV['APPLE_KEY_ID'], pem: ENV['APPLE_KEY'], callback_path: "/users/auth/apple/callback", provider_ignores_state: true, authorized_client_ids: [ ENV['APPLE_CLIENT_ID'] ] }

I'm using the service id as the APPLE_CLIENT_ID, I have recreated the service IDs and keys multiple times already but still does not have any luck. Any help is highly appreciated. Thanks

taco-chen commented 2 years ago

@dli1022 did you try the url directly? and make sure your [CALLBACK_URL] has been listed on the Apple Developers > Web Authentication Configuration

https://appleid.apple.com/auth/authorize?client_id=[CLIENT_ID]&redirect_uri=[CALLBACK_URL]&response_type=code&scope=email name&response_mode=form_post"
dli1022 commented 2 years ago

@taco-chen Thanks for the tip. When I used the URL you posted above, I get the Apple signin prompt and redirected to my own website, after that I get exactly the same error. Maybe my key and key id pairs are bad so that Omniauth can't decode the Apple call back post? But I have already recreated this key multiple times...

dli1022 commented 2 years ago

I finally figured this out. TL;DR: The quick solution is to downgrade Oauth2 version 2+ to 1.4.10. Here are the details:

The issue was caused by this breaking change introduced in Oauth2 gem version 2.0.0:

https://github.com/oauth-xx/oauth2/pull/312 - BREAKING: Set :basic_auth as default for :auth_scheme instead of :request_body. This was default behavior before 1.3.0. (@tetsuya, @wy193777)

Apple servers needs the "client_id" and "client_secret" as part of the html body for the http POST request to get the token. But when Oauth2 sets :auth_scheme to :basic_auth, it does not add "client_id" and "client_secret" to the body. Only works when :auth_scheme == :request_body.

I also opened a issue to omniauth-apple to allow for a setting to specifcy :auth_scheme to "request_body". https://github.com/nhosoya/omniauth-apple/issues/85

nov commented 1 year ago

I guess no issues anymore except for oauth2 v2 incompatibility? then I close this issue since we have https://github.com/nhosoya/omniauth-apple/issues/85 for oauth2 gem issue