We've moved discussions to Discord

Sign in with Apple - now working!

Rob Jonson
My app will be connected to an iOS app, so if I want any social sign in, then Apple insist I add Sign in with Apple. (annoying but unavoidable)

I have got things working as far as the callback with the following. 

Many edits later, I have things working. I'll leave this as a how-to for the next person...

Setup


#lib/jumpstart/lib/jumpstart/omniauth.rb

add apple to the 

AVAILABLE_PROVIDERS = {
...
,
      "apple" => {
        name: "Apple",
        scope: "email name",
        provider: :apple,
        icon: :apple
      }
    }.freeze

edit has_credentials to not check for private key (apple doesn't provide one)

    def self.has_credentials?(gem_name)
      provider = AVAILABLE_PROVIDERS.dig(gem_name, :provider)
      credentials_for(provider).dig(:public_key).present?
      #apple doesn't have a normal private key
    end

#/app/javascript/stylesheets/components/connected_accounts.scss

.bg-apple { background: #000000; }
.text-apple { color: #000000; }
.btn-apple {
  @apply bg-apple text-white;
}

#in credentials, add details in the format
(instructions here: https://github.com/nhosoya/omniauth-apple/pull/62/files)

  apple:
    public_key: 'app.skydivedesigner.beta'
    private_key: ''
    scope: 'email name'
    team_id: 'MYTEAMID'
    key_id: 'MYKEYID'
    pem: |
      -----BEGIN PRIVATE KEY-----
      real
      contents
      of .p8 file
      you get from apple
      -----END PRIVATE KEY-----


Apple doesn't let you test on localhost, so I set beta.skydivedesigner.app to point to localhost and setup local ssl following instructions here

https://blog.cloud66.com/running-rails-development-with-a-fake-domain-and-ssl/
(nb: command seems to be caddy run now rather than just caddy)

the other change is that it seems the session cookie has to be set to SameSite none.
https://github.com/nhosoya/omniauth-apple/issues/58

I just tweaked the config provided for multidomain

#/config/initializers/session_store.rb
#probably overdoing it a bitRails.application.config.session_store :cookie_store, key: '_jumpstart_session', domain: :all, tld_length: 2, same_site: :none

forgery protection fails, so I disable this for apple (not 100% sure this is a good idea!)

#/app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_forgery_protection only: :apple

and now it works.

so, actually this is all working now (in dev at least...)

thanks

Rob Jonson
and then it gets weird in production.

one of the steps in the gem is to fetch apple's keys.

I can check that the server can access the info by running

curl https://appleid.apple.com/auth/keys
#correctly returns the keys

however in the gem, it uses 

uri = URI.parse('https://appleid.apple.com/auth/keys')
response = Net::HTTP.get_response(uri)

If I type these into the rails console, then I get a 403 (which is the same as happens for the app)

Can anyone suggest why Net::HTTP.get_response would get a 403 when curl succeeds?

thanks.

Rob Jonson
additional update - Apple #$$%!
it turns out that from some locations, Apple give a 403 if the useragent for the request is 'Ruby'
My NewYork server gets dinged, My London & Amsterdam servers are fine.
I have added a fix to the oauth_apple gem and sent a pull request.
Adam Howell
Thanks for laying all this out ! This is one of my next todos and I was dreading it… 
Hi, thanks putting this together.  I haven't had success, yet.  Any idea why I keep getting the nonce_mismatch?

I'm using the apple button
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script>
AppleID.auth.init({
  clientId: "app.example",
  scope: "email name",
  redirectURI: "https://my.ngrok.io/users/auth/apple/callback",
  state: "TEST-HEX",
  usePopup: false,
  response_mode: "id_token",
  nonce: "<%= apple_signin_nonce %>",
});
</script>
app/helpers/application_helper.rb
  def apple_signin_nonce
    session["omniauth.nonce"] ||= SecureRandom.urlsafe_base64(16)
    session["omniauth.nonce"]
  end

and receiving this error

web     | Started POST "/users/auth/apple/callback" for 182.253.75.237 at 2022-06-28 10:42:23 +0800
web     | D, [2022-06-28T10:42:23.135569 #67393] DEBUG -- omniauth: (apple) Callback phase initiated.
web     | E, [2022-06-28T10:42:23.970234 #67393] ERROR -- omniauth: (apple) Authentication failure! nonce_mismatch: OmniAuth::Strategies::OAuth2::CallbackError, nonce_mismatch | nonce mismatch
web     | Processing by Users::OmniauthCallbacksController#failure as HTML
web     |   Parameters: {"state"=>"TEST-HEX", "code"=>"...(removed)...", "id_token"=>"...(removed)..."}
web     | Redirected to https://my.ngrok.io/

Any insight would be appreciated! Thanks!

Rob Jonson
My app will be connected to an iOS app, so if I want any social sign in, then Apple insist I add Sign in with Apple. (annoying but unavoidable)

I have got things working as far as the callback with the following. 

Many edits later, I have things working. I'll leave this as a how-to for the next person...

Setup


#lib/jumpstart/lib/jumpstart/omniauth.rb

add apple to the 

AVAILABLE_PROVIDERS = {
...
,
      "apple" => {
        name: "Apple",
        scope: "email name",
        provider: :apple,
        icon: :apple
      }
    }.freeze

edit has_credentials to not check for private key (apple doesn't provide one)

    def self.has_credentials?(gem_name)
      provider = AVAILABLE_PROVIDERS.dig(gem_name, :provider)
      credentials_for(provider).dig(:public_key).present?
      #apple doesn't have a normal private key
    end

#/app/javascript/stylesheets/components/connected_accounts.scss

.bg-apple { background: #000000; }
.text-apple { color: #000000; }
.btn-apple {
  @apply bg-apple text-white;
}

#in credentials, add details in the format
(instructions here: https://github.com/nhosoya/omniauth-apple/pull/62/files)

  apple:
    public_key: 'app.skydivedesigner.beta'
    private_key: ''
    scope: 'email name'
    team_id: 'MYTEAMID'
    key_id: 'MYKEYID'
    pem: |
      -----BEGIN PRIVATE KEY-----
      real
      contents
      of .p8 file
      you get from apple
      -----END PRIVATE KEY-----


Apple doesn't let you test on localhost, so I set beta.skydivedesigner.app to point to localhost and setup local ssl following instructions here

https://blog.cloud66.com/running-rails-development-with-a-fake-domain-and-ssl/
(nb: command seems to be caddy run now rather than just caddy)

the other change is that it seems the session cookie has to be set to SameSite none.
https://github.com/nhosoya/omniauth-apple/issues/58

I just tweaked the config provided for multidomain

#/config/initializers/session_store.rb
#probably overdoing it a bitRails.application.config.session_store :cookie_store, key: '_jumpstart_session', domain: :all, tld_length: 2, same_site: :none

forgery protection fails, so I disable this for apple (not 100% sure this is a good idea!)

#/app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_forgery_protection only: :apple

and now it works.

so, actually this is all working now (in dev at least...)

thanks

Rob Jonson
and then it gets weird in production.

one of the steps in the gem is to fetch apple's keys.

I can check that the server can access the info by running

curl https://appleid.apple.com/auth/keys
#correctly returns the keys

however in the gem, it uses 

uri = URI.parse('https://appleid.apple.com/auth/keys')
response = Net::HTTP.get_response(uri)

If I type these into the rails console, then I get a 403 (which is the same as happens for the app)

Can anyone suggest why Net::HTTP.get_response would get a 403 when curl succeeds?

thanks.

Rob Jonson
additional update - Apple #$$%!
it turns out that from some locations, Apple give a 403 if the useragent for the request is 'Ruby'
My NewYork server gets dinged, My London & Amsterdam servers are fine.
I have added a fix to the oauth_apple gem and sent a pull request.
Adam Howell
Thanks for laying all this out ! This is one of my next todos and I was dreading it… 
Hi, thanks putting this together.  I haven't had success, yet.  Any idea why I keep getting the nonce_mismatch?

I'm using the apple button
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script>
AppleID.auth.init({
  clientId: "app.example",
  scope: "email name",
  redirectURI: "https://my.ngrok.io/users/auth/apple/callback",
  state: "TEST-HEX",
  usePopup: false,
  response_mode: "id_token",
  nonce: "<%= apple_signin_nonce %>",
});
</script>
app/helpers/application_helper.rb
  def apple_signin_nonce
    session["omniauth.nonce"] ||= SecureRandom.urlsafe_base64(16)
    session["omniauth.nonce"]
  end

and receiving this error

web     | Started POST "/users/auth/apple/callback" for 182.253.75.237 at 2022-06-28 10:42:23 +0800
web     | D, [2022-06-28T10:42:23.135569 #67393] DEBUG -- omniauth: (apple) Callback phase initiated.
web     | E, [2022-06-28T10:42:23.970234 #67393] ERROR -- omniauth: (apple) Authentication failure! nonce_mismatch: OmniAuth::Strategies::OAuth2::CallbackError, nonce_mismatch | nonce mismatch
web     | Processing by Users::OmniauthCallbacksController#failure as HTML
web     |   Parameters: {"state"=>"TEST-HEX", "code"=>"...(removed)...", "id_token"=>"...(removed)..."}
web     | Redirected to https://my.ngrok.io/

Any insight would be appreciated! Thanks!

Notifications
You’re not receiving notifications from this thread.
© 2022 Jumpstart Pro by GoRails, LLC