Cloud to OnPremise API authentication

Introduction: The goal of this document is to document an initial interop scenario for using OAuth2 with assertions (instead of client-secrets), for web-services API authentication between environment.

Demo: Google has provided some sample apps that run on Google App Engine to demonstrate some of the building blocks of this interop scenario.

Scenario: Acme Corp has an on-premise app called WidgetCustomers that tracks how their different business customers use the product they sell called Widget. It has an API to let other IT systems read/write information into WidgetCustomers app. The Acme IT department wants to build a web-application called WidgetCloud that will run on the cloud and act as a frontend to the WidgetCustomers app as a first step to slowly moving WidgetCustomers completely into the cloud.

Challenge: When WidgetCloud makes API calls to WidgetCustomers, how will it prove that it is in fact the WidgetCloud application. In particular, if an IT administrator is fired who had previously had access to the sourcecode of those two systems, could they impersonate the WidgetCloud app and make API calls to WidgetCustomers?

Evolution of Solutions: There are many ways to enable WidgetCloud->WidgetCustomers, however most enterprise IT departments are looking for a standard way of doing it that reduces the risk of stolen credentials. The following is a list of approaches from weaker to stronger:

    • Hardcoded password: The programmers of the two systems agree on a password they will hardcode into both systems. WidgetCloud includes that password on all API calls.

    • Role Account: Acme has a central on-premise identity system where they create an entry for the WidgetCloud app, assign a username and put in the hardcoded password. WidgetCloud makes an API call to that on-premise identity system with the username+password and gets back a time-limited token it can then send to the WidgetCustomers API.

    • Public Key: Same as #2, but instead of a password the WidgetCloud app generates a public/private key pair and only gives the public key to the team running the on-premise identity system. They plan to manually rotate the key, but hardly ever do.

    • Automatic Rotation: Same as #3, but WidgetCloud publishes an Internet accessible file with a public key that it rotates daily and the on-premise identity system always uses the latest key to verify the identity of WidgetCloud

    • Cloud Key: Same As #4, but WidgetCloud runs on a Cloud PaaS/IaaS environment like Azure/AWS/Force.com/GoogleAppEngine/etc. The PaaS/IaaS environment publishes the file with the rotating key. WidgetCloud asks the PaaS/IaaS environment to sign a blob with the role account username that it sends to the on-premise identity system to verify its identity and then get back a time-limited token it can send to the WidgetCustomers API.

    • Standard Cloud Key: Same as #4 but the format of the file is an Internet standard [self-signed x509 certificate, encoded as ASN.1 DER], the format of the signed blob with the username (OAuth CK) is an Internet standard [JSON token], and the structure of the API call to the on-premise identity system is an Internet standard [OAuth2 assertion profile], and (less importantly) the structure of calls to the WidgetCustomers API is an Internet standard including error codes for expired tokens [OAuth2 access to protected resource].

Vendor Status:

Google: In March 2011 Google will have support for the PaaS elements of item #5.

Azure: The Azure ACS team have been the leaders in this space since their includes of OAuth-WRAP support in the fall of 2009. They have added support for later drafts of OAuth2. I am trying to check on how ACS supports the scenario in this document.

Salesforce: Salesforce led the effort to define the first standard for an assertion token that can be used in OAuth2 instead of a client-secret. I am trying to check on how Salesforce supports the scenario in this document.

Ping: Ping Identity is one of the well-known STS products that already supports swapping a token of one format for another. I am trying to check on how Ping supports the scenario in this document.

Oracle: Oracle has also blogged about the market demand they see of this type of scenario. I am trying to check on how Oracle supports the scenario in this document.

VMWare: I am trying to check on how VMWare supports the scenario in this document.

Intel: I am trying to check on how Intel Access360 supports the scenario in this document.

Details of the Cloud Key approach

    1. Tom is an employee of Acme who controls the application “WidgetCloud” running on the PaaS/IaaS environment operated by vendor "Zoo"

    2. Sara is an employee of Acme who controls the on-premise identity system which her company calls CorpSSO.

    3. Tom goes to the PaaS/IaaS documentation of Zoo and learns the URL of the file which is used to publish the public cert(s) in a standard format (see proposal) that the PaaS/IaaS environment manages on behalf of his app.

    4. Tom then emails Sara and asks her to first create a role account in their CorpSSO system (or maybe an LDAP server it uses) that will be used to identity WidgetCloud. He then asks here to setup a mapping in CorpSSO between that URL with the public cert and this new role account instead of generating a traditional password for the role account. Sara does so and tells Tom that she assigned it the role account name “ZooWidgetCloud.”

    5. Tom then asks Sara to give that role account permission to access the WidgetCustomers app. Sara configures a policy framework (in CorpSSO, or in WidgetCustomers, or some central identity/ACL system) to allow that access.

    6. Tom then reads the documentation on the format of assertions he must send to Acme’s CorpSSO system, as well as the API call he must make with the assertion. The docs specify the format, as well as the signing mechanism, and (optionally) the place in the API call to identify the current cert used for signing. [The format is completely up to Acme/CorpSSO, but it would be preferable for it to be the JSON Web Token format]

    7. Tom then writes codes in his WidgetCloud application which implements the following steps

    8. WidgetCloud creates a blob in the format he learned in step 6. The blob at minimum specifies the ZooWidgetCloud role account, the current time, and the name of the target system, i.e. WidgetCustomers.

    9. WidgetCloud then asks the PaaS/IaaS environment to sign that blob and return the signature

    10. WidgetCloud makes an API call to the CorpSSO system using the mechanism he learned in step 6 [The API call structure is completely up to Acme/CorpSSO, but it would be preferable for it to be the OAuth2 assertion profile <that profile may or may not be in the core spec>]

    11. The CorpSSOsystem receives the API call. It extracts the claimed role account name, and in its local system it looks up the URL with the public cert(s) of that app. It tries each of those public certs to see if it can validate the signature (as an optimization, in step6 the signing key could be returned along with the signature, and passed as a paramter in the API call of step 10)

    12. The CorpSSOsystem then extracts the desired target and checks the policy framework to make sure the pair of role-account/target is allowed.

    13. The CorpSSOsystem then returns its own signed time-stamped API-ticket to the WidgetCloud app. [The format of this API ticket is opaque to Widget-Cloud but it would be nice if it were a standard JSON Web Token]

    14. WidgetCloud makes an API call to the WidgetCustomers app with that API-ticket. [The structure of this API call is completely up to Acme/CorpSSO, but it would be preferable for it to follow the OAuth2 standard for accessing a protect resource]. As an optional component, there may be a reverse-proxy/firewall/dmz system that sits between the WidgetCustomers API endpoint and the Internet and rejects all API calls unless the API contains a valid API ticket.

    15. WidgetCustomers uses a local framework to validate that API ticket. If valid, it performs the requested function and returns the result. If the ticket is invalid it returns an error [The structure of this error is completely up to Acme/CorpSSO, but it would be preferable for it to follow the OAuth2 standards for common errors like that of an expired access token]