Skip to main content

Sign in with Apple

Project description

Sign in with Apple

A library facilitating the server-side validation of Sign in with Apple (SIWA) identity tokens.

This library has a very narrow focus. It addresses a small subset of the potential ways in which SIWA can be used. It does not attempt to address the web-based SIWA flow. It abstracts away RSA256, JSON Web Tokens, and other machinery used by SIWA, and attempts to provide a simple, clean interface for application development.

The problem this library solves

Suppose you have a macOS or iOS application. You present the SIWA interface (the "Sign in with Apple" button) to a user using AuthenticationServices. They sign in. Your app is provided with an instance of ASAuthorizationAppleIDCredential (the "client side credential"), containing data describing the user.

Suppose your system is controlled by a platform agnostic application programming interface (API). You wish to create a new user account, or sign in an existing user, via your API. Your app makes an HTTP request to your API asking it to create a new user or sign in an existing user based on the data contained the client side credential.

How do you know the data was provided by AuthenticationServices, and not just smashed together in a text editor? That is, how do you know the data are authentic on the server side?

Apple facilitates the authentication of the credential by providing a blob of data in the ASAuthorizationAppleIDCredential.identityToken property. This identity token contains a JSON Web Token ("JWT"), a standardised format for carrying credentials.

Validation of the credential may be achieved via asymmetric cryptography, using the RSA256 algorithm. Apple retains a secret encryption key, and publishes a related public key. Apple creates signature (a large string of text) using two inputs: Their private key, and the contents of the client side credential.

External parties like your API can verify the authenticity of that signature, and therefore the associated credential, using the public key published by Apple.

This library performs the following functions with respect to the above process:

  1. Retrieves Apple's public key
  2. Parses an identity token (ASAuthorizationAppleIDCredential.identityToken)
  3. Provides a boolean flag asserting that the credential is valid or not valid
  4. Provides convenient access to the content of the identity token (e.g the user email address)

Installation

Install Sign in with Apple via PyPi:

pip install siwa

Dependencies

This library is heavily dependent on PyJWT. All validation of identity tokens is peformed by PyJWT.

Marshalling of the Apple public RSA key into PKS12 format is performed by the PythonRSA library.

Usage

from siwa import IdentityToken, KeyCache

cache = KeyCache()  # The cache is optional but will reduce the time taken
                    # to validate tokens using the same public key

token = IdentityToken.parse(data=json_string)

token_is_valid = token.is_validly_signed(key_cache=cache)

# if `token_is_valid` is True, you can confidently proceed with the credential

# Useful properties (see type reference for more):
print(token.payload.email)
print(token.payload.unique_apple_user_id)

Public Type Reference

KeyCache

A store for Apple's public key. If you supply a KeyCache instance to IdentityToken.is_validly_signed, you can reduce the time it takes to validate the key, as IdentityToken will retrieve the public key from the KeyCache rather than making an HTTP request to Apple's servers.

Example Usage

key_cache = KeyCache()

IdentityToken

Represents a SIWA identity token. Initialise with .parse(:Union[bytes, str]) and then check validity with the .is_validly_signed instance method.

Methods

Class

.parse(data: Union[bytes, str]) -> IdentityToken

Instance
.is_validly_signed(
    audience: str,
    key_cache: Optional[KeyCache] = None,
    ignore_expiry: bool = False
) -> bool

Call .is_validly_signed to check if a token is valid. Optionally pass an instance of KeyCache to improve performance for repeated checks.

Optionally specify ignore_expiry=true if you do not wish for an expired token to be considered invalid (useful for testing purposes).

Properties

.payload: Payload

Example Usage

from siwa import IdentityToken
import json

# Suppose you have a file named token.json containing a SIWA token:
with open('token.json', 'r') as rfile:
    json_string = json.loads(rfile.read())

token = IdentityToken.parse(data=json_string)

token_is_valid = token.is_validly_signed(
    audience='blinkybeach.Makara'
)

print('The token is {v}'.format(
    v=('valid' if token_is_valid else 'not valid')
))

Payload

A store of data provided by Apple, describing the user.

Properties

unique_apple_user_id: str
expires_utc_seconds_since_epoch: int
issued_utc_seconds_since_epoch: int
email: str
email_is_private: Optional[bool]
real_person: Optional[RealPerson]

Example Usage

# Using `token` from the above `IdentityToken` example
payload = token.payload

print('The user\'s email is {e} and unique ID {i}'.format(
    e=payload.email,
    i=payload.unique_apple_user_id
))

RealPerson

An enumeration of possible values provided by Apple.

Cases

UNSUPPORTED
UNKNOWN
LIKELY_REAL

Testing

To test the library, create a file that contains a valid SIWA identity token. For example, one that you have obtained from AuthenticationServices in Xcode.

Run test.py, passing command line arguments:

--example-jwt-file: the relative path to your identity token file --audience: the audience for the token

$ python3 test.py --example-jwt-file example/jwt/file --audience \
blinkybeach.Makara

Contact

@hugh_jeremy on Twitter or email hugh@blinkybeach.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

siwa-0.0.6.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

siwa-0.0.6-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file siwa-0.0.6.tar.gz.

File metadata

  • Download URL: siwa-0.0.6.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.24.0 setuptools/50.2.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.8.5

File hashes

Hashes for siwa-0.0.6.tar.gz
Algorithm Hash digest
SHA256 72abf186e1056274b2e2ee3a12dfdcfa9939cef9a8f71410c3f239bcecd73876
MD5 203dd6036286bf8ca9b89794aa7b5505
BLAKE2b-256 b861b56c077b34f7a97a8c5d2b160554080e77fbb19f5d5035f30bfb1922458d

See more details on using hashes here.

File details

Details for the file siwa-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: siwa-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.24.0 setuptools/50.2.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.8.5

File hashes

Hashes for siwa-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 937a9ee9e83e97d71b4039ebd046f38b659f6f407bbcdfdc28f7dc2fef6485c3
MD5 5cf9ff24b6e5326fd413468f98d2731d
BLAKE2b-256 6955d82dcda5b144dd67efc2a7df3290a3e610b4345cdc49264d7d18f5020e3c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page