Socket
Socket
Sign inDemoInstall

cloudflare-apple-sign-in

Package Overview
Dependencies
1
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    cloudflare-apple-sign-in

A forked Apple sign-in REST API implementation adapted for Cloudflare Workers.


Version published
Weekly downloads
2
decreased by-83.33%
Maintainers
1
Install size
58.7 kB
Created
Weekly downloads
 

Readme

Source

cloudflare-apple-sign-in

A library for implementing Sign In With Apple Rest API in Cloudflare Workers. Forked from renarsvilnis/apple-sign-in-rest

See comparison table why you should choose apple-sign-in-rest over other apple-xxx package.

Supports Cloudflare Workers runtime.

Installation

Install the package:

npm install cloudflare-apple-sign-in

Documentation

Library is built on typescript and has well documented source code. This will provide a zero-effort developer expierence within your existing code editors. But the library also provides autogenered documentation using typedoc.

Documentation

Usage

0. Prerequisites

Here are some usefull links to get started with Sign In with Apple:

1. Create a AppleSignIn instance

Compared to other libraries apple-sign-in-rest chooses to create an instance with credentials instead of passing same credentials to functions on each call. This allows the library to validate them once and create apple public key cache per instance.

// Using modules
import {AppleSignIn} from 'apple-sign-in-rest';
// or if using common.js
const {AppleSignIn} = require("apple-sign-in-rest");

/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#constructor
 */
const appleSignIn = new AppleSignIn({
  /**
   * The clientId depends on that login "flow" you trying to create:
   *   - "web login" - this is the "serviceId"
   *   - "ios login" - this is the app "bundleId", choose only this if you trying to
   *                   verify user that has signed into using the native iOS way
   *
   */
  clientId: "com.my-company.my-app",
  teamId: "5B645323E8",
  keyIdentifier: "U3B842SVGC",
  privateKey: "-----BEGIN PRIVATE KEY-----\nMIGTAgEHIHMJKJyqGSM32AgEGC..."
})

2. (Optional) Get authorization URL

Start "Sign in with Apple" flow by redirecting user to the authorization URL.

Alternatively, you can use Sign In with Apple browser javascript library to handle this.

If you implement in Sign In With Apple trough iOS native login, you won't need to do this.

/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#getauthorizationurl
 */
const authorizationUrl = appleSignIn.getAuthorizationUrl({
  scope: ["name", "email"],
  redirectUri: "http://localhost:3000/auth/apple/callback",
  // (Optional) Value of the anti-forgery unique session token, as well as any other information needed to recover the context when the user returns to your application, e.g., the starting URL.
  state: "123",
  // (Optional) A random value generated by your app that enables replay protection when present.
  nonce: "insert-generated-uuid",
});

2. Get access token

2.1. Get credentials return after successful sign in with Apple

Retrieve the "code" query parameter from the URL string when the user user redirect to your sites previously provided redirectUrl after a successfull Sign In With Apple.

Make sure to verify that the state matches what was set when creating the authorization url!

// Example: http://localhost:3000/auth/apple/callback?code=somecode&state=123
app.get("/auth/apple/callback", (req, res) => {
  const code = req.query.code;
  const state = req.query.state;

  // This depends how you implemented the storing "state"
  if (req.session.state && req.session.state !== state) {
    throw new Error("Missing or invalid state");
  }

  // Continues in next examples...
});

In the case of iOS the native-app sends the code to a custom endpoint on your app. Make sure that iOS app also securily passes along the fullName and idToken . From the backend you won't have access to the fullName and idToken can be used to verify the user without making appleSignIn.getAuthorization() call.

2.2. Create a userSecret
/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#createclientsecret
 */
const clientSecret = appleSignIn.createClientSecret({
  /**
   * Optionaly you can set the validity duration of the secret in seconds. Apple allows the secret to up to 6 months,
   * but if you are creating a clientSecret per request basis you can set your own expiration duration.
   * Defaults to 6 months.
   */
  expirationDuration: 5 * 60, // 5 minutes
});
2.2. Exchange retrieved "code" to user's access token.
/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#getauthorizationtoken
 */
