SfB und IOS-Push

Schon länger gibt es den Skype for Business Client für Apple Mobiltelefone. Aber bis Ende 2016 war es immer erforderlich, dass die App auch aktiv war, um Meldungen zu empfangen, obwohl es von Apple auch einen "Push-Service" gibt. Im Januar 2017 ist mir aufgefallen. dass mein Office 365 Tenant mittlerweile "Push" unterstützt während mein On-Premise-Account noch pollen muss. Das habe ich untersucht.

Update: Am 13. Feb 2017 wurde das CU4HF1 released, welches IOS Push auch On Premise aktiviert

Ansicht auf dem Client

Laut der Anleitung "Mobile client comparison tables for Skype for Business" auf https://technet.microsoft.com/en-us/library/dn951412.aspx unterstützen alle mobilen Clients die "Push-Benachrichtigung, damit der Skype for Business Client eben nicht permanent im Hintergrund aktiv bleiben muss. Das kostet Batterielaufzeit und wenn der Anwender den Client beendet, kommen keine Anrufe mehr an.

Ich nutze ein IPhone 5se mit IOS 10.2 und darauf installiertem Skype for Business Client 6.11.1.310. Je nachdem mit welcher SIP-Adresse ich angemeldet bin, sehe ich auf dem Client folgende Information. Um es Spammern nicht allzu leicht zu machen, habe ich die SIP-Adressen verändert.

User User1onprem@netatwork.de User2o365@netatwork.de

Backend

Skype for Business 2015 On-Premise

Skype for Business Online (EU Tenant)

Ausgabe

Da war es dann mal an der Zeit hinter die Kulissen zu schauen. Auf der On-Premise Umgebung hätte ich mit diversen Diagnose-Tools noch direkt nachschauen können aber in Skype for Business Online geht das nicht. Also könnte ich immer noch einen Fiddler zwischen den Client und das Backend schalten. Zum Glück ist aber auch das Logging des IOS Client  sehr ausführlich, so dass ich diese Log-Dateien einfach zur Analyse herangezogen habe.

Trace einer Office 365 Verbindung

Zuerst die relevanten HTTP-Requests und Antworten einer Anmeldung an Office 365. Sie können schon an dem Hostnamen in der URL erkennen, auf welchem Pool der Benutzer liegt. Alles beginnt damit, dass der Client nach der Anmeldung eine Liste der Applikationen über UCWA anfordert und als Antwort eine Liste der verfügbaren Dienste bekommt.

<ReceivedResponse>
POST https://webpoolbl20a20.infra.lync.com/ucwa/v1/applications
liefert URL zu Pushspp
?<?xml version="1.0" encoding="utf-8"?>
<resource rel="application" href="/ucwa/v1/applications/<sessionid>" xmlns="http://schemas.microsoft.com/rtc/2012/03/ucwa">
<link rel="policies" href="/ucwa/v1/applications/<sessionid>/policies" />
<link rel="batch" href="/ucwa/v1/applications/<sessionid>/batch" />
<link rel="events" href="/ucwa/v1/applications/<sessionid>/events?ack=1&amp;key=xxxxxx-<sessionid>-xxxx%3D%3D" />
<link rel="sendClientErrorReport" href="/ucwa/v1/applications/<sessionid>/clientErrorReport" />
<link rel="pushNotificationSubscription" href="/ucwa/v1/applications/<sessionid>/pushNotificationSubscription" />
<property name="culture">de-DE</property>
<property name="userAgent">iPhoneLync/6.11.310.0000 (iPhone iOS 10.2)</property>
...
</resource>
</ReceivedResponse>

Dieser Service bietet zumindest schon einmal pushNotificationSubscription an. Kurz darauf sehen wir dann auch schon den Request an diese Application

GET https://webpoolbl20a20.infra.lync.com/ucwa/v1/applications/1111111/pushNotificationSubscription
Request Id: 0x10b1080a0
HttpHeader:Accept application/vnd.microsoft.com.ucwa+xml
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml
HttpHeader:X-MS-Namespace internal
HttpHeader:X-MS-WebTicket XXXXXXX
</SentRequest>

Als Antwort kommt folgendes zurück.

2017-01-10 17:31:54.378 SfB[12236:16e187000] INFO TRANSPORT TransportUtilityFunctions.cpp:1102 <ReceivedResponse>
PUT https://webpoolbl20a20.infra.lync.com/ucwa/v1/applications/1111111/pushNotificationSubscription
Request Id: 0x10b1316f0
HttpHeader:Cache-Control no-cache
HttpHeader:Content-Length 1009
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml; charset=utf-8
HttpHeader:Date Tue, 10 Jan 2017 17:31:53 GMT
HttpHeader:Etag "2233225289"
HttpHeader:Location https://webpoolbl20a20.infra.lync.com:4443/ucwa/v1/applications/1111111/pushNotificationSubscription
HttpHeader:StatusCode 200
HttpHeader:Via 1.1 BL20A20FES06.infra.lync.com RtcExt
HttpHeader:x-ms-client-request-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
HttpHeader:X-MS-ClientDiagnostics xxxxx=
HttpHeader:X-MS-Correlation-Id 2147486270, 2147486107
HttpHeader:X-Ms-Namespace internal
HttpHeader:X-MS-Server-Fqdn BL20A20FES08.infra.lync.com

