Graph Token

Jeder Zugriff auf die Graph-Schnittstelle, aber auch andere Dienste erfordert ein Zugriffs-Token. Ein anonymer Zugriff ist nicht möglich. Sie müssen sich also mit den Graph Berechtigungen beschäftigen, ehe sie ein Token erhalten können.

Viele Wege zu Ziel

Ihre Applikation braucht ein Token und sendet dazu einen Request an den ausstellenden Token-Server. Bei Office 365 ist dies meist https://login.microsoftonline.com". Aber auch diese Adresse wird eigentlich von dem Service geliefert, auf den Sie zugreifen und dabei verraten, dass Sie "Bearer" unterstützen. Siehe dazu auch OAUTH2 / Modern Authentication und Test-Bearer. Wenn Sie von dem Dienst dann aber den Hinweis zum Token-Service bekommen haben, dann gibt es wieder mehrere Verfahren sich anzumelden.

  • Interaktiv
    Wenn Sie als Anwender eine lokale Software (App) starten oder eine Progressive Web App" einer Webseite nutzen, dann kann die Software Sie nach ihren Anmeldedaten fragen. Natürlich müssen Sie der Applikation vertrauen, die sich dann mit den Daten und ihrer AppID gegen den Token-Server authentifiziert aber das war schon immer so.
    Bei dem Fall kann der Anwender auch selbst seine Zustimmung (Consent) für die Berechtigungen erteilen.
  • Unattended als Applikation
    Im Gegensatz dazu gibt es Prozess, die keine interaktive Oberfläche anbieten können, z.B. wenn eine Application die Berechtigungen nutzt. Eine Applikation kann sich dann alleine mit der AppID und App Credential bzw. Zertifikat anmelden. Allerdings sind nicht alle APIs so erreichbar.
  • Unattended als Applikation
    Sie könnten aber auch eine Software mit einem "Serviceaccount" aufrufen, die sich dann mit diesen Daten anmeldet und die Funktionen nutzt. Interessant sind hier natürlich Zugriffe auf Daten anderer Personen als "Stellvertreter"
  • Device
    Was machen Sie aber mit Geräten, die nur stark reduzierte Eingabemöglichkeiten haben wie z.B. Telefone. Hierfür gibt es den "Device Flow", bei dem Sie auf dem Gerät z.B. eine Durchwahl angeben und das Gerät dann eine URL anzeigt. Als Anwender nutzen Sie dann ihren PC um diese URL anzusurfen und sich dort anzumelden. Das Geräte wartet solange und bekommt nacherfolgreicher Anmeldung dann das Token
  • Weitere Verfahren
    Das ist nur eine Teilmenge und natürlich gibt es noch weitere Optionen wie z.B. Passwordless Login mit dem Smartphone. Fido-Keys etc.

Seitens Microsoft gibt es dazu jede Menge Informationen als Webseite, Blog-Artikel und Video-Material. Auch gibt es entsprechende Libraries für unterschiedliche Einsatzfälle und Programmiersprachen. Diese Seite beschreibt weiter unten den "manuellen Weg", damit sie es an praktischen Beispielen durchspielen können. Hier ein paar Links

Applications permissions and consent
https://www.youtube.com/watch?v=80RdKeeDTss

Was geht mit welchen Anmeldungen?

Achtung: Die Bedeutung "Delegate" bei Graph hat nichts mit "Delegate bei Exchange" zu tun. Bei Exchange handelt es sich um die Rechte eines Stellvertreter im Auftrag des anderen Postfachs zu arbeiten. Bei Graph bedeutet es, dass eine App mit ihren Rechten arbeitet. Die App kann aber nicht eigenständig ohne Interaktion mit den Anwender auf die Daten zugreifen.

Wenn Sie eine Funktion der GraphAPI anschauen, dann finden sie immer eine Tabelle am Anfang, die ihnen die notwendigen Berechtigungen anzeigt. Hier am Beispiel für den Zugriff auf einen AzureAD Benutzer.


