---
title: Update app with PRIVATE_KEY_JWT
component: pingone-api
page_id: pingone-api:workflow-library:platform-sso-and-authorization/openid-connect-oidc/client-authentication-methods/environment-configuration/private-key-jwt/step-1-create-a-web-application
canonical_url: https://developer.pingidentity.com/pingone-api/workflow-library/platform-sso-and-authorization/openid-connect-oidc/client-authentication-methods/environment-configuration/private-key-jwt/step-1-create-a-web-application.html
section_ids:
  headers: Headers
  body: Body
  example-request: Example Request
  example-response: Example Response
---

# Update app with PRIVATE\_KEY\_JWT

##

 

```none
PUT {{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}
```

Updates an application to use `PRIVATE_KEY_JWT` authentication. This is the most secure method, using asymmetric cryptography. The client signs the JWT with its private key, and PingOne verifies it with the public key. No shared secrets are transmitted.

**Key points**

* JWT signed with RS256/RS384/RS512 or ES256/ES384/ES512

* Public key registered with PingOne (JWKS or certificate)

* No shared secret - highest security

* Ideal for enterprise applications with PKI infrastructure

The response returns information about the application, including its `id` property, which identifies the ID for this application resource and the updated value for the `tokenEndpointAuthMethod`.

|   |                                                                                                     |
| - | --------------------------------------------------------------------------------------------------- |
|   | **Important:** For `PRIVATE_KEY_JWT` to work, you must upload a public key or configure a JWKS URL. |

**Options**

* Upload Public Key Certificate: Use \`POST /environments/envID/applications/appID/keys with a PEM certificate.

* Configure JWKS URL: Update the application with `tokenEndpointAuthSigningAlg` and public key details.

**Steps to Configure**

1. Generate an RSA or EC key pair (for example, using OpenSSL).

2. Extract the public key.

3. Upload the public key to PingOne.

4. Sign JWTs with your private key.

### Headers

Authorization      Bearer {{accessToken}}

Content-Type      application/json

### Body

raw ( application/json )

```json
{
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
        "http://localhost:3000/callback"
    ],
    "responseTypes": [
        "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
}
```

##

### Example Request

* cURL

* C#

* Go

* HTTP

* Java

* jQuery

* NodeJS

* Python

* PHP

* Ruby

* Swift

```shell
curl --location --globoff --request PUT '{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
        "http://localhost:3000/callback"
    ],
    "responseTypes": [
        "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
}'
```

```csharp
var options = new RestClientOptions("{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Put);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer {{accessToken}}");
var body = @"{" + "\n" +
@"    ""enabled"": true," + "\n" +
@"    ""name"": ""Shared-Web-App""," + "\n" +
@"    ""description"": ""Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.""," + "\n" +
@"    ""type"": ""WEB_APP""," + "\n" +
@"    ""protocol"": ""OPENID_CONNECT""," + "\n" +
@"    ""grantTypes"": [" + "\n" +
@"        ""AUTHORIZATION_CODE""" + "\n" +
@"    ]," + "\n" +
@"    ""redirectUris"": [" + "\n" +
@"        ""http://localhost:3000/callback""" + "\n" +
@"    ]," + "\n" +
@"    ""responseTypes"": [" + "\n" +
@"        ""CODE""" + "\n" +
@"    ]," + "\n" +
@"    ""tokenEndpointAuthMethod"": ""PRIVATE_KEY_JWT""," + "\n" +
@"    ""jwks"": ""{{jwksString}}""" + "\n" +
@"}";
request.AddStringBody(body, DataFormat.Json);
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
```

```golang
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io"
)