?<?xml version="1.0" encoding="utf-8"?>
  <resource rel="pushNotificationSubscription" href="/ucwa/v1/applications/1111111/pushNotificationSubscription" xmlns="http://schemas.microsoft.com/rtc/2012/03/ucwa">
    <property name="service">ApnsVoip</property>
    <property name="serviceKey">/xxxx/xxxx=</property>
    <propertyList name="eventTriggers">
       <item>InstantMessage</item>
       <item>Invite</item>
       <item>LobbyChange</item>
       <item>MeetingInvite</item>
       <item>MissedItemChange</item>
       <item>ModalityChange</item>
       <item>Voicemail</item>
    </propertyList>
    <property name="lastUpdated">2017-01-10T17:31:54.2045746Z</property>
    <property name="pnchApplicationId">com.microsoft.lync2013.iphone</property>
    <property name="tileFormat">Iconic</property>
    <property name="pushNotificationMode">PnhMode</property>
    <property name="templateKey">sfb.ios_6.6</property>
    <property name="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx">please pass this in a PUT request</property>
    <property name="etag">2233225289</property>
</resource>
</ReceivedResponse>

Der WebService informiert den Client über die verschiedenen Events, für die er eine Push-Benachrichtigung unterstützt. Nun ist es wieder am Client sich für eben diese Events zu registieren. Der nächste Request zeigt dies:

<SentRequest>
PUT https://webpoolbl20a20.infra.lync.com/ucwa/v1/applications/1111111/pushNotificationSubscription
Request Id: 0x10b1316f0
HttpHeader:Accept application/vnd.microsoft.com.ucwa+xml
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml
HttpHeader:If-Match "2487091113"
HttpHeader:X-MS-Namespace internal
HttpHeader:X-MS-WebTicket XXXXXXX
<input xmlns="http://schemas.microsoft.com/rtc/2012/03/ucwa">
<property name="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx">please pass this in a PUT request</property>
<property name="etag">2487091113</property>
<propertyList name="eventTriggers">
<item>InstantMessage</item>
<item>Invite</item>
<item>LobbyChange</item>
<item>MeetingInvite</item>
<item>MissedItemChange</item>
<item>ModalityChange</item>
<item>Voicemail</item>
</propertyList>
<property name="lastUpdated">0001-01-01T00:00:00.0000000</property>
<property name="pnchApplicationId">com.microsoft.lync2013.iphone</property>
<property name="pushNotificationMode">PnhMode</property>
<property name="service">ApnsVoip</property>
<property name="serviceKey">/xxxx/xxxx=</property>
<property name="templateKey">sfb.ios_6.6</property>
<property name="tileFormat">Iconic</property>
</input>
</SentRequest>

Der WebService muss diese Anforderung natürlich bestätigen. Das sieht dann so aus,

2017-01-10 17:31:54.378 SfB[12236:16e187000] INFO TRANSPORT TransportUtilityFunctions.cpp:1102 <ReceivedResponse>
PUT https://webpoolbl20a20.infra.lync.com/ucwa/v1/applications/1111111/pushNotificationSubscription
Request Id: 0x10b1316f0
HttpHeader:Cache-Control no-cache
HttpHeader:Content-Length 1009
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml; charset=utf-8
HttpHeader:Date Tue, 10 Jan 2017 17:31:53 GMT
HttpHeader:Etag "2233225289"
HttpHeader:Location https://webpoolbl20a20.infra.lync.com:4443/ucwa/v1/applications/1111111/pushNotificationSubscription
HttpHeader:StatusCode 200
HttpHeader:Via 1.1 BL20A20FES06.infra.lync.com RtcExt
HttpHeader:x-ms-client-request-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
HttpHeader:X-MS-ClientDiagnostics T3BlcmF0aW9uQ29udGV4dC0=
HttpHeader:X-MS-Correlation-Id 2147486270, 2147486107
HttpHeader:X-Ms-Namespace internal
HttpHeader:X-MS-Server-Fqdn BL20A20FES08.infra.lync.com

