Sign-in with Apple is the authorization service provided by Apple which allows the user of your website to log in using their Apple ID and password. In this guide, I'll show you how to integrate it into your website.
Integrating Apple ID sign-in is not a straightforward process and can be challenging if you are doing this for the first time. To test our integration locally, we need to first set up a few tools. I couldn't find any articles discussing this stage, so I'm writing one for you.
To implement this, we won’t be working directly with the APIs provided by Apple Sign In with JS but to make our lives easier, we will be using the npm package that uses these APIs under the hood. So, let us begin.
Before diving into the implementation, ensure you are enrolled in the Apple Developer Program and have an Apple Developer account. Just like any other Apple service, this program is also a paid program.
As per docs,
ngrok is a globally distributed reverse proxy that secures, protects and accelerates your applications and network services, no matter where you run them. You can think of ngrok as the front door to your applications.
That's a lot to take in. The basic idea behind ngrok is that it helps us expose our local environment to the internet. It generates a secure URL we can share without having to deploy it anywhere.
You may wonder, why we need to expose our local environment to test the integration locally. It turns out that, Apple Sign-In don’t support HTTP domains. While generating the credentials required for the sign-in process we need to provide a HTTPS domain, which is why we're using ngrok.
ngrok has wonderful documentation to help you set up the ngrok CLI agent. Follow the instructions provide in this Getting Started guide.
Ensure that you create a static domain on your dashboard, by default ngrok provides random domain names every time you start the application. The final command to get your local application up and running may look like this -
ngrok http 8080 --domain <your static domain name>
After executing this command you can access your application at https://<your static domain name>. Try making some changes to your local code and the changes will automatically reflect on this domain. That is fantastic!
In this step, we need to create App ID, service ID, and register the domain we created above for Sign-In with Apple service.
com.example.app
)https://example.com/auth/apple
In this article we will be using the frontend URL of our application, the same domain the we generated in the ngrok step. We are doing this because we will be capturing the data on the client side, using the PopUp
option ( more on this in next step )We will be using react-apple-signin-auth npm package on our frontend, to install run -
yarn add react-apple-signin-auth
This package exports a React component that we can directly render in our application and pass the credentials as props -
// AppleSignIn.js
import AppleSigninButton from 'AppleSigninButton'
function AppleSignIn() {
const handleSuccess = (data) => {
const { authorization, user } = data
// Here you can send data to your backend service and process the response
// further based on your requirements
}
const authOptions = {
clientId: <CLIENT_ID>, // This is your service ID
scope: 'email name',
redirectURI: <REDIRECT_URL>,
nonce: 'nonce',
usePopup: true, // important to catch up data on the frontend
}
return (
<AppleSigninButton
authOptions={authOptions}
uiType="dark"
className="apple-auth-btn"
noDefaultStyle={false}
onSuccess={handleSuccess}
onError={(error: string) => console.error(error)}
/>
)
}
Checkout react-apple-signin-auth for more available props and customisation. You may also be interest in reading human interface guildlines by Apple.
For the first time a user logs in to your website using their Apple ID, the structure of the response sent by Apple looks like this.
{
"authorization": {
"state": "state", // state string passed in authOptions
"code": "code", // A single-use authentication code
"id_token": "id_token" // This is a JSON web token that we need to decode in backend
},
// user information requested in scope option
"user": {
"email": "email",
"name": {
"firstName": "firstName",
"lastName": "lastName"
}
}
}
Apple only sends the user object for the first time, for subsequent signs in by the same user, Apple only sends the authorization object. Ensure that the user information is saved in your database.
After Apple sends us the response including authorization
and user
object, we send this information to our backend to verify the token and store the user data in our database for future use.
We will use apple-signin-auth npm package to verify the token. To install, run
yarn add apple-signin-auth
Consider the resolver below, which handles our backend sign-in process. We import the the above-mentioned library and will use verifyIdToken
method to decode the idToken sent by the client in frontend process.
I'm taking the liberty of passing the idToken
and user
as parameters directly to the oAuth
method.
// oAuth.js
import appleSignin from 'apple-signin-auth';
export default const oAuth = async(idToken, user) => {
const { sub, email, iss } = await appleSignin.verifyIdToken(idToken, {
audience: <CLIENT_ID>,
ignoreExpiration: true,
});
// here we check if we already have the user stored in the database
// if there is no user we create a new user
}
We get a bunch of useful information after decoding the idToken
sub
if the unique identifier for the useremail
is, as you guessed, email of the user signed iniss
is the issuer-registered claim key, which in this case has value https://appleid.apple.com
You can find the full list of available information on apple-signin-auth Github repository.
At this stage, you can query your database to see if the user information is already available. If you don’t find the user that means this is the new user and we have the information about user’s name in the user
object. Make sure you save this information in your database for future use.
I hope that was useful for you. Thank you for taking the time to read this. If you have any suggestion to improve this post, please let me know. You can find me on Twitter and Linkedin.