cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Announcements

Understanding OAuth and MRA

5208
Views
55
Helpful
28
Comments

Overview: What is OAuth

Imagine sitting in an interview room with a bunch of techies, firing questions at you, assessing you, sizing you up and you walking in with confidence and trepidation knowing fully well you really want the job but also that you are really good at what you do, but somehow things are not going quite well as you would want or envisage and then in the midst of all the pandemonium and barrage of questions, you hear these words: "Do you know how OAuth works"?? 

And you bet, my ears felt like ( did I just hear that) and in my head I am like "O what?"

If you want to know the result of that interview you would have to stay with me till the very end...But for now lets get into the matter of OAuth.

OAuth is simply an Authorization protocol defined by RFC 6749. OAuth allows an end user ( like me)  to authorize an application (like Jabber) to gain access to a third party service ( like CUCM) without sharing their credentials with the application.

OAuth is becoming the defacto authorization protocol within UC collaboration solutions and vendors like Cisco and Microsoft have deployed it within their solution stacks. Some UC solutions deploying or requiring OAuth are

  • Jabber(internal)/MRA
  • Unity Connection with O365 ( unified Messaging)
  • SfB client ( uses Oauth with SFB server)

 

OAuth Components

OAuth is an authorization framework specification that comprises of different components. The diagram below gives the components used within the Cisco Oauth deployment.

oauth-components.PNG

  • Resource Owner: This is you the end user
  • User agent: This is the application that requires access to resources on your behalf ( Jabber, UCxN ( with O365))
  • Resource Server: CUCM, O365, SfB
  • Authorization Server: This is the server that issues your tokens, encrypts and signs them. eg Unified CM OAuth server

 

Architecture

The diagram below shows the Oauth architecture used within CUCM and the interactions between the end user and various components in the Oauth deployment

oauth (1).png

 

OAuth Tokens: 

CUCM uses tokens to authorize access to resources once user has been successfully authenticated. Depending on the CUCM version and the Oauth grant flow model used, CUCM uses either

  • Access tokens only or
  • Access tokens and Refresh tokens

The process of Authentication involves a user confirming their identity  and approving what information can be accessed. Once the user has been successfully authenticated,  access token is issued to the 3rd party using OAuth by the authorization server. Cisco implementation offers two tokens that will be issued for authorizing access to resources

  1. Access token: 
    • This token is issued by the authorization server. The client presents the token to a resource server when it needs to access protected resources on that server. The resource server needs to validate these tokens and is able to that because the Oauth-authorization server would have distributed the encryption and signing keys for these tokens to it. As a result, the resource server trusts connection requests using these tokens (Cisco access tokens default to a lifetime of 60 minutes)
  2. Refresh tokens 
    • This token again is issued by the authorization server. The client presents this token to the authorization server together with the client secret when the access token has expired or is due to expire. If the refresh token is still valid then the authorization server will issue a new access token without requiring another authentication. (Cisco
      refresh tokens default to a lifetime of 60 days). If the refresh token has expired then a new full OAuth authorization code grant flow has to be initiated to obtain new tokens.

 

OAuth Grant Flows and CUCM support:

OAuth supports multiple grant flows however CUCM deployment supports the following:

CUCM Version OAuth Flow model Authentication method Tokens issued
10.5 <=  cucm-version <  11.5.1(SU3) Implicit Flow SAML SSO only access token
>= 11.5.1(SU3) Authorization code grant flow Local user, LDAP and SAML SSO access token, refresh token

 

OAuth Encryption and signing keys

CUCM OAuth server generates a set of encryption and signing keys used for signing and encrypting OAuth tokens. These keys are automatically distributed within Unified CM clusters to call control and IM and presence nodes. Unity connection and Expressway-C servers are also able to fetch encryption and signing keys using a REST API. 

The signing/encryption key set is used to validate/decrypt tokens presented by jabber clients when authorization to a resource is requested

 

OAuth Benefits

OAuth provides several benefits to both end users and UC administrators. Some of these benefits are highlighted below:

  • End user is mot required to authenticate when the client is restarted
  • Authentication doesn’t fail when the password is changed
  • Faster login process once authenticated as well as offline login
  • Allows for stronger authentication methods (multi-factor, biometric) when combining OAuth with SAML 2.0 based single sign-on
  • Reduction in password support cases
  • A user is not required to share credentials with a 3rd party application

 

