How to use ssl certificate with Swift Alamofire? - ios

I am upgrading my iOS apps with HTTPS web services.
I have upgrade my web server with SSL certificate. But don't know what to do from iOS code side?
Do I need to pass any certificate along with the web request?
I am using Alamofire for making web request.
Thanks

Simple googling would have given you so many results.
For example, https://infinum.co/the-capsized-eight/how-to-make-your-ios-apps-more-secure-with-ssl-pinning
func configureAlamoFireSSLPinning {
let pathToCert = NSBundle.mainBundle().pathForResource(githubCert, ofType: "cer")
let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!
self.serverTrustPolicy = ServerTrustPolicy.PinCertificates(
certificates: [SecCertificateCreateWithData(nil, localCertificate)!],
validateCertificateChain: true,
validateHost: true
)
self.serverTrustPolicies = [
"your-api.com": self.serverTrustPolicy!
]
self.afManager = Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: self.serverTrustPolicies)
)
}
func alamoFireRequestHandler {
self.afManager.request(.GET, self.urlTextField.text!)
.response { request, response, data, error in
// response management code
}
}

Related

Swift AlamoFire 5 won't execute Request

My problem is, when I execute the request it will happen nothing.
What I made:
I made an Api with .net core Api on a another PC and now I want to make a IOS App, that has access to the Api. (The API works I tested it with swagger and Insomnia) On the IOS app I made a put request with AlamoFire. And when I execute the request it's happening nothing. I watched the Network with Wireshark and there comes Nothing too.
When I Debug, it will step through the request Methode, but it goes nothing out to the API. And there are no errors.
// buttonClick will call this Methode
func requst() {
// testing parameters
let params: Parameters = [
"nfcId": 1,
"date" : "2021-04-12T09:47:12.053Z"
]
//
session.request("http://MyAPI/api/Guard/AddGuard", method: .put, parameters: params, headers: nil).validate(statusCode: 200 ..< 299)
}
I made an own Session wehere I pinned a certificate
private let certificates = [
"https://MyAPI:5001":
PinnedCertificatesTrustEvaluator(certificates: [Certificates.certificate], acceptSelfSignedCertificates: false, performDefaultValidation: true, validateHost: true)
]
private let session: Session
init(allHostsMustBeEvaluated: Bool) {
let serverTrustPolicy = ServerTrustManager(allHostsMustBeEvaluated: allHostsMustBeEvaluated, evaluators: certificates)
let config = URLSessionConfiguration.af.default
session = Session(configuration: config, serverTrustManager: serverTrustPolicy)
}
You haven't attached a response handler or called resume(), so no, the request isn't going to do anything. Adding something like responseDecodable will start the request automatically.

OAuth Error General Code 4 Swift - AppAuth for iOS

Im trying to implement AppAuth in iOS. basic implementation has been done. seems to be everything working fine. but im not recieving the token as expected. im getting Error Error Domain=org.openid.appauth.general Code=-4
let authorizationEndpoint : NSURL = NSURL(string: "https://accounts.google.com/o/oauth2/v2/auth")!
let tokenEndpoint : NSURL = NSURL(string: "https://www.googleapis.com/oauth2/v4/token")!
let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint as URL, tokenEndpoint: tokenEndpoint as URL)
let request = OIDAuthorizationRequest.init(configuration: configuration, clientId: "<MyTOKEN>", scopes: [OIDScopeOpenID], redirectURL: URL(string: "http://127.0.0.1:9004")!, responseType: OIDResponseTypeCode, additionalParameters: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
// appDelegate.currentAuthorizationFlow
appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self, callback: { (authState, error) in
if((authState) != nil){
print("Got authorization tokens. Access token: \(authState?.lastTokenResponse?.accessToken)")
}else{
print("Authorization error \(error?.localizedDescription)")
}
})
After dealing with errors and changes i figured out the problem after dealing with redirectUri and Token.
redirectUri - once you authorized with google it will generate the token and after that you should open the app. redirectUri will help with that.
This is how you can setup redirectUri
The value for iOS URL scheme wil be the scheme of your redirect URI. This is the Client ID in reverse domain name notation, e.g. com.googleusercontent.apps.IDENTIFIER. To construct the redirect URI, add your own path component. E.g. com.googleusercontent.apps.IDENTIFIER:/oauth2redirect/google. Note that there is only a single slash (/) after the scheme.

How to authenticate Trello API user with read, write permissions using OAuth1Swift

