How to add ‘Sign in with Apple’ button to your Android app using Kotlin
- November 16, 2019
- John Codeos
Today, I’m going to show you how to integrate the ‘Sign in with Apple‘ button into your Android app in 3 steps.
In this tutorial, you will learn:
- How to set up your Apple Developer Account to use a ‘Sign in with Apple’ button on Android
- How to set up a backend server and use it as a Callback URL
- Create a ‘Sign in with Apple’ button to your Android app and get the user’s info (First name, Last name, Email, User ID).
Before we start
Before we start, I want to explain how the authentication flow goes because is more complicated than other social logins, like ‘Login with Twitter’ or ‘Login with Facebook’.
First, when the user presses the ‘Sign In with Apple’ button, a Dialog with a WebView inside pop ups.
After they fill the data and give access to the app, Apple sends a POST request on the backend server.
Backend server returns the Authorization Code + User’s Info (First name, Last name and Email) + Client Secret through URL.
The app “catches” this URL and displays the user’s info.
Next, we the Authorization Code and Client Secret to exchange it for an Access Token.
This Access Token is inside a JSON, along with an ID Token.
We take the ID Token and we split it into pieces, with a dot (.) as a separator, and we take the 2nd one.
Lastly, we decode this string (JSON Web Token) to get User’s ID.
Step 1: Set up your app in the Apple Developer Account
Go into your Apple Developer Account, choose Certificates, Identifiers & Profiles, Identifiers on the left side, and then your app from the list.
On the list Capabilities, enable Sign In with Apple, press Edit, choose Enable as a primary App ID and press Save.
Press Save again and Confirm.
Now, go back and choose Keys on the left side.
Create a new key by pressing the + button next to the ‘Keys’ title.
Give a name and enable Sign In with Apple by ticking the box.
Press Configure and choose your Primary App ID and press Save.
Press Continue, in the next page press Register, and then Download. Keep that .p8 file, you’re gonna need it later.
‘Sign in with Apple‘ gives the users the option to hide their email address when they login.
To be able to contact those users, you need to set up a domain and a contact email in your Apple Developer Account.
Choose More from the left menu and press Configure.
In the next page, add your domain and email and press Register on both
To verify the domain, press Download and download the .txt file.
Go into your website’s FTP server, create a folder with a name .well-known (yes, with the dot in front) and paste it inside.
To test if it’s working, type: https://PUT_YOUR_DOMAIN_HERE.com/.well-known/apple-developer-domain-association.txt and check if a text comes out as a result.
After that, go back and press Verify. (It might take a while until Apple ‘see’ the file on your server.)
If everything is ok, you’ll see the following page:
Now you have to create a Service ID.
Go back and choose Identifiers on the left menu and then press the plus button.
On the next page, choose Service IDs and press Continue
Next, add a name for your Service ID in the Description field, put an identifier(It’s recommended to put your domain name in reverse, like: com.johncodeos and at the end add your app name), enable the Sign In with Apple and press Configure.
In the new window, choose your Primary App ID, add your verified domain name, your Callback URL in the Return URLs field (I’ll show you later how to set up your backend server), press Save, and then Continue.
Step 2: Setup the backend server
When the user gives access to the app, Apple makes a POST request to the Callback URL you added before.
To ‘catch’ user’s info and authorization code, you need to have a back-end server.
I already made a Node Js app easy for you to run on your backend server.
I suppose you already have a server (I’m using a $5 droplet from DigitalOcean), with Node Js and Nginx installed.
Login to your server through terminal and run the next command.
Change directory and install the app.
Edit the .env file
How to get the Private Key .p8 file
Copy the .p8 file you downloaded before (when you created the Key) and paste it inside the sign-in-with-apple folder through FTP. Copy the name of the file including the extension .p8 and replace the YOUR_PRIVATE_KEY_FILE
How to get the Key ID
Go into your Apple Developer Account, choose Certificates, Identifiers & Profiles, then choose Keys on the left, and then choose your app from the list. In the new page, copy the Key ID and replace the YOUR_KEY_ID
How to get the Team ID
Go into your Apple Developer Account, choose Membership from the left menu, copy the Team ID and replace the YOUR_TEAM_ID
How to get the Service ID
Go into your Apple Developer Account, choose Certificates, Identifiers & Profiles, then choose Identifiers on the left, change to Service IDs on the top right corner, and copy the IDENTIFIER and replace the YOUR_SERVICE_ID
After all that, your file will look like this.
Save the file by pressing control+X, then press Y and Enter
Now, you can start the Node Js app by running the following command inside the sign-in-with-apple folder.
You can test if everything setup correctly by visiting the URL: http://ADD_YOUR_SERVER_IP_HERE:3000 and you’ll see the text Cannot GET / at the top left of your page.
Apple doesn’t allow IP’s or localhost as a Callback URL, so you need to use a domain name.
Stop the app from running by pressing control+C, and run the following command.
Inside the server brackets add the following.
Save the file and restart the nginx server.
Go back and run the app again, and test if it’s working by visiting the URL: https://MY_DOMAIN_NAME.com/login/callback
To keep the app running, even if you close the terminal, install the process manager pm2
After you installed pm2, run the following command in your root folder…
…and paste the following code inside.
Replace all the fields, as you did in the .env before and save it.
Now you can run the app again with the following command.
To keep the app running, even when the server restarts, run the following command.
Step 3: Add ‘Sign in with Apple’ Button
First, add a Button to your XML file. In this example, we have a button in the middle of the activity_main.xml.
Create a new Kotlin object file by right-clicking on your app’s package name on the left side and go New > Kotlin File/Class.
Give it the name AppleConstants, choose Object and press OK.
Inside the new file, copy and paste the following code and replace the CLIENT_ID (Service ID) and REDIRECT_URI with yours.
In your AndroidManifest.xml file, add internet permission.
In your Kotlin class of your Activity (In this example is the MainActivity), add a listener to your button, and create a Dialog with a WebView inside.
This WebView uses a custom WebViewClient, named AppleWebViewClient.
This helps to ‘catch’ the URL with the Authorization Code, First name, Last name, Email and Client Secret after the user has given access to your app.
IMPORTANT: Only when the user gives access to your app for the first time the callback URL returns the user’s info (First name, Last name, and Email). All the other times, it’s only returns the Authorization Code and the Client Secret. This is the way ‘Sign in with Apple’ works.
Now, you need to exchange the Authorization Code for an Access Token by making an HTTP POST request using the Authorization Code, Redirect URI, Client ID (Service ID) and Client Secret you get before.
After the request, you get the Access Token and the ID Token.
You split the ID Token using the dot (.) as a separator and you take the 2nd piece.
You decode it using Base64 and you get the User ID as a result along with other user’s info, like email (but you already get that from the URL before).
That’s it! Done!!
One more thing…
If you want to test again the authorization process, revoke the app permissions from your Apple ID by going to http://appleid.apple.com, login with your account, under the APPS & WEBSITES USING APPLE ID press Manage…, choose your app, and press Stop Using Apple ID.
You can find the final project here
If you have any questions feel free to DM me on Twitter @johncodeos or leave a comment below!