Sign in with Apple

In addition to David’s comments above I found a related topic on Apple’s developer support site which attracted an official response that confirms the issue:

https://forums.developer.apple.com/thread/121496

Official Response:

Hi aslkdjalksdjasdasd,
This behaves correctly, user info is only sent in the ASAuthorizationAppleIDCredential upon initial user sign up. Subsequent logins to your app using Sign In with Apple with the same account do not share any user info and will only return a user identifier in the ASAuthorizationAppleIDCredential. It is recommened that you securely cache the initial ASAuthorizationAppleIDCredential containing the user info until you can validate that an account has succesfully been created on your server.
Patrick

As one developer comments:

So wait… If for some reason the first redirect from Apple gets lost for one of many VERY common reasons then we’ve permanently lost that user since there’s no other way to get their information. There is NO other way to get this info?

and another:

Or if something goes wrong downstream, we would have the customers complaining and support will tell them to go into AppleId website to revoke the permission, so they can properly register again. I believe this will be a poor experience and will make people not using this login mechanism if they start having this sort of problems.

So I don’t think you can safely use this in Production, sadly. This would be a support nightmare.

I suggest we put this to sleep until Apple wakes up to the problem they’ve created: in their attempt to improve security it seems they’ve over-compromised robustness.

10 Likes

That’s a bummer. :cry:

1 Like

Apple has updated their “Sign in with Apple” developer page to include more information about data collection, data management, etc.
https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/data-management/

4 Likes

I have opened a pull request to update the omniauth-apple gem to the latest version, which includes this commit that sounds like it might resolve the issue of not receiving the user’s email on every login.

In order to try this out I followed the recommended blog post to set up the credentials, but there are two things I couldn’t figure out so far:

  • What’s the path for the return URL redirect that is needed to set up the service ID with Apple?
  • How do I get the “verification txt”, or is that not required? Searching around I found mentions of this being downloadable from Apple as part of the domain/email communication setup, but this seems to be no longer the case:
2 Likes

Thanks.

Normally you submit a PR after you’ve successfully tested something :wink:

Please confirm when you have.

Seems like a no-brainer though but I would be more encouraged if we had a statement from Apple that they now send email every time. Changing the gem version will not resolve that if Apple hasn’t addressed the core issue.

I’ll take a look at my setup when I re-subscribe to being an Apple Developer which i’ve not yet done … (this debacle was a bit of a discouragement tbh)

@David

I have tried bumping our fork of the plugin to use the latest omniauth-apple. (Note that there are some other changes required, not just a bump of the version number).

tl;dr: it’s still broken

I managed to hack it into working on my sandbox, but it still has a number of issues:

  1. Apple is using a POST request on the callback. This is not common in OAuth implementations because it means samesite=Lax cookies will not be sent with the request. That means Discourse is unable to read session cookies during the callback, and therefore throws a CSRF error.

    INSECURE workaround is to disable this security by changing Discourse cookies to samesite=None

  2. Using a POST request without a CSRF token also trips another security measure in core.

    INSECURE workaround is to remove this line

  3. I was getting a 403 from apple when the omniauth gem was fetching the JWKs. I suspect that the Accept: header is not being set correctly, but haven’t verified that

    INSECURE workaround was to hard-code the keys

After all that, I finally managed to log in with apple. You can try it out on https://sandbox.dtaylor.uk (will leave it working for a few days, but please don’t enter anything sensitive on there because it is INSECURE)

And then… emails/names are still only included in the first authentication. You can try this out - sign in with apple, cancel the account creation, then try again. The second attempt will be missing your details.

So, assuming apple isn’t going to change things any time soon… how could we make this work?

For (1) and (2) I think we could convert Apple’s POST into a GET without hurting security. When we receive a POST on the callback, we render some javascript which sets window.location='/auth/apple/callback?code=...&state=.... From there, it would work just like any other provider. However, I think intercepting the POST would require some core API changes.

For (3), I think it could probably be fixed with a little work in the omniauth gem.

But we’re still stuck without name/email, so I’m not sure it’s worth fixing these other problems :cry:

