Apple Identity Provider for Keycloak

repository·main·Indexed 43 days ago

https://github.com/klausbetz/apple-identity-provider-keycloak

An extension for Keycloak that enables 'Sign in with Apple' for web and native applications. It handles customizations to make Apple's non-standard OpenID Connect implementation compatible with Keycloak, including support for token exchange of Apple ID-Tokens and authorization codes for Keycloak tokens.

Tokens
3.2K
Snippets
6
Records
12
Agent score
55%

What's inside Apple Identity Provider for Keycloak

  1. Install the Apple Identity Provider for Keycloak

    main

    To install this extension, follow these steps:

    1. Obtain the latest JAR file from the releases page or include it as a Maven dependency via JitPack.
    2. Deploy the JAR file to your Keycloak instance by placing it in the /opt/keycloak/providers directory inside your container.
    3. Restart Keycloak (or restart your Docker container) to apply the changes.

    For Docker-specific instructions, refer to the docs/README_docker_installation.md file in this repository.

    # Example deployment step for Docker
    cp apple-identity-provider-keycloak.jar /opt/keycloak/providers/
    # Then restart the container
  2. Migrate configuration when upgrading from <1.14.0 to 1.14.0 or later

    main

    In version 1.14.0, the configuration field p8-Key was replaced by the Client-Secret field in the Keycloak Admin UI.

    If you are upgrading from a version older than 1.14.0, you must manually migrate your existing key. Copy the value from your old p8-Key field and paste it into the new Client-Secret field.

    Failure to do this will result in an "invalid_client" error from Apple during login attempts.

  3. Exchange Apple ID-Token for Keycloak tokens

    main

    You can trade an Apple ID-Token for Keycloak access and refresh tokens by calling the Keycloak realm's /token endpoint. This is the recommended method for native applications (like iOS apps) to provide native login options.

    Endpoint: <keycloak server url>/realms/<realm>/protocol/openid-connect/token
    Content-Type: application/x-www-form-urlencoded

    POST <keycloak server url>/realms/<realm>/protocol/openid-connect/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id=<your_client_id>
    grant_type=urn:ietf:params:oauth:grant-type:token-exchange
    subject_token=<apple_id_token>
    subject_issuer=apple
    subject_token_type=urn:ietf:params:oauth:token-type:id_token
    user_profile={ "name": { "firstName": "string", "lastName": "string" }, "email": "string" } (optional)
  4. Grant permissions to the Apple identity provider for token exchange

    main

    Once the preview features are enabled, you must configure Keycloak permissions to allow the Apple identity provider to exchange tokens. This involves two main stages: configuring the target client and configuring the Apple Identity Provider itself.

    Stage 1: Configure the target client

    1. Create a client: Ensure you have a client configured in Keycloak (you can use a new one with default settings or an existing one).
    2. Enable permissions: Go to your client settings and enable permissions.
    3. Create token-exchange permission: Create a new permission of type token-exchange on that client.
    4. Define Policies: In the Policies field of the new permission, create a policy that allows the exchange.

    Stage 2: Configure the Apple Identity Provider

    1. Enable permissions on Apple IDP: Navigate to the Apple Identity Provider settings and enable permissions.
    2. Create token-exchange permission on Apple IDP: Create a specific token-exchange permission directly on the Apple Identity Provider to authorize the exchange process.
  5. Install Apple Identity Provider via Docker

    main

    To run Keycloak with the Apple Identity Provider extension pre-installed, use a multi-stage Dockerfile. This approach builds an optimized Keycloak image that includes the provider, enables health and metrics endpoints, enables the token-exchange and admin-fine-grained-authz features, and configures PostgreSQL as the database.

    Note that the example Dockerfile uses version 1.7.0 of the Apple Identity Provider. Ensure you update the version in the ADD command to match the version you intend to use.

    FROM quay.io/keycloak/keycloak:22.0.1 as builder
    
    ENV KC_HEALTH_ENABLED=true
    ENV KC_FEATURES=token-exchange,admin-fine-grained-authz
    ENV KC_DB=postgres
    ENV KC_HTTP_RELATIVE_PATH="/auth"
    
    # Install custom providers
    # Apple Social Identity Provider - https://github.com/klausbetz/apple-identity-provider-keycloak
    ADD --chown=keycloak:keycloak https://github.com/klausbetz/apple-identity-provider-keycloak/releases/download/1.7.0/apple-identity-provider-1.7.0.jar /opt/keycloak/providers/apple-identity-provider-1.7.0.jar
    
    # build optimized image
    RUN /opt/keycloak/bin/kc.sh build 
    
    FROM quay.io/keycloak/keycloak:22.0.1
    
    COPY --from=builder /opt/keycloak/ /opt/keycloak/
    WORKDIR /opt/keycloak
    
    ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
  6. Exchange Apple authorization_code for Keycloak tokens

    main

    You can exchange an Apple authorizationCode for Keycloak tokens using the realm's /token endpoint. This method is used when your application flow provides an authorization code from Apple instead of an ID-Token.

    Endpoint: <keycloak server url>/realms/<realm>/protocol/openid-connect/token
    Content-Type: application/x-www-form-urlencoded

    POST <keycloak server url>/realms/<realm>/protocol/openid-connect/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id=<your_client_id>
    grant_type=urn:ietf:params:oauth:grant-type:token-exchange
    subject_token=<apple_authorization_code>
    subject_issuer=apple
    app_identifier=<service_id_or_bundle_id>
    app_redirect_uri=<redirect_uri>
    user_profile={ "name": { "firstName": "string", "lastName": "string" }, "email": "string" } (optional)
  7. Configure the Apple Identity Provider in Keycloak

    main

    To set up the provider, log into the Keycloak admin console, add Apple as a new Identity Provider, and fill in the following configuration options:

    OptionDescription
    Client IDYour Service ID from your Apple Developer Account.
    Client SecretRaw content of the .p8 key file from your Apple Developer Account. (Note: This replaced the p8 Key option since v1.14.0).
    Team IDYour Team ID from your Apple Developer Account.
    Key IDA key identifier from your Apple Developer Account.
    Default ScopesScopes to request from Apple (for web-based logins). Defaults to name%20email.
    Token-Exchange links existing accounts(Available since 1.16.0) If enabled, accounts are automatically linked to existing Keycloak accounts during token exchange flows.

    Critical Requirement: You must add the Keycloak broker URL to your valid redirect URLs in the Apple Developer Account: https://<keycloak-url>/realms/<realm>/broker/apple/endpoint

  8. Reference: Token Exchange Parameters

    main

    The following parameters are used when performing a token exchange via the Keycloak /token endpoint for the Apple Identity Provider.

    ### Using Apple ID-Token (Recommended)
    
    | Parameter            | Description |
    |----------------------|-------------|
    | `client_id`          | the client id of your Keycloak client |
    | `grant_type`         | `urn:ietf:params:oauth:grant-type:token-exchange` |
    | `subject_token`      | ID-Token from Apple |
    | `subject_issuer`     | `apple` (the name of the social provider in keycloak) |
    | `subject_token_type` | `urn:ietf:params:oauth:token-type:id_token` |
    | `user_profile`       | `{ "name": { "firstName": string, "lastName": string }, "email": string }` optional. The JSON string that Apple sends on the first login |
    
    ### Using Apple `authorization_code`
    
    | Parameter          | Description |
    |--------------------|-------------|
    | `client_id`        | the client id of your Keycloak client |
    | `grant_type`         | `urn:ietf:params:oauth:grant-type:token-exchange` |
    | `subject_token`      | `authorizationCode` from Apple |
    | `subject_issuer`     | `apple` (the name of the social provider in keycloak) |
    | `user_profile`       | `{ "name": { "firstName": string, "lastName": string }, "email": string }` optional. The JSON string that Apple sends on the first login |
    | `app_identifier`   | the ServiceID/BundleID the authorization was invoked with. You can omit this field if the ServiceID in Keycloak is the same as the BundleID |
    | `app_redirect_uri` | the Redirect URI the authorization was invoked with (since `1.16.0`) |
  9. Check compatibility between Keycloak and the extension

    main

    Because this extension implements internal Keycloak SPIs, it is sensitive to Keycloak version changes. Use the following mapping to ensure compatibility:

    Keycloak VersionExtension Version
    < 17.0.0Not tested. Use at your own risk
    17.0.0 <= 19.0.31.2.0
    20.0.0 <= 20.0.51.3.0 <= 1.4.1
    21.0.0 <= 21.0.21.5.0
    21.1.0 <= 21.1.21.6.0
    22.0.0 < 23.0.01.7.0 <= 1.8.0
    23.0.0 < 25.0.01.9.0 <= 1.12.0
    25.0.0 < 26.2.31.13.0 <= 1.14.0
    26.3.0 < 26.4.71.15.0 <= 1.16.0
    >= 26.5.0>= 1.17.0

    Important Notes:

    • Keycloak v21.X.Y: The Admin UI does not display additional properties like Team ID or Key ID. You must use external configuration tools like terraform or keycloak-config-cli to configure the provider.
    • Keycloak v19 and v20: You must switch to the old Admin UI to use this extension effectively.