### Installation using Docker Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Instructions on how to build and run a Keycloak container with the Apple Identity Provider extension pre-installed. ```APIDOC ## Installation using Docker Deploy the JAR file to Keycloak's providers directory for automatic provider registration. ```dockerfile FROM quay.io/keycloak/keycloak:26.5.0 as builder ENV KC_HEALTH_ENABLED=true ENV KC_FEATURES=token-exchange,admin-fine-grained-authz ENV KC_DB=postgres # Install Apple Identity Provider extension ADD --chown=keycloak:keycloak https://github.com/klausbetz/apple-identity-provider-keycloak/releases/download/1.17.0/apple-identity-provider-1.17.0.jar /opt/keycloak/providers/apple-identity-provider-1.17.0.jar RUN /opt/keycloak/bin/kc.sh build FROM quay.io/keycloak/keycloak:26.5.0 COPY --from=builder /opt/keycloak/ /opt/keycloak/ WORKDIR /opt/keycloak ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] ``` ```bash # Build and run the Keycloak container docker build -t my-keycloak:latest . docker run -p 8080:8080 my-keycloak:latest start-dev ``` ``` -------------------------------- ### Enable Token Exchange Feature in Keycloak Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt To use the token exchange functionality, you need to enable the 'token-exchange' and 'admin-fine-grained-authz' features when starting Keycloak. This is typically done via environment variables in a Docker container. The `start-dev` command is used here for development purposes. ```bash docker run -p 8080:8080 \ -e KC_FEATURES=token-exchange,admin-fine-grained-authz \ quay.io/keycloak/keycloak:26.5.0 start-dev ``` -------------------------------- ### Keycloak Provider Configuration for Apple Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Example JSON configuration for the Apple Identity Provider within Keycloak. This object specifies the necessary credentials and settings, such as Client ID, Client Secret (from the .p8 key), Team ID, Key ID, and scope preferences, to enable 'Sign in with Apple'. ```json { "alias": "apple", "providerId": "apple", "enabled": true, "trustEmail": true, "config": { "clientId": "com.example.service", "clientSecret": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHk...\n-----END PRIVATE KEY-----", "teamId": "ABCD123456", "keyId": "XYZ9876543", "defaultScope": "name%20email", "tokenExchangeAccountLinkingEnabled": "true" } } ``` -------------------------------- ### Keycloak Dockerfile with Apple Identity Provider Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This Dockerfile installs the Apple Identity Provider extension into a Keycloak image. It downloads the JAR file and adds it to the Keycloak providers directory before building the image. The build process ensures the extension is available for Keycloak to use. ```dockerfile FROM quay.io/keycloak/keycloak:26.5.0 as builder ENV KC_HEALTH_ENABLED=true ENV KC_FEATURES=token-exchange,admin-fine-grained-authz ENV KC_DB=postgres # Install Apple Identity Provider extension ADD --chown=keycloak:keycloak https://github.com/klausbetz/apple-identity-provider-keycloak/releases/download/1.17.0/apple-identity-provider-1.17.0.jar /opt/keycloak/providers/apple-identity-provider-1.17.0.jar RUN /opt/keycloak/bin/kc.sh build FROM quay.io/keycloak/keycloak:26.5.0 COPY --from=builder /opt/keycloak/ /opt/keycloak/ WORKDIR /opt/keycloak ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] ``` -------------------------------- ### Generate Client Secret for Apple SIWA (Ruby) Source: https://github.com/klausbetz/apple-identity-provider-keycloak/wiki/Troubleshooting-the-configuration-from-Apple This Ruby script generates a JWT client secret required for the Sign in with Apple OAuth flow. It uses the 'jwt' gem and requires your Apple Developer account's Team ID, Client ID (Service ID), Key ID, and the path to your P8 private key file. Ensure the 'jwt' gem is installed (`gem install jwt`). ```ruby require 'jwt' key_file = 'path/to/AuthKey_XYZ.p8' team_id = '' client_id = '' key_id = '' ecdsa_key = OpenSSL::PKey::EC.new IO.read key_file headers = { 'kid' => key_id } claims = { 'iss' => team_id, 'iat' => Time.now.to_i, 'exp' => Time.now.to_i + 86400*180, 'aud' => 'https://appleid.apple.com', 'sub' => client_id, } token = JWT.encode claims, ecdsa_key, 'ES256', headers puts token ``` -------------------------------- ### Build Docker Image (Shell) Source: https://github.com/klausbetz/apple-identity-provider-keycloak/blob/main/docs/README_docker_installation.md This shell command builds a Docker image from the Dockerfile in the current directory and tags it as 'my-keycloak:latest'. This image will contain the pre-configured Keycloak instance with the Apple Identity Provider. ```shell docker build -t my-keycloak:latest . ``` -------------------------------- ### Build and Run Keycloak Container Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Commands to build a Docker image for Keycloak with the Apple Identity Provider extension and then run it in development mode. This allows for local testing and development of the integration. ```bash # Build and run the Keycloak container docker build -t my-keycloak:latest . docker run -p 8080:8080 my-keycloak:latest start-dev ``` -------------------------------- ### Build Keycloak Docker Image with Apple Identity Provider (Dockerfile) Source: https://github.com/klausbetz/apple-identity-provider-keycloak/blob/main/docs/README_docker_installation.md This Dockerfile configures a Keycloak instance with the Apple Identity Provider extension. It enables health and metrics endpoints, token exchange, and fine-grained admin permissions, and specifies PostgreSQL as the database. The build process creates an optimized image. ```Dockerfile 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"] ``` -------------------------------- ### Enable Token Exchange Feature in Keycloak Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Instructions on how to enable the token-exchange feature in Keycloak, including Docker commands and Admin CLI configurations. ```APIDOC ## Enable Token Exchange Feature in Keycloak ### Description Instructions to enable the token-exchange feature in Keycloak, a prerequisite for certain token exchange flows. ### Start Keycloak with token-exchange feature enabled ```bash docker run -p 8080:8080 \ -e KC_FEATURES=token-exchange,admin-fine-grained-authz \ quay.io/keycloak/keycloak:26.5.0 start-dev ``` ### Configure token-exchange permissions via Keycloak Admin CLI Replace `$ADMIN_TOKEN` with a valid administrator access token and `{client-uuid}` with the actual UUID of your client. 1. **Enable permissions on your client:** ```bash curl -X PUT "https://keycloak.example.com/admin/realms/myrealm/clients/{client-uuid}/management/permissions" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"enabled": true}' ``` 2. **Create a client policy for token-exchange:** ```bash curl -X POST "https://keycloak.example.com/admin/realms/myrealm/clients/{client-uuid}/authz/resource-server/policy/client" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "allow-token-exchange", "clients": ["my-mobile-app"], "logic": "POSITIVE" }' ``` 3. **Enable permissions on Apple Identity Provider:** ```bash curl -X PUT "https://keycloak.example.com/admin/realms/myrealm/identity-provider/instances/apple/management/permissions" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"enabled": true}' ``` ``` -------------------------------- ### POST /token - Using Apple ID-Token Source: https://github.com/klausbetz/apple-identity-provider-keycloak/blob/main/README.md Exchange an Apple ID-Token for Keycloak tokens using the realm's token endpoint. This is the recommended method. ```APIDOC ## POST /token - Using Apple ID-Token ### Description Exchange an Apple ID-Token for Keycloak tokens. This method is recommended for its simplicity and security. ### Method POST ### Endpoint `/realms//protocol/openid-connect/token` ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of your Keycloak client. - **grant_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:token-exchange`. - **subject_token** (string) - Required - The ID-Token obtained from Apple. - **subject_issuer** (string) - Required - Should be set to `apple`. - **subject_token_type** (string) - Required - Must be `urn:ietf:params:oauth:token-type:id_token`. - **user_profile** (JSON string) - Optional - A JSON string containing user profile information (`{ "name": { "firstName": string, "lastName": string }, "email": string }`). This is only required for the first login if you wish to store the user's name. ### Request Example ``` POST /realms/myrealm/protocol/openid-connect/token HTTP/1.1 Host: keycloak.example.com Content-Type: application/x-www-form-urlencoded client_id=myclient&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=%7B%22name%22%3A%20%7B%22firstName%22%3A%20%22John%22%2C%20%22lastName%22%3A%20%22Doe%22%7D%2C%20%22email%22%3A%20%22john.doe%40example.com%22%7D ``` ### Response #### Success Response (200) - **access_token** (string) - The Keycloak access token. - **expires_in** (integer) - The expiration time of the access token in seconds. - **refresh_token** (string) - The Keycloak refresh token. - **scope** (string) - The scope of the access token. - **token_type** (string) - The type of the access token (e.g., Bearer). #### Response Example ```json { "access_token": "eyJ...", "expires_in": 3600, "refresh_token": "eyJ...", "scope": "openid profile email", "token_type": "Bearer" } ``` ``` -------------------------------- ### Provider Configuration Options Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Details on the configuration options available for the Apple Identity Provider within the Keycloak Admin Console. ```APIDOC ## Provider Configuration Options Configure the Apple Identity Provider in Keycloak Admin Console with credentials from your Apple Developer Account. | Option | |---|---| | `Client ID` | Your Service ID from Apple Developer Account | | `Client Secret` | Raw content of the .p8 key file | | `Team ID` | Your 10-character Team ID | | `Key ID` | A 10-character key identifier | | `Default Scopes` | Scopes to request (defaults to `name%20email`) | | `Token-Exchange links existing accounts` | Auto-link accounts during token exchange | ```json { "alias": "apple", "providerId": "apple", "enabled": true, "trustEmail": true, "config": { "clientId": "com.example.service", "clientSecret": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHk...\n-----END PRIVATE KEY-----", "teamId": "ABCD123456", "keyId": "XYZ9876543", "defaultScope": "name%20email", "tokenExchangeAccountLinkingEnabled": "true" } } ``` ``` -------------------------------- ### POST /token - Using Apple authorization_code Source: https://github.com/klausbetz/apple-identity-provider-keycloak/blob/main/README.md Exchange an Apple authorization code for Keycloak tokens using the realm's token endpoint. ```APIDOC ## POST /token - Using Apple authorization_code ### Description Exchange an Apple `authorizationCode` for Keycloak tokens. This method is used when a user authorizes your application via Apple's OAuth flow. ### Method POST ### Endpoint `/realms//protocol/openid-connect/token` ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of your Keycloak client. - **grant_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:token-exchange`. - **subject_token** (string) - Required - The `authorizationCode` obtained from Apple. - **subject_issuer** (string) - Required - Should be set to `apple`. - **user_profile** (JSON string) - Optional - A JSON string containing user profile information (`{ "name": { "firstName": string, "lastName": string }, "email": string }`). This is only required for the first login if you wish to store the user's name. - **app_identifier** (string) - Optional - The ServiceID/BundleID the authorization was invoked with. Can be omitted if it matches the ServiceID configured in Keycloak. - **app_redirect_uri** (string) - Optional - The Redirect URI the authorization was invoked with (available since version `1.16.0`). ### Request Example ``` POST /realms/myrealm/protocol/openid-connect/token HTTP/1.1 Host: keycloak.example.com Content-Type: application/x-www-form-urlencoded client_id=myclient&grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=APPLE_AUTHORIZATION_CODE&subject_issuer=apple&app_identifier=com.example.app&app_redirect_uri=https://myapp.com/callback ``` ### Response #### Success Response (200) - **access_token** (string) - The Keycloak access token. - **expires_in** (integer) - The expiration time of the access token in seconds. - **refresh_token** (string) - The Keycloak refresh token. - **scope** (string) - The scope of the access token. - **token_type** (string) - The type of the access token (e.g., Bearer). #### Response Example ```json { "access_token": "eyJ...", "expires_in": 3600, "refresh_token": "eyJ...", "scope": "openid profile email", "token_type": "Bearer" } ``` ``` -------------------------------- ### Configure Token Exchange Permissions via Keycloak Admin CLI Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt These commands configure the necessary permissions for token exchange within Keycloak using the Admin CLI. This involves enabling management permissions on the client and the Apple identity provider, and creating a client policy to allow token exchange for specific clients. ```bash # 1. Enable permissions on your client curl -X PUT "https://keycloak.example.com/admin/realms/myrealm/clients/{client-uuid}/management/permissions" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"enabled": true}' # 2. Create a client policy for token-exchange curl -X POST "https://keycloak.example.com/admin/realms/myrealm/clients/{client-uuid}/authz/resource-server/policy/client" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "allow-token-exchange", "clients": ["my-mobile-app"], "logic": "POSITIVE" }' # 3. Enable permissions on Apple Identity Provider curl -X PUT "https://keycloak.example.com/admin/realms/myrealm/identity-provider/instances/apple/management/permissions" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"enabled": true}' ``` -------------------------------- ### Web-Based OAuth Login Flow with Apple Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This section details the standard browser-based Sign in with Apple flow through Keycloak's identity broker, involving redirection, callback handling, and token exchange. ```APIDOC ## Web-Based OAuth Login Flow ### Description Standard browser-based Sign in with Apple flow through Keycloak's identity broker. ### Step 1: Redirect user to Keycloak's Apple broker URL **Browser navigates to:** `https://keycloak.example.com/realms/myrealm/broker/apple/login?client_id=my-web-app&redirect_uri=https://myapp.example.com/callback&response_type=code&scope=openid` ### Step 2: User authenticates with Apple, Keycloak receives callback **Method:** POST **Endpoint:** `https://keycloak.example.com/realms/myrealm/broker/apple/endpoint` **Parameters:** - **state** (string) - Required - State parameter for security. - **code** (string) - Required - Authorization code received from Apple. - **user** (JSON string) - Optional - User profile information (firstName, lastName, email) on first login. ### Step 3: Exchange the authorization code for tokens #### POST /token ##### Description Exchanges the authorization code received from the Apple callback for Keycloak tokens. ##### Method POST ##### Endpoint `https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token` ##### Parameters - **client_id** (string) - Required - The client ID of your web application. - **client_secret** (string) - Required - The client secret for your web application. - **grant_type** (string) - Required - Must be `authorization_code`. - **code** (string) - Required - The authorization code received from the Apple callback. - **redirect_uri** (string) - Required - The redirect URI configured for your web application. ##### Request Example ```bash curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-web-app" \ -d "client_secret=my-client-secret" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE_FROM_CALLBACK" \ -d "redirect_uri=https://myapp.example.com/callback" ``` ##### Response ###### Success Response (200) - **access_token** (string) - The access token. - **expires_in** (integer) - The lifetime in seconds of the access token. - **refresh_token** (string) - The refresh token. - **token_type** (string) - The type of token, usually 'Bearer'. - **id_token** (string) - The ID token. ###### Response Example ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` ``` -------------------------------- ### Web-Based OAuth Login Flow with Apple Identity Provider Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This section outlines the standard browser-based Sign in with Apple flow through Keycloak's identity broker. It involves redirecting the user to Keycloak, user authentication with Apple, and then exchanging the received authorization code for tokens. The `client_secret` is required for the token exchange. ```bash # Step 1: Redirect user to Keycloak's Apple broker URL # Browser navigates to: https://keycloak.example.com/realms/myrealm/broker/apple/login?client_id=my-web-app&redirect_uri=https://myapp.example.com/callback&response_type=code&scope=openid # Step 2: User authenticates with Apple, Keycloak receives callback at: # POST https://keycloak.example.com/realms/myrealm/broker/apple/endpoint # Form parameters: state, code, user (JSON with firstName, lastName, email on first login) # Step 3: Exchange the authorization code for tokens curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-web-app" \ -d "client_secret=my-client-secret" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE_FROM_CALLBACK" \ -d "redirect_uri=https://myapp.example.com/callback" ``` -------------------------------- ### Verify Apple Client Secret with Apple's Token Endpoint Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This command verifies the generated client secret by making a direct request to Apple's token endpoint. It uses the `client_id`, the generated `client_secret` (from the Ruby script), the authorization `code` received from Apple, and the `redirect_uri`. This is useful for debugging authentication issues. ```bash curl -X POST "https://appleid.apple.com/auth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=com.example.service" \ -d "client_secret=GENERATED_JWT_FROM_RUBY_SCRIPT" \ -d "code=AUTHORIZATION_CODE_FROM_APPLE" \ -d "grant_type=authorization_code" \ -d "redirect_uri=https://webhook.site/your-unique-id" ``` -------------------------------- ### Generate Client Secret JWT (Manual Verification) Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Provides Ruby code to generate a JWT client secret for debugging Apple authentication issues and a cURL command to verify the configuration. ```APIDOC ## Generate Client Secret JWT (Manual Verification) ### Description Generate the JWT client secret manually for debugging Apple authentication issues and verify the configuration. ### Generate Apple client secret using Ruby Save the following code as `client_secret.rb` and replace placeholders with your actual values. ```ruby # client_secret.rb - Generate Apple client secret for testing require 'jwt' key_file = 'AuthKey_XYZ9876543.p8' team_id = 'ABCD123456' client_id = 'com.example.service' key_id = 'XYZ9876543' ecdsa_key = OpenSSL::PKey::EC.new IO.read key_file headers = { 'kid' => key_id } claims = { 'iss' => team_id, 'iat' => Time.now.to_i, 'exp' => Time.now.to_i + 86400*180, # 180 days expiration 'aud' => 'https://appleid.apple.com', 'sub' => client_id } token = JWT.encode claims, ecdsa_key, 'ES256', headers puts token ``` **Output Example:** ``` eyJhbGciOiJFUzI1NiIsImtpZCI6IlhZWjk4NzY1NDMifQ.eyJpc3MiOiJBQkNEMTIzNDU2IiwiaWF0IjoxNjk5OTk2NDAwLCJleHAiOjE3MTU1NDg0MDAsImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJjb20uZXhhbXBsZS5zZXJ2aWNlIn0.signature ``` ### Verify the configuration with Apple's token endpoint Use the generated JWT client secret to test Apple's token endpoint. **Method:** POST **Endpoint:** `https://appleid.apple.com/auth/token` **Request Example:** ```bash curl -X POST "https://appleid.apple.com/auth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=com.example.service" \ -d "client_secret=GENERATED_JWT_FROM_RUBY_SCRIPT" \ -d "code=AUTHORIZATION_CODE_FROM_APPLE" \ -d "grant_type=authorization_code" \ -d "redirect_uri=https://webhook.site/your-unique-id" ``` **Parameters:** - **client_id** (string) - Required - Your service ID. - **client_secret** (string) - Required - The JWT client secret generated above. - **code** (string) - Required - The authorization code received from Apple. - **grant_type** (string) - Required - Must be `authorization_code`. - **redirect_uri** (string) - Required - The redirect URI used during the initial authorization request. ``` -------------------------------- ### Token Exchange with Apple ID Token Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This `curl` command demonstrates how to exchange an Apple ID token for Keycloak tokens. It's suitable for native applications that have obtained an ID token directly from Apple's Sign-In SDK. The request includes the client ID, grant type, the Apple ID token, issuer, and token type. ```bash # Exchange Apple ID Token for Keycloak tokens curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-mobile-app" \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ -d "subject_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmV4YW1wbGUuc2VydmljZSIsImV4cCI6MTcwMDAwMDAwMCwiaWF0IjoxNjk5OTk2NDAwLCJzdWIiOiIwMDAxMjMuYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZi4xMjM0IiwiZW1haWwiOiJ1c2VyQHByaXZhdGVyZWxheS5hcHBsZWlkLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSJ9.signature" \ -d "subject_issuer=apple" \ -d "subject_token_type=urn:ietf:params:oauth:token-type:id_token" \ -d "user_profile={\"name\":{\"firstName\":\"John\",\"lastName\":\"Doe\"},\"email\":\"user@example.com\"}" # Expected Response { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "refresh_expires_in": 1800, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "not-before-policy": 0, "session_state": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "scope": "openid email profile" } ``` -------------------------------- ### POST /realms/{realm}/protocol/openid-connect/token (Token Exchange with Apple Authorization Code) Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Exchange an Apple authorization code for Keycloak tokens. This is useful when your native app receives an authorization code from Apple Sign-In. ```APIDOC ## POST /realms/{realm}/protocol/openid-connect/token (Token Exchange with Apple Authorization Code) ### Description Exchange an Apple authorization code for Keycloak tokens, useful when your native app receives an authorization code from Apple Sign-In. ### Method POST ### Endpoint `/realms/{realm}/protocol/openid-connect/token` ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of your application. - **grant_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:token-exchange`. - **subject_token** (string) - Required - The authorization code obtained from Apple Sign-In. - **subject_issuer** (string) - Required - Must be `apple`. - **subject_token_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:authorization_code`. - **code_verifier** (string) - Required - The PKCE code verifier. - **redirect_uri** (string) - Required - The redirect URI used during the authorization code grant. ### Request Example ```bash # Exchange Apple Authorization Code for Keycloak tokens curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-mobile-app" \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ -d "subject_token=AUTHORIZATION_CODE_FROM_APPLE" \ -d "subject_issuer=apple" \ -d "subject_token_type=urn:ietf:params:oauth:grant-type:authorization_code" \ -d "code_verifier=VERIFIER_FROM_PKCE" \ -d "redirect_uri=https://myapp.example.com/callback" ``` ### Response #### Success Response (200) - **access_token** (string) - The access token issued by Keycloak. - **expires_in** (integer) - The lifetime in seconds of the access token. - **refresh_expires_in** (integer) - The lifetime in seconds of the refresh token. - **refresh_token** (string) - The refresh token. - **token_type** (string) - The type of the token, typically "Bearer". - **not-before-policy** (integer) - The time before which the token is not valid. - **session_state** (string) - The session state. - **scope** (string) - The scopes granted. #### Response Example ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "refresh_expires_in": 1800, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "not-before-policy": 0, "session_state": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "scope": "openid email profile" } ``` ``` -------------------------------- ### POST /realms/{realm}/protocol/openid-connect/token (Token Exchange with Apple ID Token) Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt Exchange an Apple ID token for Keycloak tokens. This is ideal for native applications that obtain tokens directly from the Apple Sign-In SDK. ```APIDOC ## POST /realms/{realm}/protocol/openid-connect/token (Token Exchange with Apple ID Token) ### Description Exchange an Apple ID token for Keycloak tokens, ideal for native apps that obtain tokens directly from Apple Sign-In SDK. ### Method POST ### Endpoint `/realms/{realm}/protocol/openid-connect/token` ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of your application. - **grant_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:token-exchange`. - **subject_token** (string) - Required - The Apple ID token obtained from Apple Sign-In. - **subject_issuer** (string) - Required - Must be `apple`. - **subject_token_type** (string) - Required - Must be `urn:ietf:params:oauth:token-type:id_token`. - **user_profile** (object) - Optional - User profile information to be included in the Keycloak token. - **name** (object) - Optional - **firstName** (string) - Optional - **lastName** (string) - Optional - **email** (string) - Optional ### Request Example ```bash curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-mobile-app" \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ -d "subject_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmV4YW1wbGUuc2VydmljZSIsImV4cCI6MTcwMDAwMDAwMCwiaWF0IjoxNjk5OTk2NDAwLCJzdWIiOiIwMDAxMjMuYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZi4xMjM0IiwiZW1haWwiOiJ1c2VyQHByaXZhdGVyZWxheS5hcHBsZWlkLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSJ9.signature" \ -d "subject_issuer=apple" \ -d "subject_token_type=urn:ietf:params:oauth:token-type:id_token" \ -d "user_profile=\"{\"name\":{\"firstName\":\"John\",\"lastName\":\"Doe\"},\"email\":\"user@example.com\"}\"" ``` ### Response #### Success Response (200) - **access_token** (string) - The access token issued by Keycloak. - **expires_in** (integer) - The lifetime in seconds of the access token. - **refresh_expires_in** (integer) - The lifetime in seconds of the refresh token. - **refresh_token** (string) - The refresh token. - **token_type** (string) - The type of the token, typically "Bearer". - **not-before-policy** (integer) - The time before which the token is not valid. - **session_state** (string) - The session state. - **scope** (string) - The scopes granted. #### Response Example ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "refresh_expires_in": 1800, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "not-before-policy": 0, "session_state": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "scope": "openid email profile" } ``` ``` -------------------------------- ### POST /token - Exchange Apple authorization_code for Keycloak tokens Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This endpoint is used to exchange an Apple authorization code obtained during the authentication flow for Keycloak tokens. It's typically used for mobile applications. ```APIDOC ## POST /protocol/openid-connect/token ### Description Exchanges an Apple authorization code for Keycloak tokens, commonly used in mobile application flows. ### Method POST ### Endpoint https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of your application registered in Keycloak. - **grant_type** (string) - Required - Must be `urn:ietf:params:oauth:grant-type:token-exchange` for this flow. - **subject_token** (string) - Required - The authorization code or token received from Apple. - **subject_issuer** (string) - Required - Must be `apple`. - **app_identifier** (string) - Required - The bundle identifier of your iOS application. - **app_redirect_uri** (string) - Required - The redirect URI configured in Keycloak for the Apple provider. - **user_profile** (JSON string) - Optional - User profile information if available. ### Request Example ```json { "client_id": "my-mobile-app", "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": "c1a2b3c4d5e6f7890abcdef123456789.0.nrstu.vwxyz12345ABCDE67890", "subject_issuer": "apple", "app_identifier": "com.example.ios-app", "app_redirect_uri": "https://keycloak.example.com/realms/myrealm/broker/apple/endpoint", "user_profile": "{\"name\":{\"firstName\":\"Jane\",\"lastName\":\"Smith\"},\"email\":\"jane@example.com\"}" } ``` ### Response #### Success Response (200) - **access_token** (string) - The access token issued by Keycloak. - **expires_in** (integer) - The lifetime in seconds of the access token. - **refresh_expires_in** (integer) - The lifetime in seconds of the refresh token. - **refresh_token** (string) - The refresh token. - **token_type** (string) - The type of token, usually 'Bearer'. - **session_state** (string) - The session state. - **scope** (string) - The scopes granted. #### Response Example ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "refresh_expires_in": 1800, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "session_state": "f1e2d3c4-b5a6-9870-fedc-ba0987654321", "scope": "openid email profile" } ``` ``` -------------------------------- ### Generate Client Secret JWT for Apple Authentication (Ruby) Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This Ruby script generates a JSON Web Token (JWT) client secret required for authenticating with Apple's authentication services. It uses the 'jwt' gem and requires your Apple private key file, team ID, client ID, and key ID. The generated token is used in the `-d client_secret` parameter when calling Apple's token endpoint. ```ruby # client_secret.rb - Generate Apple client secret for testing require 'jwt' key_file = 'AuthKey_XYZ9876543.p8' team_id = 'ABCD123456' client_id = 'com.example.service' key_id = 'XYZ9876543' ecdsa_key = OpenSSL::PKey::EC.new IO.read key_file headers = { 'kid' => key_id } claims = { 'iss' => team_id, 'iat' => Time.now.to_i, 'exp' => Time.now.to_i + 86400*180, 'aud' => 'https://appleid.apple.com', 'sub' => client_id } token = JWT.encode claims, ecdsa_key, 'ES256', headers puts token # Output: eyJhbGciOiJFUzI1NiIsImtpZCI6IlhZWjk4NzY1NDMifQ.eyJpc3MiOiJBQkNEMTIzNDU2IiwiaWF0IjoxNjk5OTk2NDAwLCJleHAiOjE3MTU1NDg0MDAsImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJjb20uZXhhbXBsZS5zZXJ2aWNlIn0.signature ``` -------------------------------- ### Exchange Apple Authorization Code for Keycloak Tokens (Mobile App) Source: https://context7.com/klausbetz/apple-identity-provider-keycloak/llms.txt This snippet demonstrates how to exchange an Apple authorization code for Keycloak tokens using the token exchange grant type. It's typically used for mobile applications where direct user interaction with a browser is less common. Ensure the token-exchange feature is enabled in Keycloak. ```bash curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-mobile-app" \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ -d "subject_token=c1a2b3c4d5e6f7890abcdef123456789.0.nrstu.vwxyz12345ABCDE67890" \ -d "subject_issuer=apple" \ -d "app_identifier=com.example.ios-app" \ -d "app_redirect_uri=https://keycloak.example.com/realms/myrealm/broker/apple/endpoint" \ -d "user_profile=\"{\"name\":{\"firstName\":\"Jane\",\"lastName\":\"Smith\"},\"email\":\"jane@example.com\"}\"" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.