const tokenResponse = await appleSignIn.getAuthorizationToken(clientSecret, code, {
  // Optional, use the same value which you passed to authorisation URL. In case of iOS you skip the value
  redirectUri: "http://localhost:3000/auth/apple/callback",
});

Result of appleSignIn.getAuthorizationToken command is a JSON object representing Apple's TokenResponse:

{
   // A token used to access allowed data. Currently has no use
    access_token: "ACCESS_TOKEN",
    // It will always be Bearer.
    token_type: 'Bearer',
    // The amount of time, in seconds, before the access token expires.
    expires_in: 3600,
    // used to regenerate new access tokens. Store this token securely on your server.
    refresh_token: "REFRESH_TOKEN",
    // A JSON Web Token that contains the user’s identity information.
    id_token: "ID_TOKEN"
}
2.4. Verify token signature and get unique user's identifier
/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#verifyidtoken
 */
const claim = await appleSignIn.verifyIdToken(tokenResponse.id_token, {
  // (Optional) verifies the nonce
  nonce: "nonce",
  // (Optional) If you want to check subject(sub field) of the jwt a.k.a "user_identifier|provider_id". Might be usefull in the case where iOS app also sends you it, so you can verify if it is correct
  subject: "000852.5g3d8d4b3db045b48b7a58fb07728e1e.1303",
  // (Optional) If you want to handle expiration on your own, useful in case of iOS as identityId can't be "refreshed"
  ignoreExpiration: true, // default is false
});

3. Refresh access token after expiration

Should call it no more once a day, else apple amy throttle your request.

/**
 * See docs for full list of options and descriptions:
 * https://renarsvilnis.github.io/apple-sign-in-rest/classes/_applesignin_.applesignin.html#refreshauthorizationtoken
 */
const refreshTokenResponse = await appleSignIn.refreshAuthorizationToken(clientSecret, refreshToken);
const { access_token } = refreshTokenResponse.access_token;

Comparison to other "apple sign in" libraries

There are many already packages on npm with very similar names. Most of them are missing features and/or abandoned. This package takes inspiration from apple-signin and implements features/fixes while comparing to other libraries.

The only other library I'd consider feature-full and ready to use besides this one is apple-signin-auth by A-Tokyo, seem to have missing key features.

apple-sign-in-restapple-signin-authapple-authapple-signin
Feature Full✅ (missing some minor options)
Apple Public Key Caching✅ (cache per class instance)✅ (global cache)
Passport.js library❌ (comming-soon)
Typed Support✅ (typescript based)✅ (flow based)
API Documentation✅ (auto generated docs using typedoc)
Usage Examples
Tools for easier contributors✅ (typescript, eslint, prettier, jest)✅ (flow, eslint, prettier, jest)
StatsNPMNPMNPMNPM

Contributing

Pull requests are always welcomed. 🙇🏻‍♂️ Please open an issue first to discuss what you would like to change.

Package has a pre-commit git hook that does typechecking, linting, unit testing and doc building (if see source code changes).

Helper scripts

# Build library, will create a library in /lib folder
npm run build

# Run unit tests
npm run test
npm run test:watch # watch mode

# Run typecheck and linter
npm run lint

# Attempts to fix all formatting and linting issues
npm run format

# Build docs
npm run docs

# Inspect documentation localy visit http://127.0.0.1:8080
npm run docs:serve

# By default docs are automatically built and added on pre-commit hook,
# if it sees staged changes to any /src files,
# you can override the logic by forcing to build docs by passing environmental
DOCS_FORCE=true git commit -m 'My awesome change'

# You also skip automatically adding docs to commit
DOCS_COMMIT=false git commit -m 'My awesome change'

# Commit but ignore ship the git hooks
git commit -m 'My awesome change' --no-verify

License

The MIT License

Copyright (c) 2020 Renārs Vilnis

Support

If you have any questions or need help with integration, then you can contact me by email renars.vilnis@gmail.com.

Keywords

FAQs

Last updated on 08 Mar 2024

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc