Quick Start

General SSO Concepts and Information

SSO key

No matter which Cisco SSO-enabled interface you use, you will find this information useful.

What is SSO?

What should I know before I try to use SSO?

Getting SSO Access Tokens

SSO for Specific Interfaces

Do you want to know more about how a specific product interface uses SSO? Go to that product’s portal and look for the product-specific SSO section.

Currently, you’ll find the following products are SSO-enabled:

What is the “client_id” for these interfaces?

Currently, SSO-enabled products have fixed “client_id” values. Client_id values cannot be registered dynamically, and any attempt to use a client_id value not already specified for the interface will result in an error.

What are the valid values for client_id?

SSO Interface-specific Examples

Need an example of using SSO with a specific interface? Find it here.

SSO Overview

What are the advantages of using SSO?

There are a number of advantages to using SSO:

Which Cisco products and interfaces support SSO?

Currently, you’ll find the following products are SSO-enabled:

How does SSO support different account types?

Your application will be treated differently by SSO depending on which account type it is trying to authorize.

The account types you will encounter are:

Product Interface Account Type Supported
Unified CM UDS End User
Unified CM WebDialer End User
Unified CM JTAPI & TAPI End User
Unity Connection Manager CUMI User (or “Service”)

The rules for the different account types are:

  1. Locally configured accounts are not supported when SSO is enabled.
  2. End User or “Service” Accounts are supported.
  3. LDAP-synchronized accounts are supported
  4. Application account behavior is fully preserved
  5. Application accounts should always use username/password credentials, as they are not affected by SSO feature status
  6. Applications using LDAP Synchronized User accounts with username/password or Oauth token when SSO is enabled
  7. If a server application is using an LDAP Synced user as an “application account” when SSO is enabled, this won’t work because the server application will not be able to login to the IdP.

Do Applications behave differently depending on SSO being enabled?

Account Types with and without SSO SSOAccountTypes.png

Applications do behave differently when SSO is enabled. Here is a summary of the differences:

Account Types SSO (disabled) SSO (enabled)
End User (local account) Password stored in UCM DB, PIN stored in UCM DB Account type not supported, PIN stored in UCM DB End User
(LDAP synchronized account) Password stored in customer LDAP validated via LDAP bind. PIN stored in UCM DB Browser clients SAML redirect to IdP. WebDialer, and UDS support passwords and IDP tokens concurrently. PIN stored in UCM DB
Application Password stored in UCM DB Password stored in UCM DB

Interesting SSO concepts and terms you may want to research

In this document, we are only going to cover how to use Cisco SSO. We will not cover introductory subjects like SSO components, concepts, or Cisco SSO implementation details you don’t really need to know as a developer. Cisco SSO is straightforward to use and fast to adopt, and that is what we’re focusing on here. However, developers are curious types, and you may want to know some of the more esoteric details surrounding and underpinning Cisco’s SSO.

If you would like to know more about Cisco SSO’s “engine room” details, and SSO using OAuth2 in general, look up these terms:

What should I know before I try to use SSO?

There are a few basics you should be aware of before using Cisco’s SSO facility on any of the supported interfaces.

Before you start

You need to be comfortable with the following before being able to successfully utilize Cisco’s SSO functionality:

Things you should know

Before successfully using the SSO feature, you’ll need to make sure your infrastructure is properly configured to supply the type of behavior you want.

This includes knowing where your Unified CM, IdP, and LDAP servers are, and how they are configured. Make sure you understand the following:

Get a Cisco SSO Token in 5 Steps

Cisco SSO is implemented conforming to OAuth 2.0. All you need to do is follow these 5 easy steps to request, acquire, and use an access token with any supported interface.

Step 1 - Request status of Single Sign On feature from Unified CM.

Step 2 - (Assuming SSO status = TRUE), parse the response and add required parameters.

Step 3 - Obtain an OAuth token by issuing a request through a WebView/Browser.

Step 4 - Within the browser/webview, the connecting client is redirected to the redirect_uri with the OAuth access token as a parameter.

Step 5 - Parse the token from the response and acquire access to the secured resource.

Step 1: Request Status of SSO feature

Request Status of SSO

RequestStatusofSSO

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-agent="Android"  --user-data-dir="C:/temp-chrome-eng" --app="http://localhost.cisco.com/SSOsampleapp.html"
<!-- Send a Single Sign On GET Request using HTTPS -->
GET https://<anyPublisherOrSubscriberIP>:8443/ssosp/ws/public/singleSignOn
<SSOResult>
<ErrorCode>0</ErrorCode>
    <Response>
        <SingleSignOn version="10.5.0.98000-77">
            <Status enabled="true"/>
            <Token reuse="false"/>
            <Uri>https://<sameIPaddressInRequest>:8443/ssosp/oauth/authorize</Uri>
        </SingleSignOn>
    </Response>
</SSOResult>
<!DOCTYPE html>
<html>
<head>
<title>SSO Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Using javascript to access SSO
    <script type="text/javascript" src="jquery-1.11.1.min.js"></script>
