Skip to main content
Question

iOS SDK - Authentication With JWT

  • May 22, 2025
  • 4 replies
  • 33 views

Forum|alt.badge.img

We are using the iOS SDK (Swift) to try and get a token but are having some trouble figuring this out. We have a valid API key and all that it's just that I think we could use some sample code to help get the token and start performing some Box calls.

 

Can anyone give us a link or paste in some code here?

 

Thanks in advance!

4 replies

Forum|alt.badge.img

Just elaborating on the initial question:

 

The BOXAPIAccessTokenDelegate method is being defined.  When we try to authenticate with 

autheticateAppUser() the delegate method gets called, which provides a callback where we set the accessToken.  What we're missing is getting this token.

 

func fetchAccessToken(completion: ((String?, Date?, Error?) -> Void)!) {

        let accessToken = getAccessToken() // This is what's missing

        completion(accessToken, Date(timeInterval: 1000, since: Date()), nil)

}

 

What we have is:

- clientID

- clientSecret

- publicKeyID

- privateKey

- passphrase

- enterpriseID

 

The clientID and clientSecret are set in the setClientID(clientSecret:) static method on BOXContentClient.

 

There is a class in the Java API called BOXConfig, which takes the remaining values but I don't see one for iOS.  Any help would be greatly appreciated.


Forum|alt.badge.img

After about a week of scouring the internet this is what I did to get it to work on swift3:

 

  1. Based off of several blogs, Apple decprecated openssl; so, it might be easier to first decrypt your private key through your terminal like here https://stackoverflow.com/questions/13732826/convert-pem-to-crt-and-key
    1. I ran >> openssl pkcs8 -outform pem -in ecrypted.pem -out decrypted.pem to get a decrypted key.
  2. I then pasted the decrypted pem string into a struct so I could easily import it later (don't recommend doing this with data sensitive app).

    struct dKey {

       static let pKey =

    "-----BEGIN PRIVATE KEY-----\n"

    + "-----END PRIVATE KEY-----\n" }

  3. Using SwiftyCrypto I imported the key and created a JWT assertion https://github.com/Wstunes/SwiftyJWT:
    1. let privateKeyD = try! RSAKey.init(base64String: dKey.pKey, keyType: .PRIVATE)

              let headerWithKeyId = JWTHeader.init(keyId: appAuthJson["publicKeyID"] as? String)

              let alg = JWTAlgorithm.rs256(privateKeyD)

              var payload = JWTPayload()

              payload.issuer = configJson["clientID"] as? String

              payload.subject = configJ["enterpriseID"] as? String

              payload.jwtId = generateRandomBytes()!.hexEncodedString()

              payload.audience = "https://api.box.com/oauth2/token"

              payload.expiration = Int(Date().addingTimeInterval(1.0 * 60.0).timeIntervalSince1970)

              payload.customFields = ["box_sub_type": EncodableValue(value: "enterprise")]

              

              let jwtWithKeyId = try? JWT.init(payload: payload, algorithm: alg, header: headerWithKeyId)

  4. I then created params to pass into a Request:

    let params = ["grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",

                          "assertion" : jwtWithKeyId!!.rawString!,

                          "client_id" : tmpClientID,

                          "client_secret": tmpClientSecret,

                            ]

  5. I then submitted a request through the http body, NOT url query
    1.  let urlParams = params.flatMap({ (key, value) -> String in

                  return "\(key)=\(value)"

              }).joined(separator: "&")

              

              let bodyString = urlParams

              print("bodyString \(bodyString)")

              // create post request

              let url = URL(string: "https://api.box.com/oauth2/token")!

              var request = URLRequest(url: url)

              request.httpMethod = "POST"

              

              // insert json data to the request

              request.httpBody = bodyString.data(using: .utf8)

              

              let task = URLSession.shared.dataTask(with: request) { data, response, error in

                  guard let data = data, error == nil else {

                      print(error?.localizedDescription ?? "No data")

                      return

                  }

                  let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])

                  if let responseJSON = responseJSON as? [String: Any] {

                      print(responseJSON)

                  }

              }

              

              task.resume()

You should have your access token now in responseJSON.

This was using a play app, and I don't recommend pasting decrypted key into a struct for apps dealing with sensitive data. 


Forum|alt.badge.img

Hello,

 

Thank you for sharing that info. I am facing the same problem and I hope if you can give the source file on Github or share it with me on Drive, here is my email:

 

***email address removed for privacy***


Forum|alt.badge.img

Did anyone resolve this to completion? I've been stuck on the same problem for quite a while, but no good examples seem to show a complete solution.

 

~Bryan