How to Enable OAuth

The recommended and supported versions for OAuth are shown below:

Screenshot 2020-04-22 at 10.42.06.png

Enabling Unified CM & IM&P

To enable OAuth perform the following procedure
1. Go to Cisco Unified Communications Manager Admin > System > Enterprise Parameters > SSO and OAuth Configuration and

"Select OAuth with Refresh Login Flow" set Enable support OAuth feature. ( adjust timers if desired)

enable-oauth.PNG

NB: There is no configuration change required on IM&P nodes. CUCM will automatically push this settings to all the IM&P nodes in the cluster.

There is an exception to this and that is when centralized IM&P cluster is deployed. Additional configuration is required on the IM&P cluster to fetch the OAuth token keys from the CUCM clusters

 

Enabling Unity Connection

Two steps are required to enable unity connection for OAuth:

  1. Configure the Unity connection Server to fetch OAuth token signing and encryption keys from Unified CM. This step is required because unity connection is not part of CUCM cluster, hence we need to find a way to obtain the sign and encryption key from CUCM Oauth server.
  2. Enable OAuth services on Unity connection cluster

To obtain the signing and encryption keys Unity must be configured with the Unified CM host details and a user account enabled for Unified CM AXL access
Go to AuthZ Servers > Add New

unity.PNG

 

MRA and OAuth Trace Analysis

Now that the theory is explained and understood we now take a deep dive into the inner workings of OAuth in MRA deployment.

The selected trace analysis was taking while troubleshooting an issue with OAuth login flow and I thought it might provide an excellent source of learning. Sit tight, here we go....

 

++ Summary of Issue ++

After enabling OAuth on CUCM and Expressway-C, users attempted to login, got the CUCM browser page ( shown in step 4 of the architecture diagram), entered in user credentials but got "unable to communicate with server"

 For all who are familiar with the Jabber MRA call flow, the first request that jabber sends ( after _collabe-edge SRV lookup) used to be "get_edge_config" However to support OAuth flow, the first request that jabber sends now is

"get_edge_sso"

The next few lines we will detail the requests and responses used in OAuth flow with Jabber

Request-sequence

Request Sent

{1: get_edge_sso}

GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/get_edge_sso?email=aokanlawon@lab.com

 

++ Expressway-E receives the request ++

