App Security

The default authentication for SOA Software Open is a custom authentication mechanism, Shared Secret authentication.

It's important to set up authentication for the messages your app sends to an API you’re using. Authentication protects the sender, the receiver, and the message itself. It’s important that the security is strong enough that a third party couldn’t pose as the sender, pose as the receiver, and/or view or change the message content.

Authentication and security are particularly important when money and sensitive personally identifiable information are involved.

Once your app is registered, it's important to set up authentication so that the app can use the API to process messages securely.

In SOA Software Open, as part of setting up your app, you’ll need to choose the security mechanism you’ll use for authentication of your messages. There are two choices:

What do you want to read about?

Note: This topic provides information about setting up authentication for any API hosted in SOA Software Open. For implementation information and examples for a specific API you're using, refer to the documentation for that API.


Which Security Mechanism Should I Choose?

Both approaches are very secure. Both use a secret key combined with hashing and encoding, and both are sent via HTTPS.

The Shared Secret approach, which is the default, is easier to implement since you don't have to generate public and private keys.

The PKI approach is a little more secure, although both approaches are very secure. The PKI approach is more complex to implement.

Back to top


Authenticating with the Shared Secret

When you register your app, the AppID and Shared Secret are automatically generated. The Shared Secret is a binary hashed value, generated within the secure environment of SOA Software Open and known only to you and to SOA Software Open. In the Security Credentials section of the App Details screen you'll see that the Shared Secret option is the default security mechanism.

The Shared Secret approach follows the WS-Security digest authentication mechanism.

The Shared Secret, generated by SOA Software Open, is a 40-character alphanumeric value that acts as the key. An example is shown below.

1008877afabf32efb31f9c974dbeaa688bed0769

You combine the Shared Secret with two other values, hash the result using the SHA-1 secure hashing algorithm, and then encode the hashed value using the Base64 encoding scheme. You can also URL-encode the result, but this isn't required.

The result is sent in the HTTP Authorization message header as the value for the atmosphere_secret_digest parameter.

The API verifies each incoming request using the Shared Secret.

If you choose the Shared Secret security mechanism, your HTTP Authorization header must include the values shown below.

Name Data Type Description
atmosphere_app_id String The AppID assigned to the app in the platform.
atmosphere_nonce String A random string, uniquely generated for each request. For more information, see Generating a Nonce Value.
atmosphere_secret_digest String A value produced by concatenating the nonce, the timestamp, and the Shared Secret, hashing the combined value using SHA-1, and then Base-64 encoding the result. You can also URL-encode the result but this isn't required.
atmosphere_signature_method String A value indicating the signature method. For the Shared Secret approach, the valid value is Digest.
atmosphere_timestamp String The timestamp of the request, expressed as the number of milliseconds since January 1, 1970 00:00:00 GMT. The timestamp must be a positive integer and must be greater than or equal to the timestamp used in previous requests.
atmosphere_version String The SOA Software Open version. Optional. If present, the valid value must be 1.0.

More information about the shared secret approach is given in these sections:

Authenticating with the Shared Secret: Process Flow

The process flow diagram below shows an overview of API request authentication with the shared secret security mechanism.

Process flow: shared secret security mechanism

Sample Header With Authorization Parameters (Shared Secret Approach)

Below is an example of an Authorization header with app authentication parameters, when you use the shared secret approach. The sequence of the parameters isn't significant, but all parameters must be present with valid values.

Note: The value for the realm is determined by the www-Authenticate header. Make sure the value you set in the Authorization: SOA Software Open header matches the value received for the attribute from the server.

Authorization: Atmosphere realm="http://atmosphere",
  atmosphere_app_id="development-AS0iTmhoGaE6Y9sWhUkvcL6T",
  atmosphere_nonce="1326409129918",
  atmosphere_secret_digest="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
  atmosphere_digest_method="SHA1",
  atmosphere_timestamp="1326755565940",
  atmosphere_version="1.0"

Generating a Nonce Value

A nonce is a random string that is uniquely generated for each request. The nonce allows the API providers to verify that a request has never been made before. A nonce is sent in the message header for both Shared Secret and PKI security mechanisms. In the Shared Secret mechanism, the same nonce value sent in the message header is also used in creating the Secret Digest.

The way you create the nonce will depend on your development environment. Most programming languages include a method for creating a nonce. Below is an example of generating a nonce value in Java:

Import java.security.SecureRandom:
Random rand =  SecureRandom.getInstance ("SHA1PRNG");
long nonce = rand.nextLong();

Generating the Timestamp

The timestamp of the request is sent in the message header, for both Shared Secret and PKI security mechanisms. In the Shared Secret mechanism it is also used in creating the Secret Digest.

The timestamp must be in Unix epoch time, expressed as the number of milliseconds since January 1, 1970 00:00:00 GMT. The timestamp must be a positive integer and must be greater than or equal to the timestamp used in previous requests. In most implementations, the timestamp is taken from the host server. It's important that the timestamp in the message is accurate; if the timestamp is off, the message might be rejected.

For more information on Unix epoch time, and examples of implementation of the timestamp in different programming languages, see http://www.epochconverter.com (scroll down).

Hashing With the SHA-1 Secure Hash Algorithm

SHA-1 is a cryptographic hash function, broadly used and trusted.

When you hash a value with SHA-1, the hash function returns a 160-bit string. This is the message digest. The value is hashed and sent with the message; at the receipt point, the value is hashed again, and the two hash values are compared. When the two hash values match, it is a secure, reliable indication that the message hasn't changed; the message at the receipt point is an accurate duplication of the message at the send point.

If you're using the Shared Secret security mechanism, you concatenate the nonce, the timestamp, and the Shared Secret, and then you hash that combined value using SHA-1. You then encode the result, and send it in the message header as the value for the atmosphere_secret_digest parameter.

The formula for computing the hash is:

atmosphere_secret_digest = Base64 ( SHA-1 ( nonce + created + AppSecret ) ) 

Below is an example of a hashed base string:

1326409129918+1326755565940+2d9d42b42a4e2abc1fa5489d5081e03b95818ffd 

Encoding the base string into bytes

When you concatenate the nonce, timestamp, and app secret into a base string to be hashed, you'll need to make sure the concatenated value is a byte value before hashing. The hashing algorithm requires the input parameter to be in bytes. Depending on your app, you might need to use encoding to get a byte value. If so, use UTF-8 encoding.

Below is an example using Java.

MessageDigest md = MessageDigest.getInstance("SHA1"); 
md.update(baseString.getBytes("UTF-8")); or
md.update(baseString.getBytes()); 
String digest = encodeAsBase64String(md.digest()); 

Note: The example above is part of a larger Java sample for a specific API. For more information, refer to the implementation examples for the API you're using.

Encoding with the Base64 Encoding Scheme

The Base64 encoding scheme converts binary data into an ASCII string.

If you're using the Shared Secret security mechanism, you must encode the binary hash value that you created using the SHA-1 secure hash algorithm. Encoding turns it into ASCII string format. It's common practice to encode data to make sure it remains intact without modification during transport by HTTP or HTTPS.

Once the hash is encoded, the next step is to send the encoded value in the message header as the value for the atmosphere_secret_digest parameter.

Troubleshooting (Shared Secret Approach)

If there's a problem with your HTTPS header, you might see one of the error messages shown below.

Code Description
1010701 Required HTTP header parameter missing. [{0}]
1010702 One or more invalid HTTP header parameters.
1010703 Invalid Nonce. The value of the atmosphere_nonce field has already been used.
1010704 Invalid timestamp. The value of the atmosphere_timestamp field is out of range.
1010705 Signature or digest algorithm is not supported. [{0}]
1010706 Signature or digest verification failed.
1010707 Missing nonce. The atmosphere_nonce field value is required.
1010708 Unable to verify signature. There is no public key associated with the app.
1010709 Authentication scheme is invalid or missing.
1010710 Invalid AppID. The value [{0}] in the atmosphere_app_id field is invalid or missing.
1010711 Unable to verify signature. There is no shared secret associated with the app.
1010712 Invalid timestamp. Timestamp must be Unix epoch time in milliseconds.