?<?xml version="1.0" encoding="utf-8"?>
  <resource rel="pushNotificationSubscription" href="/ucwa/v1/applications/1111111/pushNotificationSubscription" xmlns="http://schemas.microsoft.com/rtc/2012/03/ucwa">
  <property name="service">ApnsVoip</property>
  <property name="serviceKey">/xxxx/xxxx=</property>
  <propertyList name="eventTriggers">
    <item>InstantMessage</item><item>Invite</item>
    <item>LobbyChange</item>
    <item>MeetingInvite</item>
    <item>MissedItemChange</item>
    <item>ModalityChange</item>
    <item>Voicemail</item>
  </propertyList>
  <property name="lastUpdated">2017-01-10T17:31:54.2045746Z</property>
  <property name="pnchApplicationId">com.microsoft.lync2013.iphone</property>
  <property name="tileFormat">Iconic</property>
  <property name="pushNotificationMode">PnhMode</property>
  <property name="templateKey">sfb.ios_6.6</property>
  <property name="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx">please pass this in a PUT request</property>
  <property name="etag">2233225289</property></resource>
</ReceivedResponse>

Soweit ist dieser Ablauf selbst ohne jegliche Dokumentation sehr gut zu verstehen. Die eigentliche "Push"-Meldung erfolgt dann nicht über UCWA sondern über das Apple Push-Netzwerk. Das Telefon bekommt die Info über eine Änderung und weckt die Applikation auf oder kann die Meldung anzeigen, damit der Anwender die Applikation starten kann.

Sollte bei ihnen die Funktion mit einem Office 365 Konto dennoch nicht möglich sein, dann hat ein Administrator dies vielleicht abgeschaltet:

Trace einer On-Premise Verbindung

Die Anmeldung mit dem zweiten Konto hat natürlich ergeben, dass Push nicht möglich ist. Also muss sich die Verbindung unterscheiden. Die ersten Pakete sind noch dahingehen identisch, dass der Client wieder per UCWA nach den verfügbaren Applikationen fragt und heute auch schon von einem Skype for Business On-Premise Server. Natürlich sendet der Client die gleiche Anfrage an die Applikation

<SentRequest>
GET https://lync-web.netatwork.de/ucwa/v1/applications/213346597943/pushNotificationSubscription
Request Id: 0x10e4641e0
HttpHeader:Accept application/vnd.microsoft.com.ucwa+xml
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml
HttpHeader:X-MS-Namespace internal
HttpHeader:X-MS-WebTicket XXXXXXX
</SentRequest>

Allerdings unterscheidet sich die Antwort fundamental. Der HTTP-Code ist natürlich ein 200OK aber die XML-Antwort enthält nur eine leere "eventTriggers"-Liste

<ReceivedResponse>
GET https://lync-web.netatwork.de/ucwa/v1/applications/11111/pushNotificationSubscription
Request Id: 0x10e4641e0
HttpHeader:Cache-Control no-cache
HttpHeader:client-request-id b5030356-ec54-47ee-82a8-bf5b7c871ac5
HttpHeader:Connection Keep-Alive
HttpHeader:Content-Length 554
HttpHeader:Content-Type application/vnd.microsoft.com.ucwa+xml; charset=utf-8
HttpHeader:Date Tue, 10 Jan 2017 17:40:09 GMT
HttpHeader:Etag "2730206693"
HttpHeader:Keep-Alive timeout=15, max=98
HttpHeader:Server Apache
HttpHeader:StatusCode 200
HttpHeader:Strict-Transport-Security max-age=31536000; includeSubDomains
HttpHeader:Vary Accept-Encoding
HttpHeader:X-MS-Correlation-Id 2147524080
HttpHeader:X-Ms-Namespace internal
HttpHeader:X-MS-Server-Fqdn NAWLYNC002.netatwork.de

?<?xml version="1.0" encoding="utf-8"?>
  <resource rel="pushNotificationSubscription" href="/ucwa/v1/applications/111111/pushNotificationSubscription" xmlns="http://schemas.microsoft.com/rtc/2012/03/ucwa">
  <property name="service">Mpns</property>
  <propertyList name="eventTriggers" />
  <property name="lastUpdated">0001-01-01T00:00:00.0000000</property>
  <property name="tileFormat">Standard</property>
  <property name="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx">please pass this in a PUT request</property>
  <property name="etag">2730206693</property>
  </resource>
</ReceivedResponse>

Der Service ist "Mpns" statt "ApnsVoip" und die Liste der "eventTriggers" ist leer. Der Client kann also keinen Event zur Registrierung senden. Solange die Antwort so aussieht, ist Push für diesen Benutzer nicht möglich.

Auch für die Push-Notifications "On-Premise" bemüht der Skype for Business Server die Cloud. Microsoft Dienst als Relay zu Apple. Insofern ist es zwingend erforderlich einen Edge-Server installiert und die erforderliche Konfiguration vorgenommen zu haben. Dazu zählt die Federation zu push.lync.com und natürlich die Aktivierung der Funktion über die entsprechende Policy fpr die Benutzer

Weitere Links