https://docs.microsoft.com/en-us/graph/api/user-get

"Delegated" ist dann der Zugriff auf die eigenen Daten, wobei Graph hier zwischen "richtigen" Office 365 Konten und dem privaten "Microsoft Konto", vormals LiveID oder Passport, unterscheidet. Sie sehen aber schon, dass die beiden Plattformen eigentlich nicht getrennt sind. Die Berechtigungen für "Applications" sind auch aufgeführt.

Interessant sind hier auch andere Fälle wie z.B. das Abrufen der Präsenz eines Benutzers:


https://docs.microsoft.com/de-de/graph/api/presence-get?view=graph-rest-1.0&tabs=http

Nur ein Benutzer (oder ein Dienstkonto) kann mit "Presence.Read.All" einen Status abfragen aber eine Applikation kann es niciht. Eine Funktion zum Setzen der eigenen Präsenz ist über Graph noch gar nicht vorhanden. (Stand Juni 2021)

What are App Application Permissions vs Delegated Permissions? | One Dev Question: Hirsch Singhal
https://www.youtube.com/watch?v=6R3W9T01gdE

Getting Started with Microsoft Graph and Consent Permissions
https://www.youtube.com/watch?v=yXYzgWWVdSM

Applications permissions and consent
https://www.youtube.com/watch?v=80RdKeeDTss

Die Umleitung

Ob ein Service eine Anmeldung per Token unterstützt oder nicht, bekommen Sie durch einen anonymen HTTP-Request heraus, der im Header das Feld "Authorization:Bearer" enthält. Der Service kann anhand dieser Information erkennen, dass ihr Client eine Anmeldung per OAUTH unterstützt. Sie können es recht einfach per PowerShell ausprobieren:

param ($url)

$HeaderParams = @{ 'Authorization' = "Bearer" }
$result= Invoke-WebRequest `
            -UseBasicParsing `
            -Headers $HeaderParams `
            -SkipCertificateCheck `
            -SkipHttpErrorCheck `
            -Uri $url 
$result.headers."WWW-Authenticate"

Hier ein paar Beispiele (Stand Juni 2021)

$url WWW-Authenticate
https://graph.microsoft.com/v1.0/me

Bearer realm="", authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", client_id="00000003-0000-0000-c000-000000000000"

https://outlook.office365.com/ews

Bearer client_id="00000002-0000-0ff1-ce00-000000000000", trusted_issuers="00000001-0000-0000-c000-000000000000@*", token_types="app_asserted_user_v1 service_asserted_app_v1", authorization_uri="https://login.windows.net/common/oauth2/authorize"

So erhalten wie zumindest bei Microsoft den OAUTH Server, um ein Token anzufordern. Ich beschränke mich im Weiteren auf Graph und damit https://login.microsoftonline.com/common/oauth2/authorize.

Token direkt anfordern

Die Anforderung eines Tokens über den OAUTH-Server ist in der Regel ein HTTP-POST mit den entsprechenden Parametern. Beim ersten Beispiel besorge ich mir ein Token als Benutzer mit meinen Anmeldedaten und einer definierten App. (Body zur Lesbarkeit umgebrochen.

$LoginUrl="https://login.microsoftonline.com"  # Graph API URLs
$ResourceUrl="https://graph.microsoft.com"     # Ressource API URLs
$AppID="12345678-1234-1234-1234-1234567890ab"
$Appkey="xxxxxx" 
$TenantName="msxfaq.onmicrosoft.com"           # Tenant name

$username="pwdresetter@carius.onmicrosoft.com"   # keine Sorge. den Benutzer gibt es nicht 
$password="SuperGeheimesKennwort"    
 
$authresponse=invoke-restmethod `
                 -method POST `
                 -ContentType "application/x-www-form-urlencoded" `
                 -body "client_id=$($AppID)
                       &scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
                       &client_secret=$($Appkey)
                       &username=$($username)
                       &password=$($password)
                       &grant_type=password" `
                 -uri "$($LoginUrl)/$($tenantName)/oauth2/v2.0/token"

Auch die Anforderung eines Tokens als "Applikation" ist noch einfacher möglich. Das Beispiel zeigt die Authentifizierung einer Applikation mit einem AppSecret. Es gibt auch noch eine Authentifizierung per Zertifikat:

$authresponse=Invoke-RestMethod `
           -body "client_id=$($AppID)
                  &scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
                  &client_secret=$($Appkey)
                  &grant_type=client_credentials
                  &api-version=1.0" `
           -uri "$($LoginUrl)/$($tenantName)/oauth2/v2.0/token"
 
$accesstoken= $authresponse.access_token

Beide Beispiele erwarten, dass eine entsprechende App bereits im Tenant eingetragen wurden, die alle gewünschten Berechtigungen erhalten haben und mit Consent versehen wurde.

Token indirekt anfordern

Die Beispiele sind für mich als Consultant mit PowerShell passend. Aber natürlich gibt es auch Wege, damit eine WebApp ein Ticket anfordern kann. Sie starten also einen Browser und gehen auf eine Webseite, die im wesentlichen eine Progressive Web App als JavaScript herunterlädt. Diese App läuft dann in ihrem Browser und möchte im Hintergrund auf ihre Daten zugreifen. Dazu benötigt diese App natürlich ein Token. Sie könnte dazu in einem Formular ihre Anmeldedaten abfragen und im Hintergrund die den gleichen Request stellen. Aber das ist unsicherer, da Sie einer WebApp ihre Zugangsdaten geben.

Hier ist es denn besser, wenn sie WebApp sie auf die Anmeldeseite des OAUTH-Service verweist, an dem Sie sich dann anmelden. Der Service leitet dann den Browser wieder zurück zur App mit dem Token als Payload. Das geht aber auch per Powershell, wie die Exchange Online V2-Powershell zeigt. Dieser Umweg erlaubt ihnen dann z.B. auch die Anmeldung per MFA oder sogar Single-SignOn.

Ein Beispiel für die Nutzung in PowerShell fehlt hier noch

Token interpretieren

Auf den ersten Blick ist ein Token nur eine Buchstabenwüste aber auf den zweiten Blick sehen Sie, dass es ein BAS64 codierter String ist, den Sie einfach decodieren können. Sie können nicht nur die Identität sondern auch ihre App und die Berechtigungen erkennen.

Allerdings habe ich diese Werte nie weiter untersucht, sondern das Token unverändert in den eigentlichen Anfragen an die Dienste weitergereicht. Ein Decoding habe ich immer nur genutzt, wenn etwas nicht funktioniert hat und ich nachschauen wollte, ob meine App auch wirklich die erforderlichen Berechtigungen erhalten habe.

Dann habe ich aber den Text einfach in einen Webdecoder wie https://jwt.io reingeworfen. Wenn Sie OAUTH nicht selbst per PowerShell steuern sondern eines der verschiedenen Frameworks verwenden, dann gibt es dort in der Regel auch vordefinierte Klassen zur Interaktion

Token Ablauf

Bedenken Sie, dass Tokens ähnlich einem Kerberos-Ticket nur eine bestimmte Laufzeit haben. Wenn ein Token abgelaufen ist, dann müssen Sie es neu anfordern. Sie können das natürlich wieder mit dem gleichen Flow machen, mit dem sie auch erstmalig das Token angefordert haben.

Sie können aber ein Token auch verlängern. Das ist insbesondere dann ratsam, wenn die Anmeldung z.B. durch MFA u.a. abgesichert wurde und sie den Anwender nicht bei der Arbeit unterbrechen wollen. Ihre Software sollte daher einen Timer nutzen, der vor dem Ablauf des Tokens eine Erneuerung vorsieht.

Wenn Sie bestehende Libraries verwenden, dann können diese oft diese Refresh-Funktion übernehmen.

Es kann übrigens auch ein Grund sein, wenn ein PC oder Smartphone auch nachts "wach" wird oder ein paar Bytes überträgt

Weitere Links