Praxiswissen: Micronaut Integration mit Zoom (Authentifizierung)
Nachdem im Beitrag Integration von Online-Event-Systemen in die IT-Landschaft von Unternehmen die generelle Bedeutung der Thematik vorgestellt wurde, geht dieser Artikel auf technische Aspekte der Integration am Beispiel der Meeting-Plattform Zoom ein. Hierbei wird zunächst die Authentifizierung und Autorisierung zwischen Zoom und der Zugriffs-Plattform beleuchtet. Die Integration wird mit dem Framework Micronaut illustriert, das auf der Java-Plattform aufbaut.
Zoom bietet für den Zugriff eine REST Schnittstelle an, die über HTTP/HTTPS genutzt werden kann.
Für die Nutzung der REST-Endpunkte ist eine Authentifizierung notwendig, wobei es hierfür zwei Möglichkeiten gibt:
- JWT (JSON Web Token)
- OAuth 2.0
Welches der beiden Verfahren genutzt wird, hängt von mehreren Faktoren ab.
Ein Aspekt sind die Berechtigungen des Accounts. Die Authentifizierung über JWT kann nicht mit jedem Account eingerichtet werden und steht nicht immer zur Verfügung. Generell werden zur Einrichtung und Nutzung der JWT-Authentifzierung Administrationsrechte benötigt.
Ein anderer Aspekt, der bei der Nutzung von JWT bedacht werden muss, ist der voll umfassende Zugriff auf die Zoom-API ohne Einschränkungen. Erfolgt in einem größeren Unternehmen bspw. die Integration von einigen ZOOM-Endpunkten in ein Drittsystem, dann hat das Drittsystem bzw. die Entwickler des Drittsystems über JWT auch Zugriff auf Funktionalitäten, die sie ggf. nicht nutzen sollten. Hierzu können bspw. das Löschen von Benutzer-Accounts gehören. Bei der Nutzung eines OAuth Accounts können Berechtigungen definiert werden und damit entsprechende Einschränkungen der verfügbaren Endpunkte.
Einige Funktionalitäten, wie das Abrufen von Teilnehmer-Statistiken, stehen über OAuth gar nicht zur Verfügung und in diesen Fällen muss JWT genutzt werden.
Bei den hier vorgestellten Szenarien gehen wir von einer Serveranwendung aus, die den Zugriff auf Zoom realisiert. Dies bedeutet, dass die Authentifizierung automatisiert ohne Benutzereingriff erfolgt. Die Schnittstelle zu Zoom wird zum einen für stündliche Batch-Zugriffe sowie für direkte Zugriffe durch den Endanwender eingesetzt.
Authentifzierung über JWT
Die JWT-Token Authentizfierung muss zunächst über einen Admin-Account auf dem Zoom Marketplace freigeschaltet werden. Beim Einrichten können einige Zusatz-Informationen hinterlegt werden, wichtig für die Nutzung ist der in der nachfolgenden Abbildung gezeigte Reiter "App Credentials".
Der dort generierte API Key und API Secret werden für die Generierung des JWT-Tokens durch das Drittsystem benötigt.
Die folgende Methode illustriert die Generierung des JWT-Tokens anhand der übergebenen "App Credentials". Die Gültigkeitsdauer fließt entsprechend in die Token-Generierung ein.
String getTokenJWT(String clientId, String clientSecret) {
JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256).type(JOSEObjectType.JWT).build()
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
.expirationTime(Date.from(Instant.now().plus(Constants.JWT_TOKEN_VALIDITY, ChronoUnit.SECONDS)))
.issuer(clientId)
.build()
SignedJWT jwt = new SignedJWT(header, claimsSet)
jwt.sign(new MACSigner(clientSecret.bytes))
String token = jwt.serialize()
return token
}
Das generierte Token wird jedem Zugriff auf einen Zoom-Endpunkt im Header mit übergeben. Mit Micronaut wird bspw. ein POST-Request folgendermaßen initialisiert:
HttpRequest request = POST(uri, registrant)
request.bearerAuth(accessToken)
Authentifzierung über OAuth2
Wird OAuth2 genutzt, dann gestaltet sich die Token-Erstellung und die Aktualisierung etwas komplizierter. Zunächst wird wie bei JWT über den Marketplace ein Zugriff eingerichtet. Im Unterschied zu JWT können für OAuth2 mehrere sogenannte Apps eingerichtet werden. Bei der Nutzung einer Serverapplikation für den Zoom-Zugriff, wie in unserem Fall, kann so für verschiedene Umgebungen (Produktion, Abnahme, Test, ...) jeweils ein Zugriff generiert werden.
Bei OAuth2 wird mit der Client ID und dem Client Secret, wie in der nachfolgenden Abbildung gezeigt, ebenfalls ein Schlüsselpaar erstellt. Im Unter-Dialog Scopes werden entsprechende Rechte für den Zugriff definiert. Hier sollten selbstverständlich nur die relevanten Zugriffe für Drittapplikationen freigeschaltet werden.
OAuth2 nutzt verschiedene Genehmigungsprozesse (Grant Types), um unterschiedliche Anwendungsfälle abzudecken. Für den Zugriff auf Zoom über eine Server-Applikation ohne Benutzer-Interaktion eignen sich die beiden Typen "password credentials" und "client credentials". Leider stehen diese beiden Typen für die Zoom-Endpunkte nicht zur Verfügung.
Für die Zoom API steht aber der Typ "refresh_token" zur Verfügung, der wie der Name schon vorhersagt, für ein übergebenes Token ein neues Token ausstellt, das anschließend genutzt werden kann.
Wie funktioniert dieser Prozess im Detail?
Zunächst muss ein erstes Refresh-Token erstellt werden. Dies kann bspw. manuell über Curl-Befehle durch Aufrufe der Zoom Api erfolgen.
Die Dritt-Applikation muss schließlich eine Zugriffsschnittstelle implementieren für die fortlaufende Generierung der Refresh-Token.
Mit dem folgenden Befehl wird anhand des bisherigen Refresh-Tokens ein neues generiert sowie ein Zugriff-Token zurückgegeben:
POST https://zoom.us/oauth/token?grant_type=refresh_token&refresh_token=ab...74qZAfA
Request Headers
"Authorization": "Basic AxxpxxxxxxxxxxxxsaWVudF9TZWNyZXQ=" <-- Base64 Encodierung von "Client_ID:Client_Secret"
Spätestens wenn ein Zugriffs-Token abgelaufen ist, muss über das vorhandene Refresh-Token ein neuer Token generiert werden. Hierbei ist wichtig zu wissen, dass ein Refresh-Token nur für einen Zugriff gültig ist.
Wird Micronaut mit groovy genutzt, kann diese Funktionalität, wie nachfolgend dargestellt, einfach und schnell implementiert werden.
AuthenticationResult getRefreshTokenOAuth(String refreshToken, String clientId, String clientSecret) {
String uri = UriTemplate.of("/oauth/token?grant_type=refresh_token&refresh_token=${refreshToken}")
Map body = [:]
HttpRequest request = POST(uri, body)
request.basicAuth(clientId, clientSecret)
AuthenticationResult result = httpClientAuth.toBlocking().retrieve(request, Argument.of(AuthenticationResult))
return result
}
Da das Zugriffs-Token und das Refresh-Token sich ständig ändern, sollten diese in einer Datenbank-Tabelle abgelegt werden.
Ein Nachteil bei der Nutzung dieses Mechanismus ist die Notwendigkeit des manuellen Eingreifens, wenn das Refresh-Token aufgrund von Fehlern seine Gültigkeit verliert. In diesem Fall muss auf dem Zoom-Marketplace die App neu veröffentlicht werden und wieder ein neues "erstes" Refresh-Token erzeugt werden.
Welche Authentifizierungs-Methode sollte genutzt werden?
Die Nutzung von Zoom-Endpunkten über JWT ist einfacher und stabiler. Steht JWT zur Verfügung, sollte generell dieses Verfahren eingesetzt werden. Problematisch bei der Vewendung von JWT ist die Sicherheit. Zum einen gibt es pro Account nur eine JWT-Authentifizierungskombination für alle Dritt-Applikationen und zum anderen kann der JWT-Zugriff nicht über Berechtigungen eingeschränkt werden. Unter Berücksichtigung der Sicherheitsaspekte kann es also durchaus ratsam sein, OAuth2 zu nutzen.
Die Zoom API wird ständig erweitert, so dass durchaus auch im Bereich der beiden Verfahren noch Anpassungen und Verbesserungen zu erwarten sind.