|
| 1 | +# What is AppleAuth? |
| 2 | +AppleAuth is a very simple library for Java, based on Google Api Client, that encapsulates logic for communicating with [Apple's REST API for Sign in with Apple](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api). |
| 3 | +The main goal is to make the implementation of [Sign in with Apple](https://developer.apple.com/sign-in-with-apple/) easier for any web application. |
| 4 | + |
| 5 | +# Prerequisites |
| 6 | +## Configure Sign in with Apple from the Developer Portal |
| 7 | +In order to use Sign in with Apple you must enroll in the [Apple Developer Program](https://developer.apple.com/programs/enroll/). |
| 8 | +After you have enrolled in the program go to [Developer Account Help](https://help.apple.com/developer-account/) and navigate to Configure app capabilities > Sign in with Apple. |
| 9 | +There you can find the information for configuring Sign in with Apple for your app. |
| 10 | + |
| 11 | +## Display the "Sign in with Apple" button |
| 12 | +Next, you have to configure your web page for Sign in with Apple. Follow the guidelines from the official [documentation](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/configuring_your_webpage_for_sign_in_with_apple). You can also refer to this [link](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/displaying_sign_in_with_apple_buttons) to see how to setup the styles of the buttons. |
| 13 | + |
| 14 | +# Example |
| 15 | +## Using `AppleAuthProvider.java` `AppleClientPrivateKeyFactory.java` |
| 16 | +First order of business should be creating an instance of `ECPrivateKey` representing the client's(your) private key.<br/> |
| 17 | +`AppleKeyProvider` can help you create a `ECPrivateKey` if you have your private key as string or stream (from a p8 for example). |
| 18 | + |
| 19 | +Creating a new instance of `AppleAuthProvider`, should be trivial at this point. The only two parameters that are not |
| 20 | +self explanatory are the `SecretGenerator` and the collection of scopes.<br/> |
| 21 | +`SecretGenerator` is responsible for creating the auth's client_secret. A new instance of the class should cover most of the use cases. |
| 22 | +`scopes` is a collection that determines what information will re required from apple and what information will be populated in the returned id_token. |
| 23 | + |
| 24 | +Note: `AppleAuthProvider` is thread safe and is intended to be long lived. For best performance, we recommend you create a single instance of it, unless you need a second with different parameters. |
| 25 | + |
| 26 | +Once you have your `AppleAuthProvider` instance you can: |
| 27 | +- Call `getLoginLink` to get an apple oAuth2 login link. You can use the state parameter to carry over information to the redirect url. |
| 28 | +- Use `makeNewAuthorisationTokenRequest` to make a initial authorisation request to apple and retrieve user data based on the auth code from the redirect. |
| 29 | +- Use `makeNewRefreshTokenRequest` to verify that the user is still using 'Sign in with Apple' to sign in your system. |
| 30 | +## Handling initial response from Apple |
| 31 | +After the user clicks on the "Sign in with Apple" button on your page they will be redirected to https://appleid.apple.com/. |
| 32 | +After they provide their credentials Apple will make a POST request to the url that you have specified as Redirect URL. |
| 33 | +It will contain a ```code``` field. Its contents is what should be handed down to `makeNewAuthorisationTokenRequest` in order retrieve thee authorization token (it will also contain the state used to create the redirect url). |
| 34 | +Keep in mind that tokens returned from Apple are short-lived, so you should create a session or a user in your system |
| 35 | +using the returned ```AppleAuthorizationToken``` object. After that you can verify if the user is |
| 36 | +still logged in using "Sign in with Apple" by retrieving a refresh token using the ```makeNewRefreshTokenRequest``` method. |
| 37 | + |
| 38 | +```java |
| 39 | + public class AppleIdTokenManager { |
| 40 | + |
| 41 | + private final static String CLIENT_ID = "Your client id"; |
| 42 | + private static final String KEY_ID = "Your Key id"; |
| 43 | + private static final String TEAM_ID = "Your team id"; |
| 44 | + private static final String REDIRECT_URL = "Your redirect url"; |
| 45 | + |
| 46 | + public static void main(String[] args) throws IOException, InvalidKeySpecException { |
| 47 | + //Generating your private key. |
| 48 | + //This could be just a string containing the key. |
| 49 | + InputStream pkStream = AppleIdTokenManager.class |
| 50 | + .getClassLoader().getResourceAsStream("your_pk_file.p8"); |
| 51 | + AppleClientPrivateKeyFactory appleClientPrivateKeyFactory = new AppleClientPrivateKeyFactory(); |
| 52 | + ECPrivateKey privateKey = appleClientPrivateKeyFactory.getEcPrivateKey(pkStream); |
| 53 | + |
| 54 | + //Creating provider instance. |
| 55 | + SecretGenerator secretGenerator = new SecretGenerator(); |
| 56 | + AppleAuthProvider appleAuthProvider = new AppleAuthProvider( |
| 57 | + CLIENT_ID, |
| 58 | + KEY_ID, |
| 59 | + TEAM_ID, |
| 60 | + secretGenerator, |
| 61 | + privateKey, |
| 62 | + Arrays.asList(AppleUserScope.EMAIL, AppleUserScope.NAME), |
| 63 | + REDIRECT_URL |
| 64 | + ); |
| 65 | + |
| 66 | + //We are ready to start using the provider. |
| 67 | + |
| 68 | + //Generate a url and navigate the user to it. |
| 69 | + String loginLink = appleAuthProvider.getLoginLink("Some form of state"); |
| 70 | + |
| 71 | + //Once the user is redirected back to our domain get the "code" in the request. |
| 72 | + String authCode = "the code in the callback request"; |
| 73 | + //Now we can authenticate the user. |
| 74 | + AppleAuthorizationToken initialToken = appleAuthProvider.makeNewAuthorisationTokenRequest(authCode); |
| 75 | + //After the authentication we should check (not more than once every once 24 hours) if the user still |
| 76 | + // logged in using "Sign in with Apple" by retrieving a refresh token. |
| 77 | + AppleAuthorizationToken refreshToken = appleAuthProvider.makeNewRefreshTokenRequest(initialToken |
| 78 | + .getRefreshToken()); |
| 79 | + |
| 80 | + } |
| 81 | + } |
| 82 | +``` |
0 commit comments