What If the Shared Secret Is Compromised?

If for any reason you know or suspect that your app's Shared Secret might have been compromised, you must generate a new Shared Secret to replace the old one. You can generate a new Shared Secret in the Community Platform

To generate a new Shared Secret
  1. Navigate to App Details > Security Credentials.
  2. Click Regenerate Key.
  3. Copy the new key and use it in your app in place of the old one.

Note: It might take up to five minutes for the new key to take effect. During that time, messages sent using the new key will fail. It's best to wait for five minutes before sending messages with the new key.

Java Example: Creating a Shared Secret Hash

Below is an example of how to create the atmosphere_secret_digest value in Java.

  //Use the shared secret of app on file
String sharedSecret = "1008877afabf32efb31f9c974dbeaa688bed0769";

  //Generate the nonce value
Import java.security.SecureRandom:
Random rand =  SecureRandom.getInstance ("SHA1PRNG");
long nonce = rand.nextLong();

  //Get the timestamp in milliseconds
long timestamp = System.currentTimeMillis();
  
  // Concatenate the nonce, timestamp, and Shared Secret
String baseString = String.valueOf(nonce) + String.valueOf(timestamp) + sharedSecret;

  // Hash the concatenated value into a message digest using SHA-1
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(baseString.getBytes());

// Encode the message digest using Base-64 encoding
String digest = encodeAsBase64String(md.digest());

Back to top


Authenticating with PKI

When you register your app in SOA Software Open, in the Security Credentials section of your App Details you'll see that the Shared Secret option is the default.

If you want to use Public Key Infrastructure (PKI) for secure message signing, click the button to choose Public Key Integration. You'll need to get a public/private key pair and upload the public key to SOA Software Open, as explained later in this document. In the custom app code you will sign the API requests using the private key. The API verifies each incoming request using the public key.

More information about authenticating with PKI is given in these sections:

Authenticating with PKI: Process Flow

The process flow diagram below shows an overview of API request authentication with PKI.

Process flow: PKI security mechanism

Generating a Public/Private Key Pair with OpenSSL

You can use the OpenSSL open source product to produce a public/private key pair. For more information on OpenSSL, refer to www.openssl.org.

If you are developing the application using the Microsoft Windows OS you can get an adaptation of OpenSSL for the Windows platform from the following location: http://code.google.com/p/openssl-for-windows/downloads/list.

To create a public/private key pair with OpenSSL
  1. From the URL given above, download the applicable openssl archive file for your operating system.
  2. Unzip the contents to a folder; for example, C:\openssl.
  3. Launch the command-line utility cmd.exe.
  4. Change location to the folder referenced in step 2; for example, cd c:\openssl.
  5. Cut and paste or type the following at the command prompt:
    C:\openssl>bin\openssl req -config openssl.cnf -out csr.csr -new -newkey rsa:2048 -keyout privatekey.key
  6. Enter data for the prompts that appear.

    Note: Anything with an empty bracket set [] is not required.

Below is an example of what you might see in the command-line window.

Generating the CSR file

This process creates your public/private key pair in the c:\openssl folder. The key pair includes the files shown below.

File name Key type Comments
privatekey.key private key

Make sure you save a copy of the private key in a safe place. If you lose this key you will need to generate a new key pair.

You will sign your request using the private key. For more information, see Composing the Signature.

csr.csr public key Upload this file to the SOA Software Open portal. The API uses this file to verify the signature of your requests.

Important: Upload the file csr.csr to the SOA Software Open portal.

Java Developers: Generating a Keystore and CSR with the JDK Keytool

