Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apple Sign-In: How to use it for custom server endpoint authentication?

My use case is that once I have a user signed into my app, I use the Oauth token, resulting from the sign-in, when I make endpoint calls from my app to my custom server-- to authenticate the caller. E.g., I use Google Sign In in this way.

This method (e.g., with Google Sign In) has several useful properties:

  1. Updated tokens are created automatically on the client app.

  2. My custom server can easily verify the validity of the token, using Google's endpoints.

  3. Initial token verification can take place early in the endpoint request processing-- without access to the custom servers database (as in the style in https://github.com/IBM-Swift/Kitura-Credentials).

My question is: Given that we're being told we have to incorporate Apple Sign-In into our iOS apps (if we offer general purpose sign-in facilities), how can I do endpoint authentication with my custom server?

I see two alternatives, neither of which I like very much.

First, I can have my client app send an Apple Sign In id_token to my server and ignore the exp (expiry) field. I can regenerate the id_token periodically (apparently, no more than once a day) and send it back to my client. I don't like this idea both because of ignoring the expiry of the token, and because of the need to periodically send the token from server to client. (My app uses multiple sign in systems and this just creates extra difficulty).

Second, I could have my client send an Apple Sign In refresh token to my server. My server would need, of course, to initially generate that refresh token and send it back to the client. I like this idea even less than the first idea. My initial token verification in my custom server would need to access its database to look for a match this token. I can't generally use an Apple endpoint -- because, again, Apple is apparently going to throttle this verification.

Additionally, I don't really like the idea that my custom server can, at best, check on token validity once a day. If the user revokes the app's credentials, I would hope my custom sever would stop being able to operate on behalf of the user relatively quickly.

Thoughts?


10/5/19-- update to the first alternative above. Upon actual use of https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens for refresh token validation, I find that it is not actually generating an updated id token. It is generating an access token (but Apple doesn't define a use for that), and is validating the refresh token. And so, there is no way to send an updated id token to the client iOS app. Thus, using the first alternative, the expiry date of the id token cannot be used.

10/10/19-- update: I've written a blog article on this subject-- https://medium.com/@crspybits/apple-sign-in-custom-servers-and-an-expiry-conundrum-d1ad63223870

8/6/20-- update: Follow on blog article with possible path forward, pending details from Apple: https://medium.com/@crspybits/part-ii-apple-sign-in-custom-servers-and-an-expiry-conundrum-b3e9735dc079

like image 825
Chris Prince Avatar asked Oct 01 '19 04:10

Chris Prince


People also ask

How do I use Apple authentication?

Use the code displayed on your trusted deviceSign in with your Apple ID and password on a new device or browser. Look for a sign in notification on any of your trusted devices. Tap Allow to receive your verification code. Enter the verification code on your other device to complete sign in.

Does Sign in with Apple use OAuth?

How Sign In with Apple Works (Hint: it uses OAuth and OIDC) Thankfully, Apple adopted the existing open standards OAuth 2.0 and OpenID Connect to use as the foundation for their new API. While they don't explicitly call out OAuth or OIDC in their documentation, they use all the same terminology and API calls.

What is Apple ID authentication token?

The identity token is a JSON Web Token (JWT) and contains the following claims: iss. The issuer registered claim identifies the principal that issues the identity token. Because Apple generates the token, the value is https://appleid.apple.com .


1 Answers

In Get the most out of Sign in with Apple in WWDC 2020, at 11:30 in their presentation, they introduce server-to-server notifications to enable your server to monitor user account state changes on a real-time basis.

So far, few details on this though.

----------------- UPDATE (12/23/20) -----------------

I now have these server-to-server notifications working in a testing environment with my server. Some notes:

  1. I decided on the endpoint to use, on my server, to allow Apple to send my server these REST endpoint requests.

  2. I pasted that into developer.apple.com > Account > Certificates, Identifiers & Profiles > Identifiers > Select your app identifier > Click 'Edit' next to 'Sign In with Apple' > Server to Server Notification Endpoint

  3. This endpoint is effectively unauthorized. E.g., it is made by Apple with no OAuth credential access to your server. How this is setup will depend on your server. I had a means to set up a new endpoint/route for my server that was unauthorized.

  4. I have the client side and other parts of my server set up to allow creation of accounts using Apple Sign In. So, using one of those accounts, I now started taking actions that would cause Apple to invoke their server-to-server notification endpoint on my server. I wanted to reverse engineer the details of the endpoint request Apple is making, since details are scarce. This provides some ideas on how to cause the notification events to occur: How to revoke Sign in with Apple credentials for a specific app? You can revoke credentials, but it's easier (because you can do it repeatedly) to enable and disable the email relay. Of course, to do this, you have to initially sign-in with Apple using the private/email relay.

  5. I next learned two things:

a) After you take the action (e.g., revoke the email relay), the server-to-server notification endpoint is accessed on your server within about 30 seconds. I had added various log output into my server, so could watch my server log and see this happening.

b) The endpoint request Apple makes to your server has body data containing JSON in the following format: {"payload" : "-- SNIP -- JWT"}

I'm using the following Swift structure to decode this.

    struct ApplePayload: Decodable {
        let payload: String // JWT
    }
  1. As Apple has indicated in the WWDC 2020 video (https://developer.apple.com/videos/play/wwdc2020/10173/), the main content of the body data is a JWT. Above, this is the value of the key "payload" in the JSON.

  2. The next step is decoding this JWT. I just guessed that it would use the same mechanism for decoding as with the JWT in other parts of the Apple Sign In server-side process. And specifically, in decoding the identity token (a JWT) passed up to your server by a client using Apple sign in. See https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple I had some code that did this JWT decoding, so I factored that out and put it in a common place: https://github.com/SyncServerII/AppleJWTDecoder.git Integrating that into my server-side processing of Apple's server-to-server notification requests, I found that indeed this JWT can be decoded in this manner.

  3. Another aspect that became evident is that the structure indicated by Apple in the WWDC 2020 video isn't 100% what is present in the JWT, after decoding. Specifically, in my tests so far at least the events field is not an array, rather it has a single value. See https://github.com/SyncServerII/AppleJWTDecoder/blob/main/Sources/AppleJWTDecoder/AppleSignInClaims.swift for a Swift structure.

I am now successfully parsing the JWT. The next main step on my server is to actually utilize the different event types in my server to take actions. For me this is going to involve the two account (not email) related actions:

User decided to stop using their Apple Id with your application. And should be treated as a sign-out by the user. E.g., when a user decides to disconnect your application from Settings. (From https://developer.apple.com/videos/play/wwdc2020/10173/)

Also considered a request from user to "delete their app account" (broader context: "Server to Server Notification Endpoint Sign in with Apple server to server notifications allow you to receive important updates about your users and their accounts. Notifications are sent for each app group when users change mail forwarding preferences, delete their app account, or permanently delete their Apple ID. Each group of apps can have one URL, which must be absolute and include the scheme, host, and path. TLS 1.2 or higher is required to receive notifications. Learn more.") To see these docs, go to: developer.apple.com > Account > Certificates, Identifiers & Profiles > Identifiers > Select your app identifier > Click 'Edit' next to 'Sign In with Apple' > Server to Server Notification Endpoint

case consentRevoked = "consent-revoked"

    

User has asked Apple to delete their Apple Id. The user identifier will now no longer be valid.

case accountDelete = "account-delete"

My plan is to take both of these events as equivalent- and delete the user's account on my server. I'm then going to have to consider how to communicate this to my client (iOS app). It will need to know that the user has deleted their account.

like image 50
Chris Prince Avatar answered Oct 02 '22 12:10

Chris Prince