</head>
<body>
    <div class="navbar">
        <div class="navbar-inner">
            <a class="brand" href="#">Something</a>
        </div>
    </div>
    <div id="main" class="container">
        ...Put the javascript here...
    </div>
</body>
</html>
    <script type="text/javascript">
    // global variables
    // DS-SSO-ADFS.ds-adfs.sso.com
// secure doesn't work!
//      var UCMSSOstatusURL = 'https://ds-ucm105.cisco.com:8443/ssosp/ws/public/singleSignOn';
// insecure works
        var UCMSSOstatusURL = 'http://ds-ucm105.cisco.com/ssosp/ws/public/singleSignOn';
        var UCMusername = "user1";
        var UCMuserpass = "cisco!123";
        var UCMxhr;
    // DS-CUC105.cisco.com
//      var CUCSSOstatusURL = 'https://DS-CUC105.cisco.com:8443/ssosp/ws/public/singleSignOn';
        var CUCSSOstatusURL = 'http://DS-CUC105.cisco.com/ssosp/ws/public/singleSignOn';
        var CUCusername = "Administrator";
        var CUCuserpass = "ciscopsdt";
        var CUCxhr;

// common function for creating a CORS request
    function createCORSRequest(method, url, xhr){
        xhr = new XMLHttpRequest({mozSystem: true});
        console.log("debug 3A");
        if ("withCredentials" in xhr){
        console.log("debug 3B withCredentials");
            // false=sync, true=async
            xhr.open(method, url, true);
        } else if (typeof XDomainRequest != "undefined"){
            console.log("debug 3C XDomainRequest is supported/defined");
            xhr = new XDomainRequest();
            console.log("debug 3D XDomainRequest");

            xhr.open(method, url);
        } else {
            xhr = null;
        }
        console.log("debug 3E end of createCORSRequest()");

        return xhr;
    }

// UCM inquiry  
    var getSSOstatusUCM = createCORSRequest("GET", UCMSSOstatusURL, UCMxhr);
    console.log("debug 4A return from createCORSRequest(UCM)");
    if (getSSOstatusUCM){
        console.log("debug 4B getSSOstatusUCM created");

        // Now create the event handler
        // getSSOstatusUCM.onload = function(){
        getSSOstatusUCM.onreadystatechange = function(){
        //do something with getSSOstatusCUCM.responseText
            console.log("debug 5A onreadystatechange handler");
            if (getSSOstatusUCM.readyState == 4  && getSSOstatusUCM.status == 200) {
                console.log("UCM debug 5B readyState ==4");

                console.log(getSSOstatusUCM.status);
                console.log(getSSOstatusUCM.statusText);
                console.log(getSSOstatusUCM.responseText);

                // now parse the XML 
                console.log(getSSOstatusUCM.responseXML);

                xmlDoc = (new DOMParser()).parseFromString(getSSOstatusUCM.responseXML,"text/xml");

                // ------------

                var SSOresult=xmlDoc.getElementsByTagName("SSOResult");                 
                    console.log("DEBUG SSOresult: " + SSOresult[0].value);
                var errorCode=xmlDoc.getElementsByTagName("ErrorCode");
                    console.log("DEBUG errorCode: " + errorCode[0].value);
                var SSOresponse=xmlDoc.getElementsByTagName("Response");
                var SSOversion = xmlDoc.getElementsByTagName("SingleSignOn version");
                    console.log("DEBUG SSOversion: " + SSOversion[0].value);



            }  else
            {
                console.log("debug 5C readyState != 4 or getSSOstatusUCM.status != 200");
            }
        };
    }


// CUC Unity enquiry
    var getSSOstatusCUC = createCORSRequest("GET", CUCSSOstatusURL, CUCxhr);
    console.log("debug 4A return from createCORSRequest(CUC)");
    if (getSSOstatusCUC){
        console.log("debug 4B getSSOstatusCUC created");

        // Now create the getSSOstatusCUC event handler
        getSSOstatusCUC.onload = function(){
        //do something with getSSOstatusCUC.responseText
            console.log("debug 5A onload getSSOstatusCUC handler");
            if (getSSOstatusCUC.readyState == 4  && getSSOstatusCUC.status == 200) {
                console.log("CUC debug 5B readyState ==4");

                console.log(getSSOstatusCUC.status);
                console.log(getSSOstatusCUC.statusText);
                console.log(getSSOstatusCUC.responseText);
            }  else
            {
                console.log("debug 5C getSSOstatusCUC readyState != 4 or getSSOstatusCUC.status != 200");
            }
        };
    }
//-------------------------

    // set headers here if desired, after open() but before send()
    // void setRequestHeader(
//          DOMString header,
//          DOMString value
///     );
    console.log("debug 6A getSSOstatusUCM.send about to be called...");
    getSSOstatusUCM.send();
    console.log("debug 6B getSSOstatus.send returned");

    console.log("debug 6C getSSOstatusCUC.send about to be called...");
    getSSOstatusCUC.send();

    console.log("debug 6D getSSOstatus.send returned");

    </script>