If you are a Java developer and have worked with cryptography in Java, you might be familiar with the concept of a keystore. A keystore is a file used to store and deploy certificates and private keys in a single package. You can create a keystore using OpenSSL as explained above. However, as a Java developer, it is probably far more convenient to use keytool, a key and certificate management utility that's distributed as part of the Java Development Kit (JDK).

You can use keytool to create both the keystore and the CSR associated with the private key in the keystore. Once you've created your CSR, you upload it to SOA Software Open just like any other CSR. Your Java code reads your private key, used for signing the base string used in API request headers, from the keystore file you create.

Since the keytool utility is part of the JDK, you don't have to download anything to create your Java keystore. Just follow the steps below.

Note: The procedure below assumes that your JDK bin directory is in your Windows system path.

To create a Java keystore using the keytool utility
  1. Open a command prompt.
  2. Create the keystore file by typing the following:

    keytool -genkey -alias <keystorealias> -keyalg RSA -keystore <keystore_filename>.p12 -storetype PKCS12 -keypass <password> -keysize 2048

  3. Create the CSR associated with the keystore created in step 2 by typing the following:

    keytool -certreq -alias <keystorealias> -keystore <keystore_filename>.p12 -file <csr_filename>.csr -storetype PKCS12

The illustration below shows the steps to create a keystore called keystore.p12 with an alias of mykeystore and the password changeme.

Creating a keystore with the Java keytool utility

The illustration below shows how to create a CSR called csr.csr from keystore.p12.

Creating a CSR with the Java keytool utility

Note: For implementation examples, check the authentication documentation for the specific API you're using.

IMPORTANT : Upload the file CSR.csr to the SOA Software Open portal.

Signing REST-Based Web Service Requests (PKI)

The signature process follows a similar approach to the OAuth 1.0 standard. The platform uses an HTTP Extension header to support its app authentication scheme. This Extension header is named Atmosphere (not case-sensitive). It uses the standard HTTP Authorization header and WWW-Authenticate response header to pass app-related authentication parameters. The HTTP query string can also be used to pass authentication data for cases where the app cannot directly manipulate HTTP headers.

WWW-Authenticate header

API providers can indicate their support for the extension by returning the SOA Software Open HTTP WWW-Authenticate header in response to app requests for protected resources. Below is an example:

WWW-Authenticate: Atmosphere realm="http://atmosphere

Authorization header

Apps should send their credentials in the HTTP Authorization header. If you choose the Public Key Integration approach for your app security, your HTTP Authorization header must include the values shown below.

Important: The sequence of the header attributes is critical and must exactly match the order below.

Name Data Type Description
atmosphere_app_id String The AppID assigned to the app in the platform.
atmosphere_nonce String A random string, uniquely generated for each request. The nonce allows the API providers to verify that a request has never been made before and helps prevent replay attacks when requests are made over a non-secure channel.
atmosphere_signature_method String Indicates the signature method used. Valid values are SHA1withRSA or NONE. The NONE signature method is used for APIs that don't require security. In this case, only the atmosphere_app_id is required in the SOA Software Open HTTP Authorization headers.
atmosphere_signature String The signature value. See next section for how the signature value is calculated.
atmosphere_timestamp String The timestamp of the request, expressed as the number of milliseconds since January 1, 1970 00:00:00 GMT. The timestamp must be a positive integer and must be greater than or equal to the timestamp used in previous requests.
atmosphere_version String The SOA Software Open version. Optional. If present, the valid value must be 1.0.

Sample header with authorization parameters (PKI approach)

Below is an example of an Authorization header with app authentication parameters. Make sure you list the parameters in the sequence shown below.

Note: The value for the realm is determined by the www-Authenticate header. Make sure the value you set in the Authorization: SOA Software Open header matches the value received for the attribute from the server.

Authorization: SOA Software Open realm="http://atmosphere",
  atmosphere_app_id="development-7FSXeNRkVRJ8XtAurgaea65R ",
  atmosphere_nonce="1323732744354",
  atmosphere_signature_method="SHA1withRSA",
  atmosphere_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
  atmosphere_timestamp="1323732744354",
  atmosphere_version="1.0"

Sample header without authorization parameters

Below is an example of an Authorization header for an API that doesn't require authentication:

Authorization: SOA Software Open realm="http://atmosphere",
atmosphere_app_id="http://www.open.com/app/101",
atmosphere_signature_method="NONE"

Note: In case the client, such as an Ajax client in the browser or an Android app, cannot set the HTTP Authorization header, you can set the required SOA Software Open authorization header parameters in the HTTP query string.

Composing the Signature

There are several steps to composing the signature:

Creating the Signature Base String

The first step in composing the digital signature is to create the content. Once that's done, the data is signed using the signature algorithm.

Note: The atmosphere_signature parameter must be excluded from the Signature Base String.

Below is an example of the Signature Base String.

POST&https://api.sandbox.yoursandbox.com/APIName/Payment/v1/MethodName
&atmosphere_app_id=Atmosphere-7FSXeNRkVRJ8XtAurgaea65R
&atmosphere_nonce=1323732744354&atmosphere_signature_method=SHA1withRSA
&atmosphere_timestamp=1323732744354&atmosphere_version=1.0

Signing the Signature Base String and Encoding the Signature

Once the Signature Base String is constructed, the next step is signing:

  1. Use the SHA-1 algorithm to generate the hash of the Signature Base String.
  2. Sign the hashed value using the private key of the app.
  3. Base64-encode the signature value. Note: Base64 encoding should not include the CRLF (carriage return/line feed) every 72 characters which is part of strict Base64 encoding. Instead, the whole Base64 encoded string should be without line breaks.
  4. Optionally, URL-encode the result into a string.
  5. Set the string as the value for the atmosphere_signature parameter.

Back to top


Header Example for Both Approaches

The example below shows the same message header as it would be if created with each approach.

Some parameters are common to both approaches:

Shared Secret Approach

In the example below, the message header uses the Shared Secret approach, with a Shared Secret value of 1008877afabf32efb31f9c974dbeaa688bed0769. The atmosphere_secret_digest value is the hashed value of nonce + timestamp + shared secret.

Atmosphere realm="http://atmosphere",
atmosphere_app_id="Atmosphere-2f97rkSViLn6yd7syPtRiG7q",
atmosphere_nonce="1328745832972",
atmosphere_timestamp="1328745832972",
atmosphere_digest_method="SHA1",
atmosphere_secret_digest="fr3u4BCMJv03THDqsj5c6RQMUWk=",
atmosphere_version="1.0"

PKI Approach

In the example below, the message header uses the PKI approach. The atmosphere-signature value is the signed value of the signature base string (see signature base string).

Atmosphere realm="http://atmosphere",
atmosphere_app_id="Atmosphere-2f97rkSViLn6yd7syPtRiG7q",
atmosphere_nonce="1328745832972",
atmosphere_timestamp="1328745832972"
atmosphere_signature_method="SHA1withRSA",
atmosphere_signature="XKYtUsH7ta8I5mbZaZebm4b6NLjAVSGcK3op9lJxWC%2FlpNLxAm1GoHoMkKzLUh
  %2BN7QdEBjR6ufgKMD%2BTWK4fPT2uXbHWNuOOTM4qUizrRymPxuAXEWhmECEB4WL7zr9UmWG7OGDsyuDUOt
  93nAnVvfqinF0bC%2FnWBAH%2FelZlX%2FUMtO29%2BNrMq7ep0B%2BWKEosJmCFBtfgk72kRYl5rKsDqDm2m
  gIFyHPWoFvC5WJiqtXTqGEaNxSbdWweaCaLqHNRnXowozOLMYYnnEd%2FTSFF0E5CrJBTzOq5Wvixnt6iJqWE
  J0ywIc%2FPjVFs5muYOv30Lno44F0w6h3vjKTHWOJHEg%3D%3D",
atmosphere_version="1.0"

Back to top