azureoauthskype-for-businessucwa

Skype for Business in Azure UCWA authentication - Issued token not accepted


I am integrating Java application with Skype for Business in Azure using UCWA and here is the list of actions that I performed. When it seemed that everything is working and covered, I am stuck at unexpected place. Probably the solution is something trivial, like adding an addition permission, but I cannot find it. Also, I am sure that this post will help someone who is stuck in earlier stage.

  1. Register application in Azure portal: Register as Native application Add required permissions to all Skype for Business Online Permissions Grant permissions to all users Get the app id (will use it later as client id)

  2. HTTP Get, btw: (tenant) should be replaced with actual tenant name Request:

    curl -X GET \ http://lyncdiscover.(tenant).onmicrosoft.com/ \ -H 'cache-control: no-cache' \ -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ -H 'postman-token: b45b8fee-852f-4678-3631-3a06727d99fc' \ -F Capture=undefined

Response:

`{
    "_links": {
        "self": {
            "href": "https://webdir0a.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=(tenant).onmicrosoft.com"
        },
        "xframe": {
            "href": "https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root/xframe"
        },
        "redirect": {
            "href": "https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=(tenant).onmicrosoft.com"
        }
    }
}`
  1. HTTP Get redirect url

    curl -X GET \ 'https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=(tenant).onmicrosoft.com' \ -H 'cache-control: no-cache' \ -H 'postman-token: 273cad2b-a9a9-9882-8634-b52f9a9976b5'

    { "_links": { "self": { "href": "https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=(tenant).onmicrosoft.com" }, "user": { "href": "https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=(tenant).onmicrosoft.com" }, "xframe": { "href": "https://webdir3a.online.lync.com/Autodiscover/XFrame/XFrame.html" } } }

  2. Get user url

    curl -X GET \ 'https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=(tenant).onmicrosoft.com' \ -H 'cache-control: no-cache' \ -H 'postman-token: af9ab0bd-dc6f-b2f3-e7d9-23941aac5537'

response: 401 Unauthorized Read response http header and extract

`authorization_uri="https://login.windows.net/common/oauth2/authorize"`
  1. Post to authorization url: client+id = app id from azure portal app registration resource=00000004-0000-0ff1-ce00-000000000000 (SfB resource id)

    curl -X POST \ https://login.windows.net/common/oauth2/token \ -H 'cache-control: no-cache' \ -H 'content-type: application/x-www-form-urlencoded;charset=UTF-8' \ -H 'postman-token: 39902b3f-00c3-e7a8-75d0-6b94f10e07ed' \ -d 'resource=00000004-0000-0ff1-ce00-000000000000&client_id=XXXX-XXXX-XXXX&grant_type=password&username=actualUserName@tenant.com&password=actual_password&scope=openid'

response:

`{
    "token_type": "Bearer",
    "scope": "Contacts.ReadWrite Conversations.Initiate Conversations.Receive Meetings.ReadWrite User.ReadWrite",
    "expires_in": "3599",
    "ext_expires_in": "0",
    "expires_on": "1518196708",
    "not_before": "1518192808",
    "resource": "00000004-0000-0ff1-ce00-000000000000",
    "access_token": "eyJ0...",
    "refresh_token": "AQABA...",
    "id_token": "eyJ0e..."
}`

Yes, I am getting actual token and everything seems to be fine, but it is not. When I use this token to get user url again the response now is 403 Forbidden and I am stuck.

`curl -X GET \
  'https://webdir3a.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=(tenant).onmicrosoft.com' \
  -H 'authorization: Bearer eyJ0eXA...' \
  -H 'cache-control: no-cache' \
  -H 'postman-token: ff0a80bd-5025-5b28-3f1c-cf9205890812'`

response: 403 Forbidden

`    <body>
        <div id="header">
            <h1>Server Error</h1>
        </div>
        <div id="content">
            <div class="content-container">
                <fieldset>
                    <h2>403 - Forbidden: Access is denied.</h2>
                    <h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>
                </fieldset>
            </div>
        </div>
    </body>`

Solution

  • The mistake is in step #4, parameter resource. Correct request uses user server url as resource parameter:

    curl -X POST \
      https://login.windows.net/common/oauth2/token \
      -H 'cache-control: no-cache' \
      -H 'content-type: application/x-www-form-urlencoded;charset=UTF-8' \
      -H 'postman-token: 39902b3f-00c3-e7a8-75d0-6b94f10e07ed' \
      -d 'resource=https://webdir3a.online.lync.com&client_id=XXXX-XXXX-XXXX&grant_type=password&username=actualUserName@tenant.com&password=actual_password&scope=openid
    

    and then use received token to get the application url from user url. Once application url is retrieved, a new token request must be posted to get token for application server, in my case that was:

    curl -X POST \
      https://login.windows.net/common/oauth2/token \
      -H 'cache-control: no-cache' \
      -H 'content-type: application/x-www-form-urlencoded;charset=UTF-8' \
      -H 'postman-token: 39902b3f-00c3-e7a8-75d0-6b94f10e07ed' \
      -d 'resource=https://webpoolsn23a14.infra.lync.com&client_id=XXXX-XXXX-XXXX&grant_type=password&username=actualUserName@tenant.com&password=actual_password&scope=openid
    

    This token can finally be used to create an application and other messaging services.