I am trying to authenticate a user getting read, write access permission to Trello API. I am using OAuth1Swift for authetication but cannot add paramaters to add a permission and app name.
How do we add these paramateers? This is my code below.
OAuthSwift Library
Trello API Docs
func doOAuthTrello() {
let oauthswift = OAuth1Swift(
consumerKey: "consumerKey",
consumerSecret: "consumerSecret",
requestTokenUrl: "https://trello.com/1/OAuthGetRequestToken",
authorizeUrl: "https://trello.com/1/OAuthAuthorizeToken",
accessTokenUrl: "https://trello.com/1/OAuthGetAccessToken"
)
self.oauthswift = oauthswift
oauthswift.authorizeURLHandler = getURLHandler()
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "oauth-swift://oauth-callback/trello")!,
success: { credential, response, parameters in
self.showTokenAlert(name: serviceParameters["name"], credential: credential)
self.testTrello(oauthswift)
},
failure: { error in
print(error.localizedDescription, terminator: "")
}
)
}
After trying everything, this is the solution:
lazy var paramaters:[String: String] = {
return [
"consumerKey": "consumerKey",
"consumerSecret": "consumerSecret",
"requestTokenUrl": "https://trello.com/1/OAuthGetRequestToken?scope=read,write,account&expiration=never&name=AppName",
"authorizeUrl": "https://trello.com/1/OAuthAuthorizeToken?scope=read,write,account&expiration=never&name=AppName",
"accessTokenUrl": "https://trello.com/1/OAuthGetAccessToken?scope=read,write,account&expiration=never&name=AppName"
]
}()
The magic happens by adding ?scope=read,write,account&expiration=never&name=AppName to the url parameters

Certificate pinning in Alamofire not working

I've added a .der certificate to my project, which is recognised by ServerTrustPolicy.certificatesInBundle(). I'm now creating a Manager which is then used to make API calls:
private class func manager() -> Alamofire.Manager {
let certificates = ServerTrustPolicy.PinCertificates(
certificates: ServerTrustPolicy.certificatesInBundle(),
validateCertificateChain: true,
validateHost: true
)
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"api.oursite.com": certificates
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let manager = Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
return manager
}
Before this, it was just using Alamofire.request(..., and those requests were working perfectly fine, but now it's giving me an error on every call:
Error Domain=NSURLErrorDomain Code=-999 "cancelled"
Am I setting up the manager incorrectly? Perhaps my certificate was created incorrectly, and that's causing this to not work?
Be sure that your manager not deallocated in short time after request. Make it as stored property in custom Manager class for example.

certificatesInBundle doesn't append self signed certificates

Using the convenience method ServerTrustPolicy.certificatesInBundle() doesn't appear to work correctly in my case
// MARK: - Bundle Location
/**
Returns all certificates within the given bundle with a `.cer` file extension.
- parameter bundle: The bundle to search for all `.cer` files.
- returns: All certificates within the given bundle.
*/
public static func certificatesInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecCertificate] {
var certificates: [SecCertificate] = []
let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
bundle.pathsForResourcesOfType(fileExtension, inDirectory: nil)
}.flatten())
for path in paths {
if let
certificateData = NSData(contentsOfFile: path), // <-- we get the data of the certificate in bundle
certificate = SecCertificateCreateWithData(nil, certificateData) // <-- The problem is here, the certificate is not set neither errors.
{
certificates.append(certificate) // <-- this doesn't run
}
}
return certificates
}
Probably has to do something with the format of the self-signed certificate. I used exactly the #tip 5 from this blog post. Five Tips for Using Self Signed SSL Certificates with iOS
The question is what is the limitations of the SecCertificateCreateWithData method and which certificate formats are acceptable? Even better where can I read more about this particular issue.
my code appears to be correct it's nothing special, probably one of the most used snippets :P
let defaultManager:Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"localhost": .PinCertificates(
certificates: ServerTrustPolicy.certificatesInBundle(),
validateCertificateChain: true,
validateHost: true
)
]
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
The most likely reason that SecCertificateCreateWithData would return nil, is that the file is in PEM not DER format.
As per the documentation, data should contain
A DER (Distinguished Encoding Rules) representation of an X.509
certificate
If your data begins with "-----BEGIN...", then it is the wrong format. PEM can be converted to DER (and vice versa) with OpenSSL - here is a handy reference https://www.sslshopper.com/article-most-common-openssl-commands.html.
Also, in case of a self-signed certificate (judging by "localhost"), the validateCertificateChain property should be false. Otherwise the request will fail with a "cancelled" NSError.
Additionally, starting from iOS9, App Transport Security settings should be set to allow arbitrary loads (in Info.plist). That is the only setting that will permit self-signed certificates to be evaluated by your app. Without it, the Alamofire trust policy mechanism will not get a chance to kick in.
I had a similar problem. Alamofire couldn't find my certificate, the ServerTrustPolicy.certificatesInBundle() method did not return anything.
The problem was that when dragging my certificate into my Xcode project I didn't select "Add to targets: MyProjectName".
Make sure that you downloaded the certificate in der format and added correctly to your project.
after that define a static SessionManager as mentioned below
public static let sharedManager: SessionManager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"subdomain.domain.com": .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: false,
validateHost: true
),
"insecure.expired-apis.com": .disableEvaluation
]
let manager = Alamofire.SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
return manager
}()
then you can call the above sharedManager:
YourHttpClassName.sharedManager.request(url, method: .get, headers: headers).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
debugPrint(response)
}
it should work fine with your self-signed certificate.

Resources