Skip to content

Instantly share code, notes, and snippets.

@matthewrobertson
Created December 2, 2020 21:28
Show Gist options
  • Save matthewrobertson/4abaddf5687dbd711d8660f0b1af8e3b to your computer and use it in GitHub Desktop.
Save matthewrobertson/4abaddf5687dbd711d8660f0b1af8e3b to your computer and use it in GitHub Desktop.
Issue an ACS user access token in Swift
// Script to issue an ACS user token via HMAC auth as described in this doc:
// https://docs.microsoft.com/en-us/azure/communication-services/concepts/authentication?tabs=csharp#sign-an-http-request
import UIKit
import Foundation
import CryptoKit
struct FetchTokenResult: Codable {
var identity:String
var token:String
var expiresIn: Int
}
func fetchToken(endpoint: String, accessKey: String, identity: String? = nil, completionHandler: @escaping (Result<FetchTokenResult, Error>) -> Void) {
// create the URL
let url = URL(string: "\(endpoint)/identity/token?api-version=2020-07-20-preview1")!
// create the JSON body
var jsonObject: [String: Any] = ["scopes": ["chat", "voip"]]
if let identity = identity {
jsonObject["identity"] = identity
}
let bodyBytes = try! JSONSerialization.data(withJSONObject: jsonObject)
// create an SHA256 digest of the body
let digest = SHA256.hash(data: bodyBytes)
let bodyDigest = Data(digest).base64EncodedString()
// ISO UTC Timestamp fot eh date header
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "E, dd MMM yyyy HH:mm:ss z"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let date = dateFormatter.string(from: Date())
// HMAC for the Authorization header
let stringToSign = "POST\n\(url.path)?\(url.query!)\n\(date);\(url.host!);\(bodyDigest)"
let key = SymmetricKey.init(data: Data(base64Encoded: accessKey)!)
let code = HMAC<SHA256>.authenticationCode(for: stringToSign.data(using: .utf8)!, using: key)
let authHeader = "HMAC-SHA256 SignedHeaders=date;host;x-ms-content-sha256&Signature=\(Data(code).base64EncodedString())"
// configure the URL request
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST
request.httpBody = bodyBytes
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(date, forHTTPHeaderField: "Date")
request.addValue(bodyDigest, forHTTPHeaderField: "x-ms-content-sha256")
request.addValue(authHeader, forHTTPHeaderField: "Authorization")
// submit the HTTP request
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
if let error = error {
completionHandler(.failure(error))
return
}
let decoder = JSONDecoder()
let result = try! decoder.decode(FetchTokenResult.self, from: data!)
completionHandler(.success(result))
}
task.resume()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment