PingOne Platform APIs

Step 5: Create a certificate in the destination environment

   

POST {{apiPath}}/environments/{{destinationEnvID}}/certificates

Create a certificate in the destination environment using a POST {{apiPath}}/environments/{{destinationEnvID}}/certificates request. Copy and save the certificate ID. You’ll use it when creating the IdP.

  • The usageType value must be set to "SIGNING".

  • The file entry must reference the PEM or PKCS7 file containing the source environment key you downloaded in the initial step. Creating the certificate using the PEM or PKCS7 file transfers the key from the source environment to the destination environment.

If the certificate used by the IdP in the destination environment doesn’t match the key used by the source environment application, the authentication flow fails.

Headers

Authorization      Bearer {{accessToken}}

Content-Type      multipart/form-data; boundary=<calculated when request is sent>

Body

formdata

Key Type Value

usageType

text

SIGNING

file

file

None

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{apiPath}}/environments/{{destinationEnvID}}/certificates' \
--header 'Authorization: Bearer {{accessToken}}' \
--form 'usageType="SIGNING"' \
--form 'file=@"/path/to/file"'
var options = new RestClientOptions("{{apiPath}}/environments/{{destinationEnvID}}/certificates")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Authorization", "Bearer {{accessToken}}");
request.AlwaysMultipartFormData = true;
request.AddParameter("usageType", "SIGNING");
request.AddFile("file", "/path/to/file");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "bytes"
  "mime/multipart"
  "os"
  "path/filepath"
  "net/http"
  "io"
)

func main() {

  url := "{{apiPath}}/environments/{{destinationEnvID}}/certificates"
  method := "POST"

  payload := &bytes.Buffer{}
  writer := multipart.NewWriter(payload)
  _ = writer.WriteField("usageType", "SIGNING")
  file, errFile2 := os.Open("/path/to/file")
  defer file.Close()
  part2,
         errFile2 := writer.CreateFormFile("file",filepath.Base("/path/to/file"))
  _, errFile2 = io.Copy(part2, file)
  if errFile2 != nil {
    fmt.Println(errFile2)
    return
  }
  err := writer.Close()
  if err != nil {
    fmt.Println(err)
    return
  }


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

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Authorization", "Bearer {{accessToken}}")

  req.Header.Set("Content-Type", writer.FormDataContentType())
  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))
}
POST /environments/{{destinationEnvID}}/certificates HTTP/1.1
Host: {{apiPath}}
Authorization: Bearer {{accessToken}}
Content-Length: 289
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="usageType"

SIGNING
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="file"
Content-Type: <Content-Type header here>

(data)
------WebKitFormBoundary7MA4YWxkTrZu0gW--
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  .addFormDataPart("usageType","SIGNING")
  .addFormDataPart("file","file",
    RequestBody.create(MediaType.parse("application/octet-stream"),
    new File("/path/to/file")))
  .build();
Request request = new Request.Builder()
  .url("{{apiPath}}/environments/{{destinationEnvID}}/certificates")
  .method("POST", body)
  .addHeader("Authorization", "Bearer {{accessToken}}")
  .addHeader("Content-Length", "")
  .build();
Response response = client.newCall(request).execute();
var form = new FormData();
form.append("usageType", "SIGNING");
form.append("file", fileInput.files[0], "file");

var settings = {
  "url": "{{apiPath}}/environments/{{destinationEnvID}}/certificates",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Authorization": "Bearer {{accessToken}}",
    "Content-Length": ""
  },
  "processData": false,
  "mimeType": "multipart/form-data",
  "contentType": false,
  "data": form
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var fs = require('fs');
var options = {
  'method': 'POST',
  'url': '{{apiPath}}/environments/{{destinationEnvID}}/certificates',
  'headers': {
    'Authorization': 'Bearer {{accessToken}}',
    'Content-Length': ''
  },
  formData: {
    'usageType': 'SIGNING',
    'file': {
      'value': fs.createReadStream('/path/to/file'),
      'options': {
        'filename': 'file',
        'contentType': null
      }
    }
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests

url = "{{apiPath}}/environments/{{destinationEnvID}}/certificates"

payload = {'usageType': 'SIGNING'}
files=[
  ('file',('file',open('/path/to/file','rb'),'application/octet-stream'))
]
headers = {
  'Authorization': 'Bearer {{accessToken}}',
  'Content-Length': ''
}

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

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/environments/{{destinationEnvID}}/certificates');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Authorization' => 'Bearer {{accessToken}}',
  'Content-Length' => ''
));
$request->addPostParameter(array(
  'usageType' => 'SIGNING'
));
$request->addUpload('file', '/path/to/file', 'file', '<Content-Type Header>');
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();
}
require "uri"
require "net/http"

url = URI("{{apiPath}}/environments/{{destinationEnvID}}/certificates")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer {{accessToken}}"
request["Content-Length"] = ""
form_data = [['usageType', 'SIGNING'],['file', File.open('/path/to/file')]]
request.set_form form_data, 'multipart/form-data'
response = http.request(request)
puts response.read_body
let parameters = [
  [
    "key": "usageType",
    "value": "SIGNING",
    "type": "text"
  ],
  [
    "key": "file",
    "src": "/path/to/file",
    "type": "file"
  ]] as [[String: Any]]

let boundary = "Boundary-\(UUID().uuidString)"
var body = Data()
var error: Error? = nil
for param in parameters {
  if param["disabled"] != nil { continue }
  let paramName = param["key"]!
  body += Data("--\(boundary)\r\n".utf8)
  body += Data("Content-Disposition:form-data; name=\"\(paramName)\"".utf8)
  if param["contentType"] != nil {
    body += Data("\r\nContent-Type: \(param["contentType"] as! String)".utf8)
  }
  let paramType = param["type"] as! String
  if paramType == "text" {
    let paramValue = param["value"] as! String
    body += Data("\r\n\r\n\(paramValue)\r\n".utf8)
  } else {
    let paramSrc = param["src"] as! String
    let fileURL = URL(fileURLWithPath: paramSrc)
    if let fileContent = try? Data(contentsOf: fileURL) {
      body += Data("; filename=\"\(paramSrc)\"\r\n".utf8)
      body += Data("Content-Type: \"content-type header\"\r\n".utf8)
      body += Data("\r\n".utf8)
      body += fileContent
      body += Data("\r\n".utf8)
    }
  }
}
body += Data("--\(boundary)--\r\n".utf8);
let postData = body


var request = URLRequest(url: URL(string: "{{apiPath}}/environments/{{destinationEnvID}}/certificates")!,timeoutInterval: Double.infinity)
request.addValue("Bearer {{accessToken}}", forHTTPHeaderField: "Authorization")
request.addValue("", forHTTPHeaderField: "Content-Length")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

request.httpMethod = "POST"
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

202 Accepted

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/certificates"
        }
    },
    "id": "409e8711-7d1b-4035-afc6-561c2b86286b",
    "name": "kb doc test",
    "serialNumber": 1604411669268,
    "issuerDN": "CN=kb doc test,OU=,O=myOrg,L=,ST=,C=CA",
    "subjectDN": "CN=kb doc test,OU=,O=myOrg,L=,ST=,C=CA",
    "algorithm": "RSA",
    "keyLength": 2048,
    "createdAt": "2020-11-24T15:39:55.325Z",
    "expiresAt": "2021-11-03T13:54:29.000Z",
    "startsAt": "2020-11-03T13:54:29.000Z",
    "validityPeriod": 365,
    "signatureAlgorithm": "SHA256withRSA",
    "usageType": "SIGNING",
    "status": "VALID",
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    }
}