UCWA - Unified Communication Web API
Seit Lync 2013 CU1, quasi mit der Verfügbarkeit des "Mobility-Clients" gibt es eine JSON/WebAPI, mit der ein authentifizierter Client allein per HTTP/HTTP die Dienste von Lync nutzen kann. Diese offene API hat nichts mit COM, .NET, Win32API o.ä. zu tun und ist damit auch unabhängig vom Betriebssystem des Clients. Und es gibt mit Arduino, RaspberryPI, Netduino und anderen Plattformen durchaus interessante Clients für Lync, die aber kein SIP sprechen. Ehe diese Clients aber den Status eines Benutzer anzeigen oder vielleicht sogar Kurzmitteilungen senden und empfangen können, gilt es die API zu verstehen. für solche "interaktiven" Dinge ist PowerShell ein passables Werkzeug.
Diese API ist erst ab Lync 2013 verfügbar und wird z.B. von Lync 2013 Mobile intensiv genutzt. Sie steht aber auch jedem Client offen, der Lync Dienste per WebService nutzen möchte. Als Authentifizierung meldet sich der Benutzer selbst an, es ist also kein Zugriff wie UCMA, über den ein privilegierter Prozess auch
Microsoft Quellen
- Lync Developer Roundtable - The Lync API-
Getting Started with UCWA
http://www.youtube.com/watch?v=u1s7pZwIOQU - Lync Developer Roundtable: Getting Started
with UCWA
http://channel9.msdn.com/posts/Lync-Developer-Roundtable-Getting-Started-with-UCWA - Unified Communications Web API Now Available
to Web Developers
http://blogs.technet.com/b/nexthop/archive/2013/03/12/unified-communications-web-api-now-available-to-web-developers.aspx - UCWA - Architecture
http://UCWA.lync.com/documentation/ITAdmin-Architecture - C# Library für UCWA
https://GitHub.com/kenakamu/UCWA2.0-CS
UCWA Helper Files für JavasScript
http://go.microsoft.com/fwlink/?LinkId=313244
UCWA und Office 365
Solange es noch "Skype for Business Online" gegeben hat, konnten Sie UCWA sogar gegen die Cloud nutzen. Mittlerweile ist das aber nicht mehr möglich. Für Microsoft Teams gibt es mit Graph eine passende API
- Graph API
- Skype for Business Web SDK API Reference: Globals jCafe
MePerson Interface MePerson
https://officedev.GitHub.io/skype-docs/Skype/WebSDK/model/api/interfaces/jcafe.meperson.html - How to access the UCWA endpoint für Lync
Online (Office 365)?
http://stackoverflow.com/questions/25093344/how-to-access-the-ucwa-endpoint-for-lync-online-office-365 - Get Your Lync UCWA
Programming Lab up in 5 Minutes
& 3 Easy Steps
http://windowspbx.blogspot.co.uk/2013/09/get-your-lync-UCWA-programming-lab-up.html
Trace einer IPhone Suche
Als es noch wenige Quellen zu UCWA gab und meine ersten Tests nicht funktioniert haben, habe ich einfach mein iPhone mit Fiddler verbunden und die HTTPS-Kommunikation mitgeschnitten. Hier die Suche nach "geheim":
INFO APPLICATION CPersonsAndGroupsSearchQuery.cpp/1323:Remote search started. queryType=0; lookupKeyword=geheim; lookupUri=sip:geheim; lookupEmail=geheim; lookupPhone=434346 INFO TRANSPORT CAuthenticationResolver.cpp/266:Using endpoint address https://lyncweb.netatwork.de/UCWA/v1/applications/213101205102/people/search?query=geheim&limit=20 as the server address INFO TRANSPORT TransportUtilityFunctions.cpp/638: <SentRequest> GET https://lyncweb.netatwork.de/UCWA/v1/applications/213101205102/people/search?query=geheim&limit=20 Request Id: 0x94869a8 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 xxxxxxxxxx </SentRequest> 2013-06-26 11:36:32.894 Lync[17482:7b4d000] INFO TRANSPORT TransportUtilityFunctions.cpp/907:<ReceivedResponse> GET https://lyncweb.netatwork.de/UCWA/v1/applications/213101205102/people/search?query=geheim&limit=20 Request Id: 0x94869a8 HttpHeader:Cache-Control no-cache HttpHeader:Connection Keep-Alive HttpHeader:Content-Length 265 HttpHeader:Content-Type application/vnd.microsoft.com.UCWA+xml; charset=utf-8 HttpHeader:Date Wed, 26 Jun 2013 09:36:31 GMT HttpHeader:Server Microsoft-IIS/8.0 HttpHeader:StatusCode 200 HttpHeader:X-AspNet-Version 4.0.30319 HttpHeader:X-Ms-Namespace internal HttpHeader:X-MS-Server-Fqdn NAWLYNC001.netatwork.de HttpHeader:X-Powered-By ASP.NET <?xml version="1.0" encoding="utf-8"?> <resource rel="search" href="/UCWA/v1/applications/213101205102/people/search?query=geheim&limit=20" xmlns="http://schemas.microsoft.com/rtc/2012/03/UCWA"> <property name="moreResultsAvailable">False</property> </resource> </ReceivedResponse>
- UCWA Adressbuchsuche
http://UCWA.lync.com/documentation/Resources-contact
http://UCWA.lync.com/documentation/Resources-search
http://UCWA.lync.com/documentation/KeyTasks-People-SearchContact
Anmeldung mit PowerShell
Das schöne an PowerShell ist, dass Sie alle Schritte interaktiv selbst durchgehen können. Daher beschreibe ich hier sequentiell die Schritte und sie können jeden Code in der PowerShell Box z.B. über die Zwischenablage direkt ausführen.
Die Anmeldung erfolgt mit folgenden Schritten.
- Zugriff auf Lyncdiscover.<sipdomain>
Der Client bekommt ohne weitere Authentifizierung einen JSON-Datensatz, aus dem uns die User-URI interessiert - Zugriff auf die User-URI
Ein anonymer Zugriff liefert hier einen 401, aber das ist erwartet, denn uns interessiert der "www-authenticate"-Header, in dem die OAuth-URI enthalten ist. - Zugriff auf OAuth-Service
mit Anmeldedaten
Nun besorgen wir uns bei diesem Server mit unseren Anmeldedaten ein OAuth-Token - Anmeldung an UCWA mit OAuth-Token.
Erst dann kann ich mit dem Token die weiteren Aktionendurchführen - weitere Aktionen
Da das alles per HTTPS verschlüsselt ist, ist Fiddler ein ideales Werkzeug um die Anfragen und Antworten zu analysieren. Eine erfolgreiche Verbindung, wie Sie diese gleich selbst per PowerShell aufbauen können, sieht dann in etwas so aus
Sind diese Daten nicht geheim ?
Die meisten nicht, denn wie bei Exchange
Autodiscover
kann über "lyncdiscover.<sipdomain> jeder den
Service finden, einen Request absenden und damit
die Lync Webservice URI erfahren und dann sogar
noch den OAuth-Service erfahren. Um aber ein
Ticket zu erhalten, muss man sich anmelden. DoS
oder DDoS-Attacken sind denkbar.
- Create an Application
http://UCWA.lync.com/documentation/KeyTasks-CreateApplication
Beachten Sie die Einschränkungen von Invoke-Webrequest auf PS HTTPClient, warum ich dann doch wieder die "alte" Klasse genutzt habe
Parameter für die Anmeldung
Zuerst muss das Script natürlich ein paar Parameter bekommen. können. Die habe ich als "param"-Block angegeben, damit man später bei Aufruf des Powershell diese schnell überschreiben kann
param ( [string]$sipaddress = "frank.carius@netatwork.de", [string]$Username = "frank.carius@netatwork.de", [string]$Userpassword = $( Read-Host "Input password für User $sipaddress" ) )
Auf der Seite PS Passworte habe ich verschiedene Optionen beschrieben wie man sicher das Kennwort hinterlegen kann
Eingang per Lyncdiscover ermitteln
Aus den Werten in der Variablen "$sipaddress" kann ich die SIP-Domain ableiten und damit die URL für Lyncdiscover generieren
[string]$sipdomain = $sipaddress.split("@")[1] [string]$lyncdiscoverURL = ("https://lyncdiscover."+$sipdomain) Write-host "LyncdiscoverURL: $lyncdiscoverURL"
Und dann kann ich auch schon den ersten "anonymen" Request absetzen, um die URL der Lync WebDienste zu bekommen: (gekürzt, ohne Fehlerbehandlung und daraus die UserURL holen:
$result1 = Invoke-WebRequest -uri $lyncdiscoverURL -Method GET $jsondata = convertfrom-json $result1.content $UCWAUserURL = $jsondata._links.User.href Write-host "UCWAUserURL: $UCWAUserURL"
Ermitteln der OAUTH-Anmeldung
Die Nutzung von UCWA erfordert natürlich eine Anmeldung. das virtuelle Verzeichnis /OUWA) akzeptiert aber erst mal keine normale Anmeldung, sondern erwarer eine OAUTH.Token. Das bekommt ich mit dem nächsten Zugriff auf gesagt. Fiddler zeigt den GET und den 401. Wichtig ist der "WWW-Authenticate:"-Header in der Antwort.
Das Problem mit PowerShell ist aber, jede HTTP-Methode hier versagt. Auf PS HTTPClient habe ich die verschiedenen Optionen einer HTTP-Anfragen unter PowerShell beschrieben und alle liefern einen 401-Fehler aber keine Header.
- Response Property
https://msdn.microsoft.com/en-us/library/system.net.webexception.response.aspx - WebException Class
https://msdn.microsoft.com/en-us/library/system.net.webexception.aspx
Some Internet protocols, such as HTTP,
return otherwise valid responses indicating that an error
has occurred at the protocol level. When the response to an
Internet request indicates an error, WebRequest..::..GetResponse sets
the Status property to WebExceptionStatus..::..ProtocolError and
provides the WebResponse that contains the error message in
the Response property of the WebException that was thrown.
The application can examine the WebResponse to determine the
actual error.
Quelle Response Property
https://msdn.microsoft.com/en-us/library/system.net.webexception.response.aspx
- InnerException: We have to go deeper.
http://tasteofpowershell.blogspot.de/2011/10/innerexception-we-have-to-go-deeper.html - Exceptions and Error Handling
(PowerShell)
https://vwiki.co.uk/Exceptions_and_Error_Handling_(PowerShell)
Daher ist der nächste Aufruf etwas aufwändiger:
Try { $result2 = Invoke-WebRequest ` -uri $UCWAUserURL ` -Method GET ` } Catch [System.Net.WebException] { Write-host " Got a expected Web Exception $result2 = $_.Exception } if (( $result2.Response.StatusCode -eq 401) ` -and ($result2.Response.Headers["WWW-Authenticate"] -ne $null )) { [string]$oauthURL = (($result2.Response.headers['WWW-Authenticate'] -split '.*MsRtcOAuth\shref="(.*?)".*')) $oauthURL=$oauthURL.trim() # remove spaces } write-host " OAuthURL = $oauthURL"
Damit sollte ich nun aber eine gültige OAUTH-UR- erhalten haben. Viele anderen Beispiele für UCWA sparen sich den Schritt und erraten die URL einfach aus den Hostnamen im vorherigen Request.
Form-POST für WebTicket
unter der ich mir im nächsten Schritt ein WebTicket besorgen kann., was ich umgehend tue. Hier muss ich nun quasi ein "Formular"-POST machen.
$jsonrequest = @{grant_type = "password";Username = $Username;password = $Userpass;} $result3 = Invoke-WebRequest ` -uri $oauthURL ` -Method POST ` -Body $jsonrequest $jsondata3 = convertfrom-json $result3.content write-host ("Got token:" + $jsondata3.access_token) write-host ("Got token:" + $jsondata3.token_type) PS C:\> $jsondata3 access_token expires_in ms_rtc_identityscope token_type ------------ ---------- -------------------- ---------- cwt=AAEBHAEFAAAA... 28356 local Bearer
Hier wieder die Ansicht in Fiddler:
Sind diese Daten nicht geheim ?
Sie sehen, dass ich das Kennwort natürlich unkenntlich gemacht habe. Sie wissen aber nun
auch, dass HTTPS keine Kür sondern Pflicht ist.
Das "access_token" für einen authentifizierten
Benutzer selbst ist aber nur acht (8) Stunden
gültig. Tokens für anonyme Meetings sind sogar
nur eine (1) Stunde gültig. Der Client muss sich
selbst darum kümmern das Token zu erneuern.
Quelle: Authentication in UCWA
http://msdn.microsoft.com/en-us/library/office/dn356686(v=office.15).aspx
Das Ergebnis ist dann ein OAuth-Token, was mich für die nächste Zeit authentifiziert.
Das Token sollte ich mit lokal speicherm, wenn die Applikation z.B. angehalten oder beendet wird. Solange es gültig ist, kann die Applikation damit immer wieder die Verbindung fortsetzen und auch der Server "erkennt" die Applikation wieder und nutzt den bestehenden Status. Das ist insbesondere für eingehende Nachrichten erforderlich, die per UCWA vom Server gepuffert aber nur an die gleiche Session ausgeleifert werden.
Die Applikation sollte sich aber auch merken, wann Sie das Token angefordert hat und ablaufende Tokens erneuern bzw. nach dem Ablaufen wieder eine Anmeldung zu wiederholen.
Ermitteln der Application URI
Mit diesem Token werde ich nun erst noch mal die User-Uri ansprechen, denn noch habe ich ja keine Informationen über den Anwender und dessen Anwendungen: Zudem kann ich so schon mal sehen, ob das Token funktioniert.
$UCWAauth = @{Authorization = ($jsondata3.token_type+" "+$jsondata3.access_token);} Try { $result4 = Invoke-WebRequest ` -uri $UCWAUserURL ` -Method GET ` -headers $UCWAauth $httperrorcode = $result4.Statuscode } Catch [System.Net.WebException]{ [System.Net.HttpWebResponse]$result4 = [System.Net.HttpWebResponse] $_.Exception.Response $httperrorcode = $result4.StatusCode.Value__ $error.clear() }
In Fiddler ist im Header die Authentication zu sehen.
Die Ausgabe von $result4.content enthält den JSON-String, die man mit "convertfrom-json" konvertieren kann.
$jsondata4 = convertfrom-json $result4.content [string]$UCMAAppsURL=$jsondata4._links.applications.href write-host "UCMAAppsURL = $UCMAAppsURL"
Liste der Applikationen ermitteln
Erst jetzt kann ich mit dieser URL dann die nächste Anfragen stellen, um die komplette Liste der Dienste zu erhalten. Diesmal nutze ich die "Applications"-URI und wieder das bereits erhaltene OAuth-Token im Header.
$UCWAauth = @{Authorization = ($jsondata3.token_type+" "+$jsondata3.access_token);} $jsonrequest5 = convertto-json @{'culture'='en-us';'endpointId'='1235637';'UserAgent'='MSXFAQ UCMA-PSSample';} Try { $result5 = Invoke-WebRequest ` -uri $UCMAAppsURL ` -Method POST ` -headers $UCWAauth ` -ContentType "application/json" ` -body $jsonrequest5 $httperrorcode = $result5.Statuscode } Catch [System.Net.WebException]{ [System.Net.HttpWebResponse]$result5 = [System.Net.HttpWebResponse] $_.Exception.Response $httperrorcode = $result5.StatusCode.Value__ $error.clear() }
Nun bin ich sicher, dass ich quasi "authentifiziert" bin und auf die Daten zugreifen kann. Sie sehen schon hier unter "JSON._embedded.me" meine eigene Information, d.h. Name, SIP-Adresse, Mailadresse etc. Weiter unten unter "people" finden Sie dann die URLs um per REST z.B. meine Kontakte abzurufen.
Wichtiger Hinweis
Die URLs hier sind "relative" URLs, in denen
kein Hostname mehr enthalten ist.
Meine Kontakte auslesen
Zuerst sollten wir erst mal nur "lesend" über UCWA zugreifen. Also ist die erste Übung meine Kontakte auszulesen. Auch hierzu setze ich nun einen REST-Request auf die gelieferte URL ab. Ich muss natürlich zu jedem Request auch immer wieder das Authentifizierungstoken mit senden.
- Receive an Incoming IM Call
https://ucwa.skype.com/documentation/KeyTasks-Communication-IncomingIMCall
Samples
http://go.microsoft.com/fwlink/?LinkId=313244
- Send an IM with UCWA
An introduction to Sending An IM With UCWA
http://matthewproctor.com/Send-An-IM-With-UCWA-Introduction/
Part 1 Prerequisites
http://matthewproctor.com/Send-An-IM-With-UCWA-Prerequisites/
Part 2 Creating the Application
http://matthewproctor.com/Send-An-IM-With-UCWA-Creating-the-Application/
Part 3 Sending the IM
http://matthewproctor.com/Send-An-IM-With-UCWA-Sending-the-IM/
Part 4 Setting Presence
http://matthewproctor.com/Send-An-IM-With-UCWA-Setting-Presence/
Part 5 Hints, Tips & Extra Goodies
http://matthewproctor.com/Send-An-IM-With-UCWA-Hits-and-Tips/ - UCWA Sample Project – Online Chat Example
https://blog.thoughtstuff.co.uk/2015/04/ucwa-sample-project-online-chat-example/
Weitere Links
- Windows Phone Series – Using UCWA to connect
to Lync Server
http://www.rahulpnath.com/blog/windows-phone-series-using-ucwa-to-connect-to-lync-server/ - Lync Development
- http://UCWA.lync.com/
- UCWA -
Building Services für Any Client with ASP.NET
Web API
http://channel9.msdn.com/Events/Build/2012/3-036 - UCWA Overview
http://channel9.msdn.com/posts/Lync-Developer-Roundtable-UCWA-Overview - Unified Communications Web
API Now Available to Web
Developers
http://blogs.technet.com/b/nexthop/archive/2013/03/12/unified-communications-web-api-now-available-to-web-developers.aspx - Lync 2013 training videos on UCWA
http://msdn.microsoft.com/en-us/lync/jj543530 - Lync Server 2013 and UCWA
http://windowspbx.blogspot.com/2012/07/UCWA-api-in-lync-server-2013-opens.html - UCWA – Unified Communications Web-pal
http://blogs.claritycon.com/ucpractice/2012/11/28/UCWA-unified-communications-web-pal/ - UCWA API in Lync Server 2013
Opens Ability to Have Lync
Functionality in Any Device or
Application Without Lync Client
Installed
http://windowspbx.blogspot.de/2012/07/UCWA-api-in-lync-server-2013-opens.html - UCWA 1.0 general reference >
What is this API?
http://msdn.microsoft.com/en-us/library/office/dn323670.aspx - Introducing the Unified Communications Web API (UCWA)
http://mohamedasakr.wordpress.com/2012/12/06/introducing-the-unified-communications-web-api-UCWA/ - Documentation für the Unified Communications Web API
(UCWA)
http://UCWA.lync.com/documentation/what-is-lync-UCWA-api.
fully interactive demo and sandbox http://UCWA.lync.com - Use PowerShell to Convert to
or from JSON
http://blogs.technet.com/b/heyscriptingguy/archive/2012/10/08/use-PowerShell-to-convert-to-or-from-json.aspx - ConvertFrom-Json
http://technet.microsoft.com/en-us/library/hh849898.aspx - ConvertTo-Json
http://technet.microsoft.com/en-us/library/hh849922.aspx - Using PowerShell to Query
Web Site Information
http://learn-PowerShell.net/2011/02/11/using-PowerShell-to-query-web-site-information/ - http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/15/simplify-your-PowerShell-script-with-parameter-validation.aspx
- http://blogs.technet.com/b/heyscriptingguy/archive/2010/03/11/hey-scripting-guy-march-11-2010.aspx
- Hey, Scripting Guy! How Can I use Try/Catch/Finally in Windows PowerShell?
- PowerShell v3.0:
Invoke-WebRequest
http://psscripts.blogspot.de/2012/09/PowerShell-v30-invoke-webrequest.html - Invoke-WebRequest
http://technet.microsoft.com/en-us/library/hh849901.aspx - InvokeRestMethod für the
Rest of us
http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/21/invokerestmethod-for-the-rest-of-us.aspx - UCWA by the numbers
#2 Authentication http://blogs.claritycon.com/ucpractice/2013/04/19/UCWA-numbers-2-authentication-2/
#3 Communication http://blogs.claritycon.com/ucpractice/2013/05/14/UCWA-numbers-3-communication/ - GitHub:
msmorul / lync-sample1.py
https://gist.GitHub.com/msmorul/7902330 - Querying Skype for Business
Online using UCWA and PowerShell
https://blog.kloud.com.au/2016/09/07/querying-skype-for-business-online-using-ucwa-and-powershell/ - Send Skype For Business
(Lync) IMs via Powershell
https://www.angryadmin.co.uk/?p=865 - Send an IM with UCWA - Step
1 - Prerequisites
https://www.matthewproctor.com/Send-An-IM-With-UCWA-Prerequisites/ - An introduction to Sending
an IM with UCWA
https://www.codeproject.com/articles/871653/an-introduction-to-sending-an-im-with-ucwa - Lync UCWA App – E-mail Alert
Based Upon Presence
https://ucryan.com/2014/11/15/lync-ucwa-app-e-mail-alert-based-upon-presence/ - aJson is an Arduino library
to enable JSON processing with
Arduino
https://GitHub.com/interactive-matter/aJson