2020-03-24T16:31:00.962-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:00,962" Module="network.http.trafficserver" Level="INFO": Detail="Receive Request" Txn-id="2004" Src-ip="81.157.160.37" Src-port="59252" Msg="GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/get_edge_sso?email=aokanlawon@lab.com HTTP/1.1"
2020-03-24T16:31:00.962-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:00,962" Module="network.http.trafficserver" Level="DEBUG": Detail="Receive Request" Txn-id="2004" Src-ip="81.157.160.37" Src-port="59252"
HTTPMSG:
|GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/get_edge_sso?email=aokanlawon@lab.com HTTP/1.1
Host: labucexpye01.lab.com:8443
Accept: */*
User-Agent: Jabber/12.8.0.51920 (Windows;)

 

++ Expwe-responds with 200 OK With Token-reuse set to True ( NB: Request is forwarded to ExpwC and C sends to CUCM and CUCM responds based on the Refresh login configuration ++

 

2020-03-24T16:31:00.963-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:00,962" Module="network.http.trafficserver" Level="DEBUG": Detail="Sending response" Response-code="200" Txn-id="2004" Dst-ip="81.157.160.37" Dst-port="59252"
MSGBODY:
|<?xml version='1.0' encoding='UTF-8'?>
<SSOResult version="1.0">

     <Response>

        <SingleSignOn>

            <Status enabled="false"/>

            <Token reuse="true"/>                                        

        </SingleSignOn>

     </Response>

</SSOResult>

 

++ Once Token re-use is set to True, Expressway-E will then presents Jabber with a login form ( via the built in web browser) 

Once the user has entered all the login details, Jabber sends an Authorize Response with the client ID to be used for the authentication++

 

Request-Sequence

Request Sent

{2: "authorize?response_type=code&realm=local&client_id="}

"GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/authorize?response_type=code&realm=local&client_id=....

 

++ Jabber confirms Token reuse is enabled ++

2020-03-24 22:31:00,442 INFO [0x00002b04] [rvices\impl\system\SingleSignOn.cpp(206)] [Single-Sign-On-Logger] [CSFUnified::SingleSignOn::Impl::isAuthenticatorTokenReuseEnabled] - TokenReuse enabled for 1001
2020-03-24 22:31:00,442 DEBUG [0x00002b04] [rvices\impl\system\SingleSignOn.cpp(329)] [Single-Sign-On-Logger] [CSFUnified::SingleSignOn::Impl::setCredentialAuthorizationMode] -

 

++ Jabber states that services needs authorization and we need credentials for authentication ++

2020-03-24 22:31:00,442 INFO [0x00002b04] [\impl\system\UserProfileManager.cpp(153)] [UserProfileManager] [CSFUnified::UserProfileManager::Impl::getCredentialsForAuthenticator] - for authenticator: 1001
2020-03-24 22:31:00,442 DEBUG [0x00002b04] [vices\impl\system\SingleSignOn.cpp(2044)] [Single-Sign-On-Logger] [CSFUnified::SingleSignOn::Impl::currentServiceNeedsAuthorization] - creds->getSecureOAuthToken().empty() for service: 1001

 

++ Jabber sends authorization response with client id++

 2020-03-24 22:31:00,442 DEBUG [0x00002b04] [bwindowplugin\browsercontroller.cpp(167)] [PluginUtils]

[BrowserController::NavigateTo] - Enter - url = https://labucexpwye01.bouldermedicalcenter.com:8443/Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/authorize?response_type=code&realm=local&client_id=C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d7

8774e305bae9ab1&device_id=2c23dad7-ab7e-4686-a461-b23cffbaa15e&email=aokanlawon@lab.com&state=1771145038

 

++ Expressway-E recieves the the Authorization response ++

2020-03-24T16:31:01.569-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:01,569"

Module="network.http.trafficserver" Level="INFO": Detail="Receive Request" Txn-id="2005" Src-ip="81.157.160.37"

Src-port="59254" Msg="GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/authorize?response_type=code&realm=local&client_id=C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d78774

e305bae9ab1&device_id=2c23dad7-ab7e-4686-a461-b23cffbaa15e&email=aokanlawon@lab.com&state=1771145038 HTTP/1.1"
2020-03-24T16:31:01.569-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:01,569" Module="network.http.trafficserver" Level="DEBUG": Detail="Receive Request" Txn-id="2005" Src-ip="81.157.160.37" Src-port="59254"
HTTPMSG:

 

++ Next Jabber sends Authentication request with client_id established earlier ++

 

Request-Sequence

Request Sent

{3: "localauthentication"}

"POST https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/localauthentication HTTP/1.1"

 

+++ Next Jabber sends a POST request for local authentication with its client_id++

 

2020-03-24T16:31:22.729-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:22,729"

Module="network.http.trafficserver" Level="INFO": Detail="Receive Request" Txn-id="2007" Src-ip="81.157.160.37"

Src-port="59254" Msg="POST https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/localauthentication HTTP/1.1"
2020-03-24T16:31:22.729-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:22,729"

Module="network.http.trafficserver" Level="DEBUG": Detail="Receive Request" Txn-id="2007" Src-ip="81.157.160.37" Src-port="59254"
HTTPMSG:
|POST https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/localauthentication HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*
Referer: https://labucexpye01.lab.com:8443/Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/authorize?response_type=code&realm=local&client_id=C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d78

774e305bae9ab1&device_id=2c23dad7-ab7e-4686-a461-b23cffbaa15e&email=aokanlawon@lab.com&state=1771145038

 

+++ Next Expressway-E sends POST request to C +++

+++ Expressway-C receives the request +++

 

2020-03-24T16:31:22.739-06:00 labucexpyc01 traffic_server[14358]: UTCTime="2020-03-24 22:31:22,739" Module="network.http.trafficserver" Level="INFO": Detail="Receive Request" Txn-id="6114" Src-ip="127.0.0.1"

Src-port="33688" Last-via-addr="10.10.1.44" Msg="POST http://vcs_control.lab.com:8443/Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/localauthentication HTTP/1.1"

 

+++ Expressway-C will do two things here
1. Verify the UDS server to use for the authentication
2. Send a POST authorize_proxy request to the CUCM after use has been validated

 

Request-Sequence

Request Sent

{4: "edgeconfigprovision"

|GET //cucm.lab.com:8443/cucm-uds/clusterUser?username=<CONCEALED>|

 

+++ Expressway C sends edge config provision to find UDS server to use +++

2020-03-24T16:31:22.741-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:22,741" Module="network.http.edgeconfigprovisioning" Level="DEBUG" Action="Send"

Url="https://av-cucm.lab.com:8443/cucm-uds/clusterUser?username=<CONCEALED>"

HTTPMSG:
|GET //av-cucm.lab.com:8443/cucm-uds/clusterUser?username=<CONCEALED>|

 

+++ CUCM sends 200 OK , so now we are going to use this UDS server for the authentication +++

 

2020-03-24T16:31:22.851-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:22,851" Module="network.http.edgeconfigprovisioning" Level="DEBUG" Action="Received"

Request-url="https://av-cucm.lab.com:8443/cucm-uds/clusterUser?username=<CONCEALED>"
HTTPMSG:
|HTTP/1.1 200 OK
-----
X-Content-Type-Options: ['nosniff']
Expires: ['Wed, 31 Dec 1969 17:00:00 MST']
----
Content-Type: ['application/xml']
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><clusterUser version="11.5.1"

uri="https://cucm.lab.com:8443/cucm-uds/clusterUser?username=<CONCEALED

 

Request-Sequence

Request

{5: "authorize_proxy"}

HTTPMSG:
|POST //cucm.lab.com:8443/ssosp/token/authorize_proxy HTTP/1.1

 

+++ Once UDS server is located,

Next Expressway-C sends Authorize_proxy POST request to CUCM +++

 

2020-03-24T16:31:22.852-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:22,852" Module="network.http.sso.server" Level="DEBUG" Action="Send"

Url="https://cucm.lab.com:8443/ssosp/token/authorize_proxy"
HTTPMSG:
|POST //cucm.lab.com:8443/ssosp/token/authorize_proxy HTTP/1.1
X-Credentials: <CONCEALED>
Content-Type: ['application/x-www-form-urlencoded']
Authorization: <CONCEALED>
User-Agent: ['TANDBERG-Video-Communication-Server/X12.5.7']
client_id=C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d78774e305bae9ab1&response_type=

code&realm=local&state=1771145038

 

+++ CUCM sends 200 OK with the authorization code for the user+++

 

2020-03-24T16:31:23.025-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:23,025" Module="network.http.sso.server" Level="DEBUG" Action="Received" Request-url="https://av-cucm.lab.com:8443/ssosp/token/authorize_proxy"
HTTPMSG:
|HTTP/1.1 200 OK
{"redirect_uri":"https://cucm:8443/ssosp/public/OAuthcb#code=<CONCEALED>&expires_in=299&realm=local&state=1771145038"}
|

2020-03-24T16:31:23.029-06:00 labucexpyc01 edgeconfigprovisioning: Level="INFO" Event="Edge OAuth/SSO" Service="OAuth/SSO" Detail="Successful authorization" Dst-ip="127.0.0.1" Dst-port="33252" Local-ip="127.0.0.1" Local-port="22111" Server="10.12.1.172" Username="aokanlawon" UTCTime="2020-03-24 22:31:23,029"
2020-03-24T16:31:23.030-06:00 labucexpyc01 edgeconfigprovisioning: Level="INFO" Event="Edge SSO" Service="OAuth/SSO" Detail="Redirected client" Dst-ip="127.0.0.1" Dst-port="33252" Local-ip="127.0.0.1" Local-port="22111" Redirect="/OAuthcb#code=Hidden" Username="aokanlawon" UTCTime="2020-03-24 22:31:23,030"

 

+++ Next Expresway-C sends 302 to Expressway-E and E sends 302 to the client to get the authorization code +++

2020-03-24T16:31:23.031-06:00 labucexpyc01 traffic_server[14358]: UTCTime="2020-03-24 22:31:23,031" Module="network.http.trafficserver" Level="DEBUG": Detail="Sending Response" Txn-id="6114" Dst-ip="127.0.0.1" Dst-port="33688"
HTTPMSG:
|HTTP/1.1 302 Found
Location: /OAuthcb#code=<CONCEALED>|

 

++ Next expressway-E sends the 302 redirect to Jabber ++

2020-03-24T16:31:23.023-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:23,023" Module="network.http.trafficserver" Level="DEBUG": Detail="Sending Response" Txn-id="2007" Dst-ip="81.157.160.37" Dst-port="59254"
HTTPMSG:
|HTTP/1.1 302 Found
Location: /OAuthcb#code=<CONCEALED>|

 

+++ Next Jabber sends a GET request using the authorization code to get an access token +++

Request-Sequence

Request

{6: "OAuthcb"}

GET https:///OAuthcb HTTP/1.1

 

2020-03-24T16:31:23.155-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:23,155" Module="network.http.trafficserver" Level="DEBUG": Detail="Receive Request" Txn-id="2008" Src-ip="81.157.160.37" Src-port="59254"
HTTPMSG:
|GET https:///OAuthcb HTTP/1.1
----
Referer: https://labucexpye01.lab.com:8443/Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/authorize?response_type=code&realm=local&client_id=---&email=aokanlawon@lab.com&state=1771145038

 

+++ Expressway-E sends 200 OK to Jabber indicating that the authorization code is valid ( Note that E does not sent this to Expw_C, its processed locally by expwe +++

 

2020-03-24T16:31:23.155-06:00 labucexpye01 traffic_server[16087]: UTCTime="2020-03-24 22:31:23,155" Module="network.http.trafficserver" Level="DEBUG": Detail="Sending response" Response-code="200" Txn-id="2008" Dst-ip="81.157.160.37" Dst-port="59254"
MSGBODY:
|<html>
<head>
<Title>Authorization Complete</Title>
<script language="javascript">
document.write("Authorization Complete");

 

+++ Now Jabber will send a POST request to get access_token and will embed the following information in the POST request +++
1. authorization code
2. client_id

Request-Sequence

Request

{7: "access_token"}

|POST //cucm.lab.com:8443/ssosp/token/access_token 

 

2020-03-24T16:31:23.789-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:23,789" Module="network.http.sso.server" Level="DEBUG" Action="Send"

Url="https://av-cucm.lab.com:8443/ssosp/token/access_token"
HTTPMSG:
|POST //av-cucm.lab.com:8443/ssosp/token/access_token HTTP/1.1
Content-Type: ['application/x-www-form-urlencoded']
Authorization: <CONCEALED>
User-Agent: ['TANDBERG-Video-Communication-Server/X12.5.7']
code=<CONCEALED>&client_id=C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d78774e305bae9ab1&

grant_type=authorization_code

 

+++ CUCM responds with 200 OK containing +++
1. refresh_token, refresh_token expiration time
2. access_token,

 

|HTTP/1.1 200 OK
{ "expires_in":3600, "token_type":"Bearer",
"refresh_token":"eyJhbGciOiJSUzI1Ni--------38oMy0ldmfJRSVRa8r8iuJJbDxA",
"refresh_token_expires_in":5184000,
"access_token":"eyJhbGciOiJSUzI1NiIsI---xRtbYA" }

 

Finally,

+++ Expressway-C Validates that access token is valid +++

Request-Sequence

Request

{8: "OAuthvalidator"}

|POST //127.0.0.1:9998/OAuthvalidator?reqtype=access 

2020-03-24T16:31:23.917-06:00 labucexpyc01 edgeconfigprovisioning UTCTime="2020-03-24 22:31:23,917" Module="network.http.sso.server" Level="DEBUG" Action="Send" Url="http://127.0.0.1:9998/OAuthvalidator?reqtype=access"
HTTPMSG:
|POST //127.0.0.1:9998/OAuthvalidator?reqtype=access HTTP/1.1
Content-Type: ['application/json']
{"token": "<concealed>"}
|

2020-03-24T16:31:23.920-06:00 labucexpyc01 credentialmanager: Level="INFO" Detail="Access Token accepted" User="aokanlawon" UTCTime="2020-03-24 22:31:23,920"
2020-03-24T16:31:23.920-06:00 labucexpyc01 credentialmanager: UTCTime="2020-03-24 22:31:23,918" Module="developer.credentialmanager.OAuthinspector" Level="INFO" CodeLocation="OAuthinspector(331)" Detail="Token validation" Type="Access Token" Reason="Matched AuthZ key" Issuer="cucm.lab.com"
2020-03-24T16:31:23.920-06:00 labucexpyc01 credentialmanager: UTCTime="2020-03-24 22:31:23,919" Module="developer.credentialmanager.OAuthinspector" Level="INFO" CodeLocation="OAuthinspector(331)" Detail="Token validation" Type="Access Token" Reason="Matched AuthZ key" Issuer="a-cucm.lab.com"

 

OAuth process is now complete and Jabber will then start the normal service requests process but rather than using user credentials, will use the authorization header which will contain the access_token that has been obtained.

++ get_edge_config with Authorization header and access_token embedded ++

 

HTTPMSG:
|GET https:///Ym91bGRlcm1lZGljYWxjZW50ZXIuY29t/get_edge_config?service_name=_cisco-uds&service_name=_cuplogin HTTP/1.1
Host: labucexpye01.lab.com:8443
Accept: */*
User-Agent: Jabber/12.8.0.51920 (Windows;)
Authorization:<CONCEALED>

 

++ Back to the issue +++

Now that we understand the flow and we can see that the OAuth flow successfully completes, we now focus on why the client still could not login. For this we need to turn to Jabber PRT logs,

From the Jabber logs, here is what I see:

+++ 2020-03-31 12:12:54,998 ERROR [0x000006c8] [rwerx\jwcpp\xmppcore\src\client.cpp(192)] [csf.jwcpp] [gloox::Client::handleNormalNode] - @XmppSDK: #0, The server doesn't offer any SASL authentication mechanism that we can support

 

++ Jabber says that there is no Simple Authentication and Security Layer (SASL) authentication mechanism it can support ++

Questions is why? We have already established that Jabber is going to use OAuth for this session and has successfully obtained the required tokens. So what is going on.??

 

To understand what is going on, we need to know that Jabber needs to know the supported SASL authentication mechanism in the XMPP features advertised by Expressway-C. This in-turn depends on the advertised SASL authentication supported by IM&P server. So the next logical place to go is to find what SASL mechanism is advertised by both IM&P and Expressway-C

 

1. ++ Expressway-C request to get supported sasl mechanism supported by IM&P ++

2020-03-31T05:13:03.271-06:00 labucexpwyc01 XCP_JABBERD[28071]: UTCTime="2020-03-31 11:13:03,271" ThreadID="140493154612992" Module="Jabber" Level="VBOSE" CodeLocation="deliver.c:1171" Detail="DELIVER: type:8, host:auth-1.lab2-imp-lab-com, packet:<route type='redirect' to='auth-1.lab2-imp-lab-com' from='sdns_plugin-1.labucexpwyc01-lab-com'><xdb from='connect-auth-1.labucexpwyc01-lab-com' id='conauth765380-jtx_10392' ns='http://jabber.com/protocol/sasl' to='lab.com' type='get'><jid>ntanborgeson@lab.com</jid></xdb></route>"


2. ++ IM&P responds with SASL streams supported ++

NB: OAUTHBEARER ( is included in the SASL mechanism supported. This is required for OAuth to work)

 

2020-03-31T05:13:03.290-06:00 labucexpwyc01 XCP_JABBERD[28071]: UTCTime="2020-03-31 11:13:03,290" ThreadID="140493163005696" Module="Jabber" Level="VBOSE" CodeLocation="deliver.c:1171" Detail="DELIVER: type:1, host:connect-auth-1.labucexpwyc01-lab-com, packet:<xdb from='lab.com' id='conauth765380-jtx_10392' ns='http://jabber.com/protocol/sasl' to='connect-auth-1.labucexpwyc01-lab-com' type='result'><jid>ntanborgeson@lab.com</jid>

<mechanisms>

    <mechanism>PLAIN</mechanism>

    <mechanism>CISCO-VTG-TOKEN</mechanism>

    <mechanism>OAUTHBEARER</mechanism>

    <hostname xmlns='urn:xmpp:domain-based-name:0'>lab1-imp.lab.com</hostname>

    <hostname xmlns='urn:xmpp:domain-based-name:0'>lab2-imp.lab.com</hostname>

</mechanisms></xdb>"

 

3. +++ However Expressway-C sets SASL supported mechanism to only CISCO-VTG-TOKEN +++

NB: Jabber will use SASL mechanism:CISCO-VTG-TOKEN for normal basic user credentials login, but this is OAuth login.


2020-03-31T05:13:03.290-06:00 labucexpwyc01 XCP_JABBERD[28071]: UTCTime="2020-03-31 11:13:03,290" ThreadID="140493146220288" Module="Jabber" Level="VBOSE" CodeLocation="deliver.c:1171" Detail="DELIVER: type:8, host:auth-1.lab1-imp-lab-com, packet:<route type='redirect' to='auth-1.lab1-imp-lab-com' from='connect-auth-1.labucexpwyc01-lab-com'><xdb from='cm-1_jsmcp-1.labucexpwye01-lab-com' id='jtx_10392' ns='http://jabber.com/protocol/sasl' to='lab.com' type='set'><auth mechanism='CISCO-VTG-TOKEN' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>XXXXXXX</auth></xdb></route>"

 

4. ++ Expressway-E sets SASL supported mechanism to CISCO-VTG-TOKEN and sends to Jabber ++

 

2020-03-31T05:13:03.338-06:00 labucexpwye01 XCP_JABBERD[16268]: UTCTime="2020-03-31 11:13:03,338" ThreadID="139821024597760" Module="Jabber" Level="DEBUG" CodeLocation="MIOByteSource.cpp:93" Detail="Got Buffer (324) <xdb from='cm-1_jsmcp-1.labucexpwye01-lab-com' id='jtx_10392' ns='http://jabber.com/protocol/sasl' to='lab.com' type='set'><auth mechanism='CISCO-VTG-TOKEN' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>XXXXXXX</auth></xdb>"

 

5. ++ Jabber sees only CISCO-VG-TOKEN as the advertised SASL mechanism suported in the XMPP stream features

and responds with no SASL mechanism supported  +++

 

2020-03-31 12:12:54,998 INFO [0x000006c8] [jwcpp\xmppcore\patch\TriClient.cpp(1636)] [csf.jwcpp] [gloox::CTriClient::HandleXmlTag] - @XmppSDK: #0, 187, Recv:<stream:features xmlns:stream="http://etherx.jabber.org/streams"><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>CISCO-VTG-TOKEN</mechanism></mechanisms></stream:features>

 

2020-03-31 12:12:54,998 INFO [0x000006c8] [jwcpp\xmppcore\patch\TriClient.cpp(1110)] [csf.jwcpp] [gloox::CTriClient::HandleStreamFeatures] - @XmppSDK: #0, SASL token empty:0
2020-03-31 12:12:54,998 INFO [0x000006c8] [jwcpp\xmppcore\patch\TriClient.cpp(1111)] [csf.jwcpp] [gloox::CTriClient::HandleStreamFeatures] - @XmppSDK: #0, SASL mechanism:
2020-03-31 12:12:54,998 ERROR [0x000006c8] [rwerx\jwcpp\xmppcore\src\client.cpp(192)] [csf.jwcpp] [gloox::Client::handleNormalNode] - @XmppSDK: #0, The server doesn't offer any SASL authentication mechanism that we can support


+++ Resolution +++

The issue turns out that even though OAuth was enabled and the first stage of  obtaining OAuth tokens was successful, expressway-C configuration was stuck on OAuth not been enabled:

 Looking at the xconfiguration API of expressway-C we saw "OAuthLocal:off" This should be on.

 

A reboot of the server fixed the issue: 

*c xConfiguration CollaborationEdge LegacyCred: On

*c xConfiguration CollaborationEdge OAuthLocal: Off

 

 

This is the correct configuration

*c xConfiguration CollaborationEdge LegacyCred: On

*c xConfiguration CollaborationEdge OauthLocal: On

 

Troubleshooting Tips 

 1. Some quick thing to check when having issues, verify the keys on all servers in the cluster

show key authz encryption

show key authz signing

 

2. Refresh servers in Expressway-C to ensure that expressway has the keys to validate access tokens from CUCM

Conclusion:

This was a long one, I guess by now you know I do not do short articles/blogs. I guess the complexities of some of these solutions cant easily be written. OAuth is a great solution, I encourage you deploy it for your customers.

As for my job interview, lets just say that I am still looking for a job. If you know someone or your team needs a good guy like myself. Please reach out to me.

 

 

Comments
Cisco Employee

I haven't even read this yet...all I saw is who wrote this and now I'm super excited.  Grabbing a cup of coffee, this is going to be epic!  Thank you!

Thanks Anthony. Hopefully you enjoy it as much as your coffee.🙂

Beginner

wow...this is interesting  and am confused. you mentioned

OAuth is simply an Authorization protocol defined by RFC 6749. OAuth allows an end user ( like me)  to authorize an application (like Jabber) to gain access to a third party service ( like CUCM) without sharing their credentials with the application.

 

so for example if am trying to access phone services on jabber from cucm, connected to VPN, CuCM is LDAP integrated with no SSO , does it mean i won't have to provide phone service credentials on jabber?

cucm is 12.5

Because you are not using SSO you will still provide user credentials for the first login, but after that as long as your token is valid, you won't need to sign in again

Beginner

ok so i just gave an attempt with my jabber and lab cucm, jabber is on cloud and i defnied the lab cucm under webex administration, i enabled the oauth under enterprise parameter , am connected to jabber softphone but i didn't get a prompt for authorization

 

oauth.JPGtoken.JPG

 

cucm 12.5

OAuth is not supported with Hybrid WebEx messenger which is what you are using

Beginner

that's a shame, any idea if this will be supported or any plans in near future

VIP Advisor

What an epic document @Ayodeji Okanlawon! Super job on this.

Thanks @Roger Kallberg for the compliment, much appreciated

Hall of Fame Master

Great doc, thank you for posting!

Beginner

if Oauth is not supported with Webex messenger, but I recently enabled SSO on one of our CuCM cluster and I can see access token and refresh tokens being issued.

 

2020-05-01 11:36:18,124 DEBUG [http-bio-8443-exec-89] token.TokenV2Manager - TokenV2Manager.createTokens:  Issuing Refresh Token

2020-05-01 11:36:18,124 DEBUG [http-bio-8443-exec-89] token.TokenV2Manager - JWT claims beofre encryption:: {"exp":1590924978,"iss":"6a2d4bd9-3bf6-4bfa-a9f2-9a15c53b6737","typ":"user","tid":"fcae3404-ca38-46c4-b579-10af3f51d361","ctyp":"refresh","ccid":"C1b4b988f3efa1c3fc97d0d0a36f6b97f244b4fafe55e8d9d78774e305bae9ab1"}

2020-05-01 11:36:18,132 DEBUG [http-bio-8443-exec-89] token.TokenV2Manager - SHA256 sum of the refresh token : 12f30557abcfab7b33590aaf824c77518b5739ac1f5c4e73b754642a316c2317

 

Or you saying this is not supported with local and LDAP authentication within CuCM

Beginner

Great post, thanks a lot!

 

Is it possible to use this inside a jabber custom tab? We use the custom tabs to integrate business applications into jabber.

On Windows pc's jabber usually supports "Windows Integrated Authentication" but for other devices like smartphones or Apple devices this doesn't work.

 

Is there a way to use the access token inside the custom tab browser?

Contributor

Hey Ayodeji

Great Document!

How about the interaction of Oauth and Apple Push Notification Service when using an Jabber on apple device?. There since to be not much information on CCO about this.

I do have an idea of how it works...

Alex

@aalejo Good to hear from you.

Oauth does not impact Jabber APPN. APPN provides a mechanism to wake jabber up when its in the foreground in iOS devices. If the clients authorised session needs to be refreshed, then the refresh token already obtained via Oauth is used.

 

@tobias.heeb I am not sure I understand your question. I am also unsure how Oauth impacts on custom tabs in Jabber

Content for Community-Ad