# Bring your own key Learn how to configure Bring Your Own Key (BYOK) authentication for your Zoom Marketplace applications. With BYOK, you can use your own cryptographic keys to enhance security and maintain greater control over your application's authentication process. ## Overview BYOK authentication gives developers control over their application's security by enabling them to manage their own encryption keys. This approach is especially valuable for applications with strict security compliance requirements or specific key management policies. **Prerequisites**: - A Zoom Developer account with permission to manage Marketplace app credentials. - A secure key management process (HSM/KMS or equivalent recommended). - A JWK/JWKS that follows [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517) format requirements. ## Generate your key pair Generate a secure RSA or ECDSA key pair for signing your authentication tokens. ### RSA key pair generation 1. Generate RSA private key (2048-bit minimum recommended) ```plainText openssl genrsa -out private_key.pem 2048 ``` 2. Extract public key from private key. ```plainText openssl rsa -in private_key.pem -pubout -out public_key.pem ``` ### ECDSA key pair generation ```plainText openssl ecparam -name prime256v1 -genkey -noout -out ec_private_key.pem openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem ``` ## Prepare JWK/JWKS When preparing JWK or JWKS, keep the following in mind: - Provide public key material only. - Do not include private key fields (for example d in RSA/EC JWKs). - Use a valid kid so key rotation works reliably. - If using JWKS URI, host a valid HTTPS endpoint returning parsable JWKS JSON. ## Register your public key with Zoom 1. Log into the [Zoom App Marketplace](https://marketplace.zoom.us) as an admin or an account with developer rights. 2. Select your application from the created app list or [create a new General App](/docs/build-flow/quick-start-guide/). 3. Go to the **App Credentials**, switch from **Client Secret** to **Public Key**. 4. Choose one method: - Paste JWK/JWKS directly. - Provide a well-known jwks_uri URL. 5. Save the configuration and note your Client ID. ## Build the client_assertion JWT For the signed JWT include: - `iss / sub`: set to `client_id`. - `aud`: must match the Zoom token endpoint audience; different endpoints require different audience values. - `exp`, `iat`, `jti`: required for token lifetime and replay protection (`jti` should be unique per assertion). --- ## Exchange for access token With your signed JWT token, make an authorization code grant request with `client_assertion`: `` and `client_assertion_type:urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. ### Authorization code grant with JWT bearer client assertion The authorization code grant flow lets your app access Zoom resources on behalf of a user. With BYOK, use a JWT bearer token as the client assertion instead of a client secret. For details about the OAuth flow, see [User authorization](/docs/integrations/oauth/). ### Redirect user for authorization First, redirect the user to Zoom's authorization endpoint to obtain an authorization code: ```plainText GET https://zoom.us/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI ``` ### Exchange authorization code for access token After the user authorizes your app, Zoom redirects to your redirect URI with an authorization code. Exchange the code for an access token by using your JWT bearer assertion. **Example Request** ```plainText POST /oauth/token HTTP/1.1 Host: zoom.us Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=YOUR_JWT_ASSERTION&client_id=CLIENT_ID ``` **Request Parameters** | Parameter | Required | Description | | ----------------------- | -------- | ---------------------------------------------------------------- | | `grant_type` | Yes | Must be `authorization_code` | | `code` | Yes | The authorization code received from the OAuth callback | | `redirect_uri` | Yes | Must match the redirect URI used in the authorization request | | `client_assertion_type` | Yes | Must be `urn:ietf:params:oauth:client-assertion-type:jwt-bearer` | | `client_assertion` | Yes | Your signed JWT bearer token | | `client_id` | Yes | Client ID in app credentials | **Token Response** A successful response returns the following JSON: ```PlainText { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "bearer", "refresh_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9...", "expires_in": 3600, "scope": "user:read:admin meeting:write:admin" } ``` **Response Fields** | Field | Description | | --------------- | -------------------------------------------------------------------- | | `access_token` | The access token to use for API requests | | `token_type` | Always `bearer` | | `refresh_token` | Token used to obtain a new access token when the current one expires | | `expires_in` | Number of seconds until the access token expires (typically `3600`) | | `scope` | Space-separated list of scopes granted to the access token | ## Make Authenticated API Requests Use the access token in your API requests to authenticate with Zoom services. ## Rotating between keys You can rotate keys by providing a key set and adding new keys to it or removing old keys from it. Zoom validates the JWT against each key in the key set.