Reputation: 2321
I have my own web application using laravel as back-end which works fine.
Now, I'm starting coding the IOS app (IOS 9, Xcode 7, Swift 2) and would like to connect it to my web app database so I can use API for queries.
My first step which I'm stuck is about the login/password for the user to connect to the web app database through the IOS app.
I have installed an oauth 2.0 configuration on my web app and using the password grant type. Tested with Postman and I can get the access token using the following parameter in the body with x-www-form-urlencoded:
Now, I want to access to the database of this web app with these credentials from the IOS app.
I have created a login form in the view controller. When I tap the login button, I launch an IBAction as follow:
@IBAction func login(sender: UIButton){
let myURL = NSURL(string: "http://myWebApplication.com/oauth/access_token")!
let request = NSMutableURLRequest(URL: myURL)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
let bodyStr:String = "grant_type=password&client_id=f3d259ddd3ed8ff3843839b&client_secret=4c7f6f8fa93d59c45502c0ae8c4a95b&[email protected]&password=123456"
request.HTTPBody = bodyStr.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Your completion handler code here
}
task.resume()
}
But nothing happened.
Could you please tell me where I'm wrong?
I spent hours searching for solution and the code above is the result of this search. Unfortunately, not sufficient.
On top of that, what is the next step to store the access token that the web app will return and use it so I can send queries related to this particular user?
Thank you in advance for your help
Upvotes: 2
Views: 7077
Reputation: 2321
Thank you Frederico for your help.
I finally managed this way using KeychainWrapper (very useful to manage keychain for sensitive information).
Let me know if anything comment:
@IBAction func loginButtonTapped(sender: UIButton) {
self.emailTextField.resignFirstResponder()
self.passwordTextField.resignFirstResponder()
if (self.emailTextField.text == "" || self.passwordTextField.text == "") {
let alertView = UIAlertController(title: "Login failed",
message: "Wrong username or password." as String, preferredStyle:.Alert)
let okAction = UIAlertAction(title: "Try Again!", style: .Default, handler: nil)
alertView.addAction(okAction)
self.presentViewController(alertView, animated: true, completion: nil)
return
}
// Check if the user entered an email
if let actualUsername = self.emailTextField.text {
// Check if the user entered a password
if let actualPassword = self.passwordTextField.text {
// Build the body message to request the token to the web app
self.bodyStr = "grant_type=password&client_id=f3d259ddd3ed8ff3843839b&client_secret=4c7f6f8fa93d59c45502c0ae8c4a95b&username=" + actualUsername + "&password=" + actualPassword
// Setup the request
let myURL = NSURL(string: "http://test.com/oauth/access_token")!
let request = NSMutableURLRequest(URL: myURL)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = bodyStr.dataUsingEncoding(NSUTF8StringEncoding)!
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) -> Void in
if let unwrappedData = data {
do {
// Convert the Json object to an array of dictionaries
let tokenDictionary:NSDictionary = try NSJSONSerialization.JSONObjectWithData(unwrappedData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
// Get the token
let token:String = tokenDictionary["access_token"] as! String
// Keep record of the token
let saveToken:Bool = KeychainWrapper.setString(token, forKey: "access_token")
// Dismiss login view and go to the home view controller
self.dismissViewControllerAnimated(true, completion: nil)
}
catch {
// Wrong credentials
// Reset the text fields
self.emailTextField.text = ""
self.passwordTextField.text = ""
// Setup the alert
let alertView = UIAlertController(title: "Login failed",
message: "Wrong username or password." as String, preferredStyle:.Alert)
let okAction = UIAlertAction(title: "Try Again!", style: .Default, handler: nil)
alertView.addAction(okAction)
self.presentViewController(alertView, animated: true, completion: nil)
return
}
}
}
task.resume()
}
}
}
Upvotes: 1
Reputation: 203
I was having the same issue.. Mostly from Cristina Moulton's iOS with REST APIs book, hope it helps.
try this: # using Alamofire & SwiftyJSON #
func loginUser() {
var code:String?
var accessToken:String?
let path:String = EndPoints.kRestEndpoint + EndPoints.kToken
let parameters:[String:String] = ["grant_type": "password","client_id": "[email protected]", "client_secret": "123456"]
let headers:[String:String] = ["Content-Type": "application/x-www-form-urlencoded","Accept": "application/json"]
Alamofire.request(.POST, path, parameters: parameters, encoding: .URL, headers: headers).responseString { response in
// Handle response to extract the OAuth Token
if let error = response.result.error {
print(error)
return
}
// The access token + type
print(response.result.value)
if let receivedResults = response.result.value, jsonData = receivedResults.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let jsonResults = JSON(data: jsonData)
for (key, value) in jsonResults {
switch key {
case "access_token":
if let token = value.string {
code = token
}
case "token_type":
if let type = value.string {
accessToken = "\(type) \(code!)"
}
case "expires_in":
// Handle expiration
print("It has expiration")
default:
print("got more than I expected from the OAuth token exchange")
print(key)
}
}
print("AccessToken: \(accessToken!)")
} //End of receivedResults
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(true, forKey: "loadingOAuthToken")
}
}
Upvotes: 1