PingOne Platform APIs

Step 9: Submit SAML sign-on request

POST {{authPath}}/{{envID}}/saml20/idp/sso

The POST /{{envID}}/saml20/idp/sso operation starts the sign-on flow. The request requires the application/x-www-form-urlencoded custom content type in the Content-Type HTTP header to initate the set password operation.

The request body includes the SAMLRequest parameter to pass in the encoded SAML authentication request information. Here is a sample SAML <AuthnRequest> in plain text:

<samlp:AuthnRequest
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    ID="identifier_1"
    Version="2.0"
    IssueInstant="2004-12-05T09:21:59">
    <saml:Issuer>https://sp.example.com/SAML2</saml:Issuer>
  </samlp:AuthnRequest>

If you use the Postman collection, this request includes a Postman pre-req script that creates and encodes the AuthnRequest and writes it to the Postman environment as the value for the SAMLRequest variable.

The request body includes the RelayState property that specifies the token for SAML assertions used in IdP-initiated SSO.

The response contains the Location header. This includes the flowId value that you’ll need for the next step.

Headers

Content-Type      application/x-www-form-urlencoded

Body

urlencoded ( application/x-www-form-urlencoded )

Key Value

SAMLRequest

{{SAMLRequest}}

RelayState

token

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{authPath}}/{{envID}}/saml20/idp/sso' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'SAMLRequest={{SAMLRequest}}' \
--data-urlencode 'RelayState=token'
var options = new RestClientOptions("{{authPath}}/{{envID}}/saml20/idp/sso")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("SAMLRequest", "{{SAMLRequest}}");
request.AddParameter("RelayState", "token");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

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

func main() {

  url := "{{authPath}}/{{envID}}/saml20/idp/sso"
  method := "POST"

  payload := strings.NewReader("SAMLRequest=%7B%7BSAMLRequest%7D%7D&RelayState=token")

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

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

  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 /{{envID}}/saml20/idp/sso HTTP/1.1
Host: {{authPath}}
Content-Type: application/x-www-form-urlencoded

SAMLRequest=%7B%7BSAMLRequest%7D%7D&RelayState=token
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "SAMLRequest={{SAMLRequest}}&RelayState=token");
Request request = new Request.Builder()
  .url("{{authPath}}/{{envID}}/saml20/idp/sso")
  .method("POST", body)
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{authPath}}/{{envID}}/saml20/idp/sso",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "data": {
    "SAMLRequest": "{{SAMLRequest}}",
    "RelayState": "token"
  }
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'POST',
  'url': '{{authPath}}/{{envID}}/saml20/idp/sso',
  'headers': {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    'SAMLRequest': '{{SAMLRequest}}',
    'RelayState': 'token'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests

url = "{{authPath}}/{{envID}}/saml20/idp/sso"

payload = 'SAMLRequest=%7B%7BSAMLRequest%7D%7D&RelayState=token'
headers = {
  'Content-Type': 'application/x-www-form-urlencoded'
}

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

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{authPath}}/{{envID}}/saml20/idp/sso');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/x-www-form-urlencoded'
));
$request->addPostParameter(array(
  'SAMLRequest' => '{{SAMLRequest}}',
  'RelayState' => 'token'
));
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("{{authPath}}/{{envID}}/saml20/idp/sso")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request.body = "SAMLRequest=%7B%7BSAMLRequest%7D%7D&RelayState=token"

response = http.request(request)
puts response.read_body
let parameters = "SAMLRequest=%7B%7BSAMLRequest%7D%7D&RelayState=token"
let postData =  parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{authPath}}/{{envID}}/saml20/idp/sso")!,timeoutInterval: Double.infinity)
request.addValue("application/x-www-form-urlencoded", 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

302 Found