ZoomMeetingSDKJWT.swift 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import CryptoKit
  2. import Foundation
  3. enum ZoomMeetingSDKJWTError: Error {
  4. case invalidUTF8
  5. case jsonSerializationFailed
  6. }
  7. /// Builds a [Meeting SDK JWT](https://developers.zoom.us/docs/meeting-sdk/auth/) from the OAuth client id/secret
  8. /// (same credentials as the in-app Zoom OAuth app when Meeting SDK is enabled on that app).
  9. enum ZoomMeetingSDKJWT {
  10. static func makeMeetingSDKToken(clientId: String, clientSecret: String) throws -> String {
  11. let header: [String: String] = ["alg": "HS256", "typ": "JWT"]
  12. let iat = Int(Date().timeIntervalSince1970) - 30
  13. let exp = iat + 60 * 60 * 2
  14. let payload: [String: Any] = [
  15. "appKey": clientId,
  16. "iat": iat,
  17. "exp": exp,
  18. "tokenExp": exp
  19. ]
  20. guard let headerData = try? JSONSerialization.data(withJSONObject: header, options: [.sortedKeys]),
  21. let payloadData = try? JSONSerialization.data(withJSONObject: payload, options: [.sortedKeys]),
  22. let headerString = String(data: headerData, encoding: .utf8),
  23. let payloadString = String(data: payloadData, encoding: .utf8) else {
  24. throw ZoomMeetingSDKJWTError.jsonSerializationFailed
  25. }
  26. let headerPart = base64URLEncode(headerString.data(using: .utf8) ?? Data())
  27. let payloadPart = base64URLEncode(payloadString.data(using: .utf8) ?? Data())
  28. let signingInput = "\(headerPart).\(payloadPart)"
  29. guard let signingData = signingInput.data(using: .utf8) else {
  30. throw ZoomMeetingSDKJWTError.invalidUTF8
  31. }
  32. let key = SymmetricKey(data: Data(clientSecret.utf8))
  33. let mac = HMAC<SHA256>.authenticationCode(for: signingData, using: key)
  34. let signaturePart = base64URLEncode(Data(mac))
  35. return "\(signingInput).\(signaturePart)"
  36. }
  37. private static func base64URLEncode(_ data: Data) -> String {
  38. data.base64EncodedString()
  39. .replacingOccurrences(of: "+", with: "-")
  40. .replacingOccurrences(of: "/", with: "_")
  41. .replacingOccurrences(of: "=", with: "")
  42. }
  43. }