Web Services

NYC.ID includes a Web services interface that your application must use to supplement SAML 2.0 authentication via the NYC.ID IdP
The Web services are split into several categories. Click a category link below to learn more about each:

The Web services share several important similarities. They:

To configure authentication, your application requires:

  • a username and password, called a service account, and
  • a signature, calculated for each request.

 

Versioning

To invoke the non-default version of a Web service (i.e., Authenticate v2), include application/vnd.nyc.vx in the HTTP "Accept" header, where x is the version number of the API (e.g., 2).

 

Provisioning a Service Account

Your application requires a username and password to securely communicate with the NYC.ID Web services. This combination of username and password is called a NYC.ID Service Account. You may create a NYC.ID Service Account via the NYC.ID Console.

 

Authenticating Requests

When accessing NYC.ID Web services, your application's request must contain the following parameters so it can be authenticated:

Parameter Name Description
userName NYC.ID Service Account username
signature Each request must contain a valid request signature, or the request will be rejected. A request signature is calculated using your NYC.ID Service Account password, which is a shared secret known only to you and NYC.ID.

Optionally, it may also include the following parameter to prevent against replay attacks:

Parameter Name Description
dateTime The current date and time formatted as a Java SimpleDateFormat pattern (MM/dd/yyyy HH:mm or M/d/yy HH:mm).

Here are the steps for authenticating requests to NYC.ID Web Services...

Your application:

  1. constructs a request to NYC.ID Web Services.
  2. calculates the authentication signature using its NYC.ID Service Account password.
  3. appends the signature to the request.
  4. sends the request to NYC.ID.

NYC.ID:

  1. looks up your application's password using the username in the request.
  2. calculates a signature from the request data and password using the same algorithm that your application used to calculate the signature.
  3. considers the request authentic if the signature generated by NYC.ID matches the one sent in your application's request and the dateTime, if sent, is within 15 minutes of the current date and time.
  4. returns an "unauthorized error" response if the signature doesn't match or the dateTime is greater than 15 minutes of the current dateTime.

Calculating the Authentication Signature

The NYC.ID Web Services use a custom HTTP scheme based on a keyed Hash Message Authentication Code (HMAC)—HMAC-SHA256—for authentication. To create the authentication signature, your application should:

  1. Concatenate the Web Service HTTP method, relative URL, and parameter values of the request to form a string (StringToSign), following these steps:
    1. Start with an empty string ("").
    2. Append the HTTP method.
    3. Append the path part of the HTTP Request-URI, up to but not including the query string.
    4. Sort the parameters (e.g., "dateTime", "guid", "userName", "userType") alphabetically by parameter name, then value. Append only the parameter value(s). When creating the signature, your application should not encode these values; however, it must URL encode them in the request.
    5. Append the value of the Authorization header

    Here are some examples of creating a StringToSign from a sample request:

    Example One:

    Request:
    GET 
    /account/api/isEmailValidated.htm?guid=ABCD1234&userName=xxx
    StringToSign :
    GET/account/api/isEmailValidated.htmABC1234xxx

    Example Two:

    Request:
    GET 
    /account/api/getUsers.htm?guids=WXYZ5678&guids=ABCD1234&userName=xxx
    StringToSign :
    GET/account/api/getUsers.htmABCD1234WXYZ5678xxx

  2. Use your NYC.ID Web services password to calculate the HMAC of that string. Informally, we call this process "signing the request." The algorithm takes as input, two strings—a key and a message.

    Algorithm Input Parameters Description
    key NYC.ID Service Account password
    message UTF-8 encoding of the StringToSign

    The algorithm returns as output, a string—the signature. We call the output of the HMAC algorithm the signature, because it simulates the security properties of a real signature.

    Algorithm Output Description
    signature The output is a base64 encoding of HMAC-SHA256 byte-string.

    The following pseudo-code illustrates the algorithm to create the signature:

    signature  = Base64(HMAC-SHA256(password, UTF-8-Encoding-Of(StringToSign)));

 

Sample Requests

The example NYC.ID service account username and password below will be used to generate a signature for each sample request.

userName xxx
password #ktccn/[i(a=j)Pdo&4{S):9=]>6Ewm.s/}}.XX-=<kK'$F][M16TR?AJ3z*g|i^

The signature has been calculated using the example username and password (above) and appended to the example requests:

GET https://www1.nyc.gov/account/api/isEmailValidated.htm?guid=ABCD1234&userName=xxx&signature=9b249ba5013256b8f46dc9a1b678699d862a1efc2a1a8bcc3c97ad4c3edac3a2
GET https://www1.nyc.gov/account/api/getUsers.htm?guids=ABCD1234&userName=xxx&signature=d11be34aee0ad4eb900a7ef5f566531125f42ec53f1bec5131bc484811790df1

 

Signature Algorithm – Java  

private static final String ALGORITHM = "HmacSHA256";
public static String getSignature(String value, String key) {
try {
// Get an hmac_sha256 key from the raw key bytes
byte[] keyBytes = key.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, ALGORITHM);

// Get an hmac_sha256 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(signingKey);
// Compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(value.getBytes()); // Convert raw bytes to Hex
byte[] hexBytes = new Hex().encode(rawHmac); // Covert array of Hex bytes to a String
return new String(hexBytes, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}

 

Signature Algorithm – C#

private static string GenerateSignature(string value, string key) {
    try {
        var enc = Encoding.UTF8;
        HMACSHA256 hmac = new HMACSHA256(enc.GetBytes(key));
        hmac.Initialize();

        byte[] buffer = enc.GetBytes(value);
        return BitConverter.ToString(hmac.ComputeHash(buffer)).Replace("-", "").ToLower();
    } catch (Exception ex) {
        throw new Exception(ex.Message);
    }
}