I'm trying unsuccessfully to get a userToken for Apple Music SDK using the developerToken from JWT. I've used pelauimagineering/apple-music-token-generator and I could get a valid and static userToken. But apple recommend to make dynamic, so I'm trying to use JWT again.
Someone can tell me please what's wrong with my code? Thank you
func fetchDeveloperToken() -> String? {
func fetchDeveloperToken() -> String? {
let iat = Date().timeIntervalSince1970
let days = TimeInterval(24*60*60*120) //120 days
let exp = TimeInterval(iat + days)
let kid = "TBESJXXXXX"
let iss = "KQ6Z6XXXXX"
let alg = "ES256"
let secret = "MIGTAgEAMBMGByqEU7ZHQsoVfmKCCxS5W6BnCgCgYIKoZIzj0AAQcggNoN7dTkNG/8timkkf+Z2toogAqN41YgOXXXXXXXXXXXXXXXXXXsecretkey"
let header:[AnyHashable:Any] = ["alg":alg, "kid":kid]
let payload:[AnyHashable:Any] = ["iss": iss,
"iat": iat,
"exp": exp]
let algorithm256 = JWTAlgorithmHS256()
return JWT.encodePayload(payload, withSecret: secret, withHeaders: header, algorithm: algorithm256)
}
Apple requires you to use the ES256 algorithm, not HS256, I ran into the same issue too. The JWT libray that you're using doesn't support ES256 as you can see here. The only other library on iOS that is listed that supports it is this one
Related
I'm trying to make a transaction through Google Pay app. I've implemented this so far:
let paValue = "Client_upi_key" //payee address upi id
let pnValue = "Merchant Name" // payee name
let trValue = "1234ABCD" //tansaction Id
let urlValue = "http://url/of/the/order/in/your/website" //url for refernec
let mcValue = "1234" // retailer category code :- user id
let tnValue = "Purchase in Merchant" //transction Note
let amValue = "1" //amount to pay
let cuValue = "INR" //currency
let str = "gpay://upi/pay?pa=\(paValue)&pn=\(pnValue)&tr=\(trValue)&mc=\(mcValue)&tn=\(tnValue)&am=\(amValue)&cu=\(cuValue)"
guard let urlString = str.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
else {
return
}
guard let url = URL(string: urlString) else {
return
}
UIApplication.shared.open(url)
Now I'm returning to my app & want to have some response like transactionID, userID etc from Google Pay. Is there any way like Android to use Intent in this scenario?
As far as I can see the Google Pay API is only available on Android and Web. Judging from the current docs only showing those options.
If you are looking for a simple payments API, Stripe I know is quite easy to implement. You could also try the Apple Pay SDK.
I've been using Stripe iOS SDK for a while now and everything is clear regarding the implementation. Since our app is going to support App Clips on iOS 14, we are reducing the binary size and therefore decided to remove Stripe iOS SDK as well.
So my question here is if I can somehow send payment requests via the API and omitting the Stripe SDK altogether?
p.s.: It looks like I need to implement the /tokens endpoint passing the card data. Is there any example of the request to be made?
I've managed to solve this situation and here is the solution if anyone is interested. Here are the steps to make this happen:
Prepare a request model
import Foundation
import PassKit
struct StripeTokenRequest: Encodable {
let pkToken: String
let card: Card
let pkTokenInstrumentName: String?
let pkTokenPaymentNetwork: String?
let pkTokenTransactionId: String?
init?(payment: PKPayment) {
guard let paymentString = String(data: payment.token.paymentData, encoding: .utf8) else { return nil }
pkToken = paymentString
card = .init(contact: payment.billingContact)
pkTokenInstrumentName = payment.token.paymentMethod.displayName
pkTokenPaymentNetwork = payment.token.paymentMethod.network.map { $0.rawValue }
pkTokenTransactionId = payment.token.transactionIdentifier
}
}
extension StripeTokenRequest {
struct Card: Encodable {
let name: String?
let addressLine1: String?
let addressCity: String?
let addressState: String?
let addressZip: String?
let addressCountry: String?
init(contact: PKContact?) {
name = contact?.name.map { PersonNameComponentsFormatter.localizedString(from: $0, style: .default, options: []) }
addressLine1 = contact?.postalAddress?.street
addressCity = contact?.postalAddress?.city
addressState = contact?.postalAddress?.state
addressZip = contact?.postalAddress?.postalCode
addressCountry = contact?.postalAddress?.isoCountryCode.uppercased()
}
}
}
Use JSONEncoder and set keyEncodingStrategy to .convertToSnakeCase.
Create a POST request against https://api.stripe.com/v1/tokens endpoint where you need to url encode parameters. If you are using Alamofire, you need to set encoding to URLEncoding.default.
Parse response. I use JSONDecoder with the following model:
import Foundation
struct StripeTokenResponse: Decodable {
let id: String
}
Create a payment
StripeTokenResponse.id is the thing you need to pass to the backend where the payment will be processed. This is the same step as you'll do when using the SDK.
You can check Strip checkout, it allows you to present a payment page in web format without any Stripe SDK on the client side.
I want to get the Channel and User Id from the registration of MCE SDK on the Watson platform. I was able to get the information on Android using the following code:
RegistrationClient client = MceSdk.getRegistrationClient();
RegistrationDetails details = client.getRegistrationDetails(this);
String channelID = registrationDetails.getChannelId();
String userID = registrationDetails.getUserId();
Does anyone knows how to get the same information of the SDK on iOS side? I tried with different ways and the only detail I was able to get is the SDK Version and the App Key with this:
let sdkVersion = MCESdk.shared.sdkVersion()
let appKey = MCESdk.shared.config.appKey
At the end, I was looking on the wrong object, all the details are on the class MCERegistrationDetails.
let appKey = MCERegistrationDetails.shared.appKey
let channelId = MCERegistrationDetails.shared.channelId
let userId = MCERegistrationDetails.shared.userId
I import JWT(using .Package(url:"https ://github.com/vapor/jwt.git", majorVersion: 1))
enter image description here
The project can build and run. But when I look into CTLS, the Xcode shows "Could not load module: CTLS". I don't know why.
At the same time, the JWT I create seems not right. Here is my codes:
import JWT
import Vapor
get("token") { req in
let algValue = StructuredData.string("ES256")
let kidValue = StructuredData.string("CapExedKid")
let headerData = StructuredData.object(["alg":algValue,"kid":kidValue])
let header = JSON.init(headerData)
let issValue = StructuredData.string("CapExdTeam")
let sec = Int(Date().timeIntervalSince1970)
let iatValue = StructuredData.number(StructuredData.Number(sec))
let expValue = StructuredData.number(StructuredData.Number(sec+1000000))
let claimsData = StructuredData.object(["iss":issValue,"iat":iatValue,"exp":expValue])
let claims = JSON.init(claimsData)
let url = URL.init(fileURLWithPath: "/Users/aamac/Desktop/HelloWorld/AuthKey_demoKey.p8")
let data = try Data.init(contentsOf: url)
let signer = ES256.init(key: data.makeBytes())
let jwt = try JWT.init(headers: header, payload: claims, signer: signer)
let token = try jwt.createToken()
return token }
I use the token to do the authenticate requests as Apple Music API says, I got a http status code 500..
I enter this in terminal:
curl -v -H 'Authorization: Bearer [developer token]' "https ://api.music.apple.com/v1/catalog/us/songs/203709340"
and got 500..
But I use a Python library to get the token and do the request in terminal, it works, so I doubt that the JWT in swift have some kind of problem...Can anyone tell me??
I experienced a similar problem (https://github.com/vapor/jwt/issues/47). What worked for me was using data.bytes.base64Decoded instead of data.makeBytes() when initializing the signer.
I am developing iOS app in swift. We need to fetch images from amazon cloud front . I am able to fetch private content from cloud front in Objective C using openssl library in Xcode 6.4 using this reference link.
But I am using same library in swift , so getting importing error.
Please suggest it , How to create signed url for amazon cloud front to access private content in iOS.
If any other library to create signed url for amazon cloud front, please suggest it.
There is a great lib for that :) And this is a full code in Swift 2:
lazy var signedURL: String = {
let epochTime = NSDate().dateByAddingTimeInterval(60*5).timeIntervalSince1970
let resourceURL = "resource url"
let keyPairId = "your pair id"
let keyPairPrivateKeyName = "name of pem file"
let myurl = String(format: "%#?Expires=%.0f&Signature=%#&Key-Pair-Id=%#",
resourceURL,
epochTime,self.getSignature(resourceURL, expiresOn: epochTime, privateKey: keyPairPrivateKeyName), keyPairId)
return myurl
}()
func encodeStringForCloudFront(signature aSignature: String) -> String {
var signature = aSignature
signature = signature.stringByReplacingOccurrencesOfString("+", withString: "-")
signature = signature.stringByReplacingOccurrencesOfString("=", withString: "_")
signature = signature.stringByReplacingOccurrencesOfString("/", withString: "~")
return signature;
}
func getSignature(resourceURL: String, expiresOn: NSTimeInterval, privateKey keyPairPrivateKeyName: String) -> String {
let signString = String(format: "{\"Statement\":[{\"Resource\":\"%#\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":%.0f}}}]}", resourceURL, expiresOn)
guard let filePath = NSBundle.mainBundle().pathForResource(keyPairPrivateKeyName, ofType: "pem"),
let privateKeyData = NSData(contentsOfURL: NSURL(fileURLWithPath: filePath)) else {
return "Error loading pem file."
}
guard let str = String(data: privateKeyData, encoding: NSUTF8StringEncoding) else {
return "Private Key Data is not valid"
}
do {
let signatureString = try SwiftyRSA.signString(signString, privateKeyPEM: str)
return self.encodeStringForCloudFront(signature: signatureString)
} catch {
return "Something goes wrong URL NotValid"
}
}
As the linked thread states, it is extremely insecure to embed the Amazon CloudFront certificates on mobile devices.
Instead of generating the pre-signed URL on iOS, you should have a server and generate the pre-signed URL on your server. See Serving Private Content through CloudFront for more details on how to do this.
How to create signed url for amazon cloud front to access private content in iOS.
Its not clear to me what this has to do with OpenSSL. I also don't know what a signed URL is. Perhaps its a Amazon or Cloud Front marketing term.
With that said, I believe Python uses self authenticating URLs. A user agent can check authenticity of a package by visiting a URL based on a digest of the package. If the server responds with a 200, then its valid; otherwise its invalid. There's no page backing the URL.
Its not clear to me what you are trying to do, so I should probably stop there. For more reading, see:
Peter Gutmann's Engineering Security, around page 384
Python self authenticating URLs
You can use OpenSSL to create a self authenticating URL. You will have to modify the Base64 encoder, however. The default Base64 encoder uses the the standard Base64 alphabet from the old days (dating back to the 1980s and email). For web gear, you usually need to use the Base64 with the web safe alphabet.