We use GET to query the Unified CM SSO enabled status of our environment.

If SSO is enabled, we are handed back several parameters:

Return Parameters:

Step 2: If SSO enabled, parse URI and supply parameters

<!--Example:
POST  https://<10.10.10.10>:8443/ssosp/oauth/authorize?response_type=token&
client_id=C45c61cee396bcce508c58f1eefe326685c85243edf77f491d631e7b01d677f94&token_type=Bearer -->
POST https://<anyPublisherOrSubscriberIP>:8443/ssosp/oauth/authorize?<parameters>

If SSO is enabled and Step 1 returns “true”, we parse the response and add the required parameters:

Parameters:

Value MUST be ‘token’ in UCM 10. Passing a value other than ‘token’ will cause the request to be rejected with error ‘unauthorized_client’.

Clients MUST pass their OAuth client_id. UC 10.5 does not support client_id registration, so the client_id must be one of the pre-provisioned client_ids in UC 10.5.
Passing an unrecognized client_id will cause the request to be rejected with error ‘unauthorized_client’.

  1. Select Client ID based on interface used (see table)
  2. When two or more interfaces are used by the same application, select the Client ID of the first interface which authenticates the User.

Interface client_id values:

Interface Client ID Values

Interface Client ID
WebDialer C6738b873b76e759297af757959cbbaf5f438913186b26547b37fe2ab376311ab
CUMI Unity Connection C69908c4f345729af0a23cdfff1d255272de942193e7d39171ddd307bc488d7a1
User Data Service Cc4013d474571c1963e6d45ee9c835b6373b397bef748a6c864c07e95d8e6144e

Step 3: Obtain a token through WebView/Browser

Login prompt

After submitting the request from Step 2, the user is prompted for a valid user/password combination:

Step 4: Client is redirected to Unified CM with a valid token

This happens automatically and transparently to the user.

Step 5: Parse and use token to access a secured Resource

<!-- HTTPS REST request. -->
POST https://10.10.10.10:8443/ssosp/public/oauthcb#
access_token=MjpjMTAzNDk4NC00ZjhhLTQzMTMtYjdlNS0xMTI2MDgzNzNlZDg&
token_type=Bearer&expires_in=3600

    // Send a request with a token that looks something like this:
    //
    // <!-- HTTPS REST request. -->
    // POST https://10.10.10.10:8443/ssosp/public/oauthcb#
    //   access_token=MjpjMTAzNDk4NC00ZjhhLTQzMTMtYjdlNS0xMTI2MDgzNzNlZDg&
    // token_type=Bearer&
    // expires_in=3600


    var getSSOlogin = createCORSRequest("POST", signonURL + 
                                                "#" + 
                                                access_token + "&" +
                                                "token_type=Bearer&" +
                                                "expires_in=3600", signonXhr);
    if (getSSOlogin){

        // Now create the getSSOlogin event handler
        getSSOlogin.onload = function(){
        //do something with getSSOlogin.responseText
            if (getSSOlogin.readyState == 4  && getSSOlogin.status == 200) {

                console.log(getSSOlogin.status);
                console.log(getSSOlogin.statusText);
                console.log(getSSOlogin.responseText);
            }  else
            {
                console.log("debug 5C getSSOlogin readyState != 4 or getSSOlogin.status != 200");
            }
        };
    }

Parse and use token to access a secured Resource

POST http://10.10.10.10:8443/ssosp/public/oauthcb#

Use your access token (the value after “access_token” that looks like the following value in the Example) to access your Resource.

Parameters:

Using SSO with UDS

GET https://rcdn6-vm59-229.cisco.com/cucm-uds/user/alice
Host: rcdn6-vm59-229.cisco.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

Initial Response

Returns “Basic” only if SSO is not enabled OR Returns both “Basic” and “Bearer” if SSO is enabled.

<!-- First, the "SSO Enabled" response: -->
401 Unauthorized
Cache-Control:  private
Expires:  Wed, 31 Dec 1969 18:00:00 CST
WWW-Authenticate:  Basic realm="Cisco Web Services Realm" 
WWW-Authenticate:  Bearer realm="Cisco Web Services Realm"
Content-Type:  text/html;charset=utf-8
Content-Length:  2235
Date:  Tue, 14 Jan 2014 18:09:24 GMT
<!--  "SSO not enabled" response: -->
401 Unauthorized
Cache-Control:  private
Expires:  Wed, 31 Dec 1969 18:00:00 CST
WWW-Authenticate:  Basic realm="Cisco Web Services Realm"
Content-Type:  text/html;charset=utf-8
Content-Length:  2235
Date:  Tue, 14 Jan 2014 18:09:24 GMT

Using SSO with WebDialer

<!-- WebDialer HTTPS Request. Provide either 'token' OR 'username+password' in the Credential element -->
   <complexType name="Credential">
    <choice>
            <element name="token" type="xsd:string" />
            <sequence>
                <element name="userID"  type="xsd:string" />
<element name="password" type="xsd:string" />
</sequence>
   </choice>
</complexType>