func main() {

  url := "{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}"
  method := "PUT"

  payload := strings.NewReader(`{
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
        "http://localhost:3000/callback"
    ],
    "responseTypes": [
        "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
}`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Authorization", "Bearer {{accessToken}}")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := io.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
```

```http
PUT /v1/environments/{{envID}}/applications/{{sharedWebAppID}} HTTP/1.1
Host: {{apiPath}}
Content-Type: application/json
Authorization: Bearer {{accessToken}}

{
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
        "http://localhost:3000/callback"
    ],
    "responseTypes": [
        "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
}
```

```java
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"enabled\": true,\n    \"name\": \"Shared-Web-App\",\n    \"description\": \"Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.\",\n    \"type\": \"WEB_APP\",\n    \"protocol\": \"OPENID_CONNECT\",\n    \"grantTypes\": [\n        \"AUTHORIZATION_CODE\"\n    ],\n    \"redirectUris\": [\n        \"http://localhost:3000/callback\"\n    ],\n    \"responseTypes\": [\n        \"CODE\"\n    ],\n    \"tokenEndpointAuthMethod\": \"PRIVATE_KEY_JWT\",\n    \"jwks\": \"{{jwksString}}\"\n}");
Request request = new Request.Builder()
  .url("{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}")
  .method("PUT", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Authorization", "Bearer {{accessToken}}")
  .build();
Response response = client.newCall(request).execute();
```

```javascript
var settings = {
  "url": "{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}",
  "method": "PUT",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer {{accessToken}}"
  },
  "data": JSON.stringify({
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
      "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
      "http://localhost:3000/callback"
    ],
    "responseTypes": [
      "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
  }),
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
```

```javascript
var request = require('request');
var options = {
  'method': 'PUT',
  'url': '{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}',
  'headers': {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer {{accessToken}}'
  },
  body: JSON.stringify({
    "enabled": true,
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
      "AUTHORIZATION_CODE"
    ],
    "redirectUris": [
      "http://localhost:3000/callback"
    ],
    "responseTypes": [
      "CODE"
    ],
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "jwks": "{{jwksString}}"
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
```

```python
import requests
import json

url = "{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}"

payload = json.dumps({
  "enabled": True,
  "name": "Shared-Web-App",
  "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
  "type": "WEB_APP",
  "protocol": "OPENID_CONNECT",
  "grantTypes": [
    "AUTHORIZATION_CODE"
  ],
  "redirectUris": [
    "http://localhost:3000/callback"
  ],
  "responseTypes": [
    "CODE"
  ],
  "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
  "jwks": "{{jwksString}}"
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{accessToken}}'
}

response = requests.request("PUT", url, headers=headers, data=payload)

print(response.text)
```

```php
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}');
$request->setMethod(HTTP_Request2::METHOD_PUT);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Authorization' => 'Bearer {{accessToken}}'
));
$request->setBody('{\n    "enabled": true,\n    "name": "Shared-Web-App",\n    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",\n    "type": "WEB_APP",\n    "protocol": "OPENID_CONNECT",\n    "grantTypes": [\n        "AUTHORIZATION_CODE"\n    ],\n    "redirectUris": [\n        "http://localhost:3000/callback"\n    ],\n    "responseTypes": [\n        "CODE"\n    ],\n    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",\n    "jwks": "{{jwksString}}"\n}');
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
```

```ruby
require "uri"
require "json"
require "net/http"

url = URI("{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Put.new(url)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer {{accessToken}}"
request.body = JSON.dump({
  "enabled": true,
  "name": "Shared-Web-App",
  "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
  "type": "WEB_APP",
  "protocol": "OPENID_CONNECT",
  "grantTypes": [
    "AUTHORIZATION_CODE"
  ],
  "redirectUris": [
    "http://localhost:3000/callback"
  ],
  "responseTypes": [
    "CODE"
  ],
  "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
  "jwks": "{{jwksString}}"
})

response = http.request(request)
puts response.read_body
```

```swift
let parameters = "{\n    \"enabled\": true,\n    \"name\": \"Shared-Web-App\",\n    \"description\": \"Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.\",\n    \"type\": \"WEB_APP\",\n    \"protocol\": \"OPENID_CONNECT\",\n    \"grantTypes\": [\n        \"AUTHORIZATION_CODE\"\n    ],\n    \"redirectUris\": [\n        \"http://localhost:3000/callback\"\n    ],\n    \"responseTypes\": [\n        \"CODE\"\n    ],\n    \"tokenEndpointAuthMethod\": \"PRIVATE_KEY_JWT\",\n    \"jwks\": \"{{jwksString}}\"\n}"
let postData = parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{apiPath}}/v1/environments/{{envID}}/applications/{{sharedWebAppID}}")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer {{accessToken}}", forHTTPHeaderField: "Authorization")

request.httpMethod = "PUT"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in
  guard let data = data else {
    print(String(describing: error))
    return
  }
  print(String(data: data, encoding: .utf8)!)
}

task.resume()
```

### Example Response

200 OK

```json
{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7029adfa-164d-4234-a3ca-3e4900ef94a6"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
        },
        "metadata": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7029adfa-164d-4234-a3ca-3e4900ef94a6/metadata"
        },
        "attributes": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7029adfa-164d-4234-a3ca-3e4900ef94a6/attributes"
        },
        "secret": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7029adfa-164d-4234-a3ca-3e4900ef94a6/secret"
        },
        "grants": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/7029adfa-164d-4234-a3ca-3e4900ef94a6/grants"
        }
    },
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    },
    "id": "7029adfa-164d-4234-a3ca-3e4900ef94a6",
    "name": "Shared-Web-App",
    "description": "Application using PRIVATE_KEY_JWT - a JWT signed with a private key for the highest level of security. No shared secrets - asymmetric cryptography.",
    "enabled": true,
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "createdAt": "2026-04-08T15:39:17.367Z",
    "updatedAt": "2026-04-20T16:29:03.919Z",
    "clientId": "7029adfa-164d-4234-a3ca-3e4900ef94a6",
    "assignActorRoles": false,
    "responseTypes": [
        "CODE"
    ],
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "jwks": "{ \"keys\": [ { \"kty\": \"RSA\", \"e\": \"AQAB\", \"use\": \"sig\", \"kid\": \"q3sWApYjHZQLmWMUdAIqZiVWSshDdau5eI4K_Bm65Us\", \"alg\": \"RS256\", \"n\": \"jWA_vDxg41NrYJdIiv3BcljMy7V15bMyOyK5aJov6F\" } ]}",
    "tokenEndpointAuthMethod": "PRIVATE_KEY_JWT",
    "pkceEnforcement": "OPTIONAL",
    "requestScopesForMultipleResourcesEnabled": false,
    "parRequirement": "OPTIONAL",
    "devicePollingInterval": 5,
    "redirectUris": [
        "http://localhost:3000/callback"
    ],
    "parTimeout": 60,
    "deviceTimeout": 600
}
```