7 Likes

Thanks for giving this another try and your analysis! Maybe submitting a technical support incident to Apple could shed some light on the remaining issues? From my experience they will more likely to provide possible solutions/workarounds there than in the Apple developer forums.

Issues 1 and 2 are caused by a deliberate implementation choice from Apple. So it’s not really a technical incident, and we can work around them. Issue 3 is with the omniauth-apple gem, so we can fix it.

The thing we need from apple is to include the name/email in subsequent authentication flows. Unfortunately they have acknowledged the behaviour, and said that it works as designed https://forums.developer.apple.com/thread/121496

This behaves correctly, user info is only sent in the ASAuthorizationAppleIDCredential upon initial user sign up. Subsequent logins to your app using Sign In with Apple with the same account do not share any user info and will only return a user identifier in the ASAuthorizationAppleIDCredential. It is recommened that you securely cache the initial ASAuthorizationAppleIDCredential containing the user info until you can validate that an account has succesfully been created on your server.

I am curious though, has anyone seen other websites using sign-in-with-apple? I think I’ve only seen native apps using it :thinking:

2 Likes

This feature makes a lot of sense to me, where our iOS app links to our discourse web and the app doesn’t have any login requirements for the other features.
It’s very convenient for users to login using this method since most are already logged in on the device and Apple Pay used for in-app purchases uses the same account.

IMO it would still make sense to contact Apple DTS about this to see what they suggest as a workaround, and also to give them the feedback that this is causing issues. (Unfortunately I’m not knowledgeable enough about this myself to have that conversation with them.)

It’s far from being as pervasive as Google/FB/etc, but I’ve seen in a couple places, e.g. ebay.com, wordpress.com and kayak.com.

2 Likes

They may use a different API though. There’s a JS script you can add, but that won’t integrate with Discourse’s more generic OAuth system I suspect:

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

Let’s take Kayak.com.

If I do a bit of sleuthing in the browser inspector I find this:

image

1 Like

They are using apple’s javascript library, yes. But it’s still using the same ‘OAuth’ (but not really OAuth) API behind the scenes.

Ebay are not even trying to pull the user info. After signing in with apple you get asked for your email:

Screenshot 2020-08-04 at 14.05.46

I suspect Kayak and Wordpress are caching user information from the first authentication attempt, per Apple’s recommendation.

I guess this is probably the approach we will need to take, but it’s not particularly robust (e.g. if network connection gets interrupted during the first attempt, or Discourse gets restored from a backup, or the user changes their apple email address). And, IMO, it is slightly worse from a privacy point of view (we have to store emails for users that haven’t even signed up yet!)

5 Likes

I think all the latest apple iOS changes make this workable now, no?

2 Likes

Did anything change related to Sign in with Apple recently?

We can certainly get it working as-is - it will require a few days of working around these issues. But then we’re still stuck only receiving email/name on the first ever login.

4 Likes

I think they refined it a bit, but I can not easily dig up any specific changes.

I think getting email only once is not a giant issue? I guess we need to test what happens when you change your email on your Apple ID email?

2 Likes

We should keep receiving the same UID, but we will not receive the new email. The user will have to update it manually in Discourse.

2 Likes

I guess we should double check this, but honestly I don’t see this as a giant drama holding us off from implementing this.

The sign in flow on iDevices is just so amazing with sign-in from apple, plus you get 2fa with faceid.

4 Likes

:+1: will add to my list to get the plugin up-to-scratch so we can test. If it works ok we can move it to core pretty easily.

12 Likes

Have passed the repo to David who has moved it to Discourse :slight_smile:

Thanks for taking this on.

10 Likes

I read this topic 2-3 times but I don’t remember if you guys tried to get the email from jwt token provided.

This is how i do it in native code. I’m not sure if the web api allows this.

First login you can get the email directly from ASAuthorizationAppleIDCredential.email.
For subsequent logins, the email can be found if you decode the jwt data and get the “email” field.

With this the feature can be implemented right?
The email provided will be the one chosen by the user, personal or random.