I am having a problem trying to Authenticate a request using alamofire and OAuth1 and I am using this library to do so:
https://github.com/phenemann/Authentication/
but I am not able to succeed if you know how to use alamofire with OAuth1.
Bellow is my progress till this moment
class HttpRestManager{
public static func sendRequest(url: String, authorizationType: AuthorizationType, method: HTTPMethod, parameters: [String: Any]?, headers: NSMutableDictionary, complition: #escaping (_ results: String?, _ errors: Error?, _ statusCode: Int?) -> Void){
let preparedHeaders = prepareHeaders(headers: headers, authorizationType: authorizationType)
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 10
manager.adapter = AuthorizationAdapter()
manager.request(url, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: preparedHeaders).responseString { (response) in
switch response.result{
case .success(let value):
complition(value, nil, response.response?.statusCode)
case .failure(let error):
complition(nil, error, response.response?.statusCode)
}
}
}
}
and this is the adapter I am using:
class AuthorizationAdapter: RequestAdapter {
private let CONSUMER_KEY = "****";
private let CONSUMER_SECRET = "****";
private let TOKEN_ID = "****";
private let TOKEN_SECRET = "****";
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
let oAuthMethod = AuthenticationMethod.oauth1(consumerKey: CONSUMER_KEY,
consumerSecret: CONSUMER_SECRET,
accessKey: TOKEN_ID,
accessSecret: TOKEN_SECRET)
let authorizer = Authenticator(method: oAuthMethod)
let authorizedRequest = try? authorizer.signRequest(request: urlRequest)
return authorizedRequest!
}
}
please note that I have the ConsumerKey, ConsumerSecret, TokenID and TokenSecret there is no CallBackUrl or anything I Just need to generate the "oauth_signiture" value, based on the request URL and it's parameters, I have generated it but the response I get is "INVALID_LOGIN_ATTEMPT", and whenever I test the API on Postman it succeeds even though the generated header is similar to the one I generate, please help me or tell me what I am doing wrong, many thanks.
Related
Im trying to upload a file to the backend. edit
I'm at a stand still with this code. I feel like I'm doing this wrong. Its returning (Status Code: 400, Headers ) Which makes me believe that the error is in the headers but I may be totally wrong because I see people using .upload() instead of .request. I've made 2 functions based on these two methods, neither one works. .request is error 400, upload() is error 500. I've tried the access token in L5 Swagger and it works. The only parameter is a file which I assume is data. Here are the methods
#discardableResult
public func postUploadSeekerAvatar(_ image: UIImage, result: #escaping (Error?) -> Void) -> URLSessionTask? {
let imageData: Data = UIImagePNGRepresentation(image)!
let params: [String: Any] = ["data": imageData]
var headers = authHeader
headers?["Content-Type"] = "application/json"
return Alamofire.request(endpointURL("users/seeker/avatar"), method: .post, parameters: params, headers: headers)
.responseData(completionHandler: { (response: DataResponse<Data>) in
guard response.result.error == nil else {
return result(response.result.error)
}
return result(response.result.error)
}).task
}
#discardableResult
public func postSeekerAvatar(_ image: UIImage, result: #escaping (Error?) -> Void) -> URLSessionTask? {
let data = UIImagePNGRepresentation(image)!
var headers = authHeader
headers?["Content-Type"] = "application/json"
return Alamofire.upload(data, to: endpointURL("users/seeker/avatar"), method: .post, headers: headers)
.responseData(completionHandler: { (response: DataResponse<Data>) in
guard response.result.error == nil else {
return result(response.result.error)
}
return result(response.result.error)
}).task
}
Can you sirs and madams please help a newbie? Thank you!
I'm trying to download a zip file and save it from server using JWT token authentication thanks to Alamofire. The download works well without token authentication, the file is saved with success. When I activate the server-side authentication (using Passport.js with NodeJS), I always received 401. I attach the token to the header with the sessionManager adapter function. Others request (post, get using sessionManager.request(..) ) works well with this authentication mechanism.
Question is : Can we modify the header of Alamofire download function ? If yes how ?
Any advices appreciated
func getZip(){
let sessionManager = Alamofire.SessionManager.default
let authHandler = JWTAccessTokenAdapter(accessToken: Auth.getAccessToken())
sessionManager.retrier = authHandler
sessionManager.adapter = authHandler
let downloadUrl: String = Auth.getApiEndpoint() + "get_zip"
let destinationPath: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0];
let fileURL = documentsURL.appendingPathComponent("myZip.zip")
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
sessionManager.download(downloadUrl, method: .get, encoding: URLEncoding.httpBody, to: destinationPath)
.downloadProgress { progress in
print(">> Zip Download Progress: \(progress.fractionCompleted)")
}
.responseData { response in
switch response.result{
case .success:
if response.destinationURL != nil, let filePath = response.destinationURL?.absoluteString {
print("success & filepath : \(filePath)")
completionHandler(filePath, true)
}
break
case .failure:
print("faillure")
completionHandler("", false)
break
}
}
}
}
JWT Adapter :
class JWTAccessTokenAdapter: RequestAdapter {
typealias JWT = String
private var accessToken: JWT
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
var urlRequest = urlRequest
if let urlString = urlRequest.url?.absoluteString, urlString.hasPrefix(Auth.getApiEndpoint()) {
/// Set the Authorization header value using the access token.
urlRequest.setValue(accessToken, forHTTPHeaderField: "Authorization")
}
return urlRequest
}
}
Output :
response: SUCCESS: 12 bytes // (Unauthorized) -> Corrupted zip file
Without a validation step in your request chain, all responses will be considered successful. So check your response code (or just add .validate() before responseData) and see if your request is actually successful. Also, you may want to double check your parameter encoding, though you don't seem to be sending any parameters.
I want to fetch the google profile image when UID is given to me .
I have this reference but m getting how to hit this url .
Please anyone provide me some example.
EDIT:
Here is my code
var googleImageUrl: URL?{
let urlString = "https://www.googleapis.com/plus/v1/people/\(uid)?fields=image&key=AIzaSyBfjHpl8DjU0IGw9mXbvK6HoNpY"
return URL(string: urlString)
}
Alamofire.request(url)
.validate()
.responseJSON(completionHandler: { (response) in
if response.result.isSuccess {
let json = response.result.value as? [String: Any]
} else {
let apiError = ApiError(response: response)
}
})
when hitting this api, am always getting the error. Why i am not getting the response ?
You have two options:
Using Googles API, requires API key:
https://www.googleapis.com/plus/v1/people/{UID}?fields=image&key={YOUR_API_KEY}
Using Googles Picasaweb which does not require any API key:
http://picasaweb.google.com/data/entry/api/user/{UID}?alt=json
Code to get the image:
// Check what you want to return in the onCompletion and use it
func getImage(uid: String, onCompletion: #escaping (String) -> Void, onError: #escaping (NSError) -> Void) {
let url = "https://www.googleapis.com/plus/v1/people/\(uid)?fields=image&key=AIzaSyBfjHpl8DjU0IGw9mXbvK6HoNpY"
let headers = [
"Content-Type": "application/json"
]
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
if let object = response.result.value as? [String:Any] {
print(object)
// use the onCompletion in here
}
}
}
The reference you listed points to the Google People API, which is different than the Google+ People API. If you want to use the Google People API you should use https://people.googleapis.com/v1/people/{UID}?personFields=photo&key={YOUR_API_KEY}
There are official examples at: https://developers.google.com/people/v1/read-people#get-the-person-for-a-google-account
I try to manage rxswift & Alamofire to get response.
These functions get response successfully when token is not expired.
But when the token is expired, I don't know how to refresh token and then retry to get response using new token.
What should I do to refresh token and retry?
I also read Alamofire documents, and I find "RequestAdapter" and "RequestRetrier".
Should I use RequestAdapter & RequestRetrier in my case?
But I dont know how to use them in my "getRequestJSON" function,
or have any good idea to refresh token and retry.
Thanks.
func get(_ callback: #escaping (JSON) -> Void) {
let url = "http://106.xx.xxx.xxx/user"
self.getRequestJSON( .get, url: url, params: [:], callback: { json in
callback(json)
})
}
func getRequestJSON(_ method: Alamofire.HTTPMethod, url:String, params:[String:Any] = [:], callback: #escaping (JSON) -> Void) {
var headers:[String:String] = [String:String]()
if token.isEmpty == false {
headers["Authorization"] = "Bearer \(token)"
}
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
configuration.timeoutIntervalForRequest = timeout
_ = SessionManager(configuration: configuration)
.rx.responseJSON(method,
url,
parameters: params,
encoding: ((method == .get) ? URLEncoding.default : JSONEncoding.default),
headers: headers)
.subscribeOn(SerialDispatchQueueScheduler.init(qos: .background))
.subscribe(onNext: { (r, data) in
if r.statusCode == 401 {
//token fail
}
let json = JSON(data)
if json["status"].stringValue == "successful" {
callback(json)
}else {
callback(json)
}
}, onError: { (error) in
callback(JSON(error))
})
.addDisposableTo(ResfulAPIDisposeBag)
}
Below is the code of my URLRequestConvertible
enum Router: URLRequestConvertible {
static let baseURLString = "http://example.com/"
case LoginRequest(String, String)
case SignUpRequest(String)
case ForgotPasswordRequest(String)
var URLRequest: NSMutableURLRequest {
let result: (path: String, method: Method, parameters: [String: AnyObject]) = {
switch self {
case .LoginRequest(let userName, let password):
let params = [userNameKey: userName, passwordKey: password]
return ("/AppUsers/login", .POST, params)
case .SignUpRequest(let profile):
let params = [fullNameKey: profile]
return ("/AppUsers/add", .POST, params)
case .ForgotPasswordRequest(let emailId):
let params = [userNameKey: emailId]
return ("/AppUsers/forgot_password", .POST, params)
}
}()
let URL = NSURL(string: Router.baseURLString)
let request = NSMutableURLRequest(URL: URL!.URLByAppendingPathComponent(result.path))
let encoding = ParameterEncoding.URL
request.URLRequest.HTTPMethod = result.method.rawValue
return encoding.encode(request, parameters: result.parameters).0
}
}
Now, I have below request which is working fine:
Alamofire.request(.POST, CommunicationService.Router.LoginRequest(txtUsername.text!, txtPassword.text!).URLRequest, parameters: ["email_id": txtUsername.text!, "password": txtPassword.text!], encoding: ParameterEncoding.JSON, headers: nil).responseJSON(options: NSJSONReadingOptions.MutableContainers) { (response) -> Void in
print(response)
}
But I want to make the use of URLRequestConvertible for Parameter passing for POST request. Let me know what is the best way for POST request using below API:
request(.POST, CommunicationService.Router.LoginRequest(txtUsername.text!, txtPassword.text!).URLRequest).responseJSON(completionHandler: { (response) -> Void in
print(response)
})
Actually, above code is giving Invalid response with below error message
FAILURE: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
What's wrong with the request generated using request(Method, URLStringConvertible) method?
Can any one help me?
You need to use the other form of the request method.
let loginRequest = CommunicationService.Router.LoginRequest(username, password).URLRequest
Alamofire.request(loginRequest).responseJSON { in
print(response)
}
Otherwise you are only using the URLString from the original NSURLRequest being created by the Router.