I am experimenting on OAuth2 (on Laravel) & Swift with Alamofire. I successfully got token, however I couldn't set the headers to be able to get authenticate-specific data from Api.
Without Alamofire, I was setting this header and it was working.
func me(handler: (data: NSDictionary?, error: String?) -> Void)
{
let url = NSURL(string: "/me", relativeToURL: self.baseUrl)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "GET"
if let t = self.getAccessToken()
{
request.setValue("Bearer \(t)", forHTTPHeaderField: "Authorization")
}
}
However I didn't get what to do with Alamofire.
Now I can use getAccessToken() to get token as a string, but I got really confused adapting it to Alamofire style.
I tried this but doesn't pass the authentication middleware for a reason:
let token = getAccessToken()
print(token!) // prints
let headers = ["Authorization":"Bearer \(token)"]
Alamofire.request(.GET, userDetailsEndpoint!, headers: headers)...
Still getting error The resource owner or authorization server denied the request
Related
I tried to make a Request with JWT Authorization, The server is Using Python/Flask-Restful. The API Works on Postman, so I guess there must be something wrong with my IOS Code. The server returns an error shows that
"Authorization Required. Request does not contain an access token",
I`m making the request from IOS Using following code.
func GetUserData(username: String, accesstoken: String,completion: #escaping (_ result: UserDataModel) -> Void){
let url = URL(string: "http://********/****/\(****)")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.addValue("Authorization", forHTTPHeaderField: accesstoken)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response as? HTTPURLResponse{
if response.statusCode != 200 {
print("Server Error When Update User Data")
} else {
if let data = data {
do {
******
completion(Data)
}
catch {
print(error)
}
}
}
}
}.resume()
}
I have no idea What is going on, Any help?
It looks like you're adding the header:
Bearer base64junk: Authorization
When instead you want:
Authorization: Bearer base64junk
You just have the parameters to addValue(_:forHTTPHeaderField:) backwards. You want this instead:
request.addValue(accesstoken, forHTTPHeaderField: "Authorization")
This should be obvious if you read that line of code like an English sentence ("value authorization for header field access token"?). In the future, you could also use something like Charles Web proxy to intercept your requests and verify that they are indeed formed the way you expect.
I have an issue when calling the /oauth2/token endpoint of the Imgur API using Swift / NSMutableURLRequest and maybe it's actually just me setting up the request in a wrong way as I don't have a lot of experience with NSMutableURLRequest.
Scenario:
The user has already authenticated my App, he can post photos to his Imgur account.
Problem:
Imgur requires to re-authenticate after 28 days.
That's why after authenticating the App you get a (temporary; for 28 days) access_token and a long-term refresh_token which you use after 28 days to get a new access_token.
I do following API call to retrieve a new access_token but always get the error:
"Invalid grant_type parameter or parameter missing" with error code 400.
Here is my HTTP request:
if let reqUrl = URL(string: "https://api.imgur.com/oauth2/token?refresh_token=\(refreshKey)&client_id=\(CLIENT_ID)&client_secret=\(IMGUR_SECRET)&grant_type=refresh_token")
{
let request = NSMutableURLRequest(url: reqUrl)
print("request: \(reqUrl)")
request.httpMethod = "POST"
request.setValue("Client-ID \(CLIENT_ID)", forHTTPHeaderField: "Authorization")
request.addValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest){ data, response, error in
if (error != nil){
print("error: \(error)")
return
}
print("response: \(response!)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response string: \(responseString!)")
}
task.resume()
}
refreshKey, CLIENT_ID and IMGUR_SECRET should all be correct.
Thank you in advance for your help!
So, I solved it this way:
let bodyString = "grant_type=refresh_token&client_secret=\(IMGUR_SECRET)&client_id=\(CLIENT_ID)&refresh_token=\(refreshKey)"
request.httpBody = bodyString.data(using: .utf8)
basically setting the parameters in the request's body instead of putting them in the URL.
Hope this can help someone else, too :)
I want to validate the OTP of created user. I'm using POST RESTful API for this. All created user have their Auth token. So when i'm validating the user OTP, it says 'Invalid Authentication', but i'm sending the Token in the POST Request Header?
Here is my code :-
let urlString = "http://192.168.182.81:8080/serviceplus/user/validateotp.json"
if let url = NSURL(string: urlString) {
let URLRequest = NSMutableURLRequest(URL: url)
let headers = [
"Authorization": "\(token)",
"Accept": "application/json"
]
Alamofire.request(.POST, URLRequest, headers: headers, parameters: ["otpcode": fields[0].text!]).responseJSON { response in
print("Error :- \(response.result.error)")
print("Result values :- \(response.result.value)")
}
}
What should i do?
Thanks.. :)
I am able to get the access token of my LinkedIn account in swift using the LinkedIn SDK. How do I authenticate this login with Stormpath?
[Update]
let APIURL = "https://api.stormpath.com/v1/applications/LI_APPLICATION_ID/accounts"
func sendRequestWithJSON(accessToken:String)
{
let json = [ "providerData" : ["providerId": "linkedin", "accessToken": accessToken] ]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted)
let username = STORMPATH_API_KEY_ID
let password = STORMPATH_API_KEY_SECRET
let loginString = NSString(format: "%#:%#", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedDataWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
// create post request
let url = NSURL(string: APIURL)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// insert json data to the request
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPBody = jsonData
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
if error != nil{
print("Error -> \(error)")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Result -> \(result)")
} catch {
print("Error -> \(error)")
}
}
task.resume()
//return task
} catch {
print(error)
}
}
I am passing accessToken fetch from linkedin to above function, but it return below result:
["message": Authentication required., "status": 401, "code": 401, "developerMessage": Authentication with a valid API Key is required., "moreInfo": http://www.stormpath.com/docs/quickstart/connect]
What's wrong I am doing?
LinkedIn is an interesting beast, since their mobile SDKs have two flaws:
An end user NEEDS the LinkedIn app to be installed, otherwise the "login" button will redirect the user to the App Store.
The mobile access token cannot be used on the server. See this screenshot from LinkedIn's iOS documentation
So - to get auth working on mobile, I would recommend using a server to handle the flow, so you don't have to worry about those two downsides. This is roughly:
The app will redirect the user to your webserver.
The webserver begins the LinkedIn authentication flow, and redirects the user to LinkedIn.
The user logs into LinkedIn, and gets redirected back to your webserver.
The webserver reads the response, and exchanges the Authorization Code with LinkedIn for an access token.
The webserver redirects your user back to the app, using a custom url scheme to send it the LinkedIn access token.
The app uses the LinkedIn access token to login to Stormpath.
Sound complicated? It's actually more straightforward than it seems. I actually wrote some demo code for this flow using Express.js & Swift if you want to try it out. Let me know if it works for you!
I am trying to login (form) into a website and parse data with Swift and NSURLSession.
I have been using cURL to confirm that this is actually possible, and the following code returns the webpage-body as expected.
curl -c cookie.txt -d "username=karl" -d "password=ivar" https://talkmore.no/talkmore3/servlet/Login
curl -b cookie.txt https://talkmore.no/talkmore3/servlet/SubscriptionUsage
When I am trying to do this in Swift, I fetch the Cookie from the response header, then I try to retrieve the SubscriptionUsage-webpage by passing the cookie along. However I cannot get this to work.
How can I convert this simple curl syntax to Swift-code using NSURLSession?
Edit: What I've got so far.
func login() -> Void {
var session = NSURLSession.sharedSession()
var request = NSMutableURLRequest(URL: NSURL(string: "https://www.talkmore.no/talkmore3/servlet/Login")!)
request.HTTPMethod = "POST"
var params = "username=karl&password=ivar"
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
request.addValue("text/html", forHTTPHeaderField: "Content-Type")
var task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) -> Void in
println("Response: \(response)")
println("Data: \(NSString(data: data, encoding: NSUTF8StringEncoding)))")
let httpResponse = response as NSHTTPURLResponse
var cookie = httpResponse.allHeaderFields["Set-Cookie"] as String
})
task.resume()
All seems good, I receive the response with a header including "Set-Cookie" = "JSESSIONID=D8307BA498EFE061C86636C51B8AC25D; Path=/talkmore3/; Secure; HttpOnly"; And I believe I have to send this cookie with the next request. But I have failed to replicate the cURL behavior.