i build project swift with OAuth and i already got Acces Token from my API Login and then i want get data from API JSon with my acces token. so, how to use OAuth get request http method with OAuth and my acces token
i have json parse standar without OAuth
let url = NSURL(string: "https://conversation.8villages.com/1.0/contents/articles?state=published")
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request as URLRequest) { data,response,error in
guard error == nil && data != nil else {
print("error", error!)
return
}
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200
{
if data?.count != 0
{
let responString = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(responString)
}
else{
print("No got data from URL")
}
}
else
{
print("error httpstatus code is ", httpStatus!.statusCode)
}
}
task.resume()
i'm used Librabry https://github.com/OAuthSwift/OAuthSwift
in there i got Signed Request (Readme.md) like this
oauthswift.client.get("https://api.linkedin.com/v1/people/~",
success: { response in
let dataString = response.string
print(dataString)
},
failure: { error in
print(error)
}
)
but im confused how to add my Acces Token, Consumer Key and My Consumer Secret to acces my API JSON
If you have got the access token, it seems you have already used your consumer key and consumer secret and you are authenticated. You need to pass the bearer access token in the authorization header of API get call.
I'm not familiar with OAuthSwift framework but I guess the error is in the following row:
request.addValue("application/json", forHTTPHeaderField: "Authorization")
Maybe it should be:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(tokenType + " " + accessToken, forHTTPHeaderField: "Authorization")
Where tokenType for a OAuth Authorization Code grant type always is the string Bearer and accessToken is of course the access token you have got from earlier.
EDIT:
Compare with the Microsoft Azure AD:
GET /v1.0/me/messages
Host: https://graph.microsoft.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...
Related
I need to resume my WebService if my bearer token expire by http code 401 ,
below is my code.
When a 401 error occurs that means the Access Token has expired and I need to send a Refresh Token over to my server to obtain a new Access Token.
After getting a new Access Token I need to redo the previous request that got the 401 error.
Suppose I hit webservice1 and its give 401 http code , then new bearer token request will generate and the same API resume to work. How can I do it ?
import UIKit
import CryptoKit
class SharedWebService: NSObject {
static let sharedApiInstance = SharedWebService()
func generalApiMethod (parameter : NSDictionary ,completion: #escaping ((NSMutableArray?) -> Void))
{
var dashboarddata : NSMutableArray = NSMutableArray()
let urlString = String(format:"URL OF API HERE")
let url = URL(string: urlString)
guard let requestUrl = url else { fatalError() }
var request = URLRequest(url: requestUrl)
request.timeoutInterval = 60
let bearerToken = "current bearer token"
request.setValue(bearerToken, forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: request) {
(data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
if httpResponse.statusCode == 401
{
// Refresh bearerToken get here
let bearerToken = self.getBearerTokenDevice() //fetch api to get new bearer token
return
}
}
guard error == nil else {
print(error!.localizedDescription);
DispatchQueue.main.async{
completion(dashboarddata)
}
return
}
guard let jsonData = data else { print("Empty data"); return }
if String(data: jsonData, encoding: String.Encoding.utf8) != nil
{
do {
let responseJSON = try? JSONSerialization.jsonObject(with: jsonData, options: [])
if let responseJSON = responseJSON as? [String: Any] {
//Success case do here reponse return
completion(dashboarddata)
}
}
}
}.resume()
}
func getBearerTokenDevice()-> String
{
//how to handle it
return "New bearer token from api fetch"
}
}
work arround is,
Always call Api at splah which fetches Bearer token from server, it will refresh the token every time user opens the app,
2.1 make Api call Queue to process Api calls (Use generics here)
2.2 if api is successfull, Ok. if not than call a special Api call yo get the token,
2.3 if after fetching the token, get last api from Api Queue and call it..
its just an idea, how i think, i think it will be done, might be different in your case
https://stevenpcurtis.medium.com/use-operationqueue-to-chain-api-calls-in-swift-71eefd6891ef
here is guide to make Api call chain
Here is my scenario. I have my valid accessToken, which I have already used to retrieve info from user profile. Below is the steps I have been trying to post using that token. I have been receiving statusCode = 401
linkedinHelper.authorizeSuccess({ [unowned self] (lsToken) -> Void in
self.writeConsoleLine("Login success lsToken: \(lsToken)")
print("\(lsToken.accessToken ?? "")")
let targetURLString = "https://api.linkedin.com/v1/people/~/shares?oauth2_access_token=\(lsToken.accessToken ?? "")&format=json"
let payloadStr: String = "{\"comment\":\"Check out developer.linkedin.com!\",\"visibility\":{\"code\":\"anyone\"}}"
// Initialize a mutable URL request object.
let request = NSMutableURLRequest(url: NSURL(string: targetURLString)! as URL)
// Indicate that this is a GET request.
request.httpMethod = "POST"
request.httpBody = payloadStr.data(using: String.Encoding.utf8)
// Add the access token as an HTTP header field.
request.addValue("Bearer \(lsToken.accessToken ?? "")", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("json", forHTTPHeaderField: "x-li-format")
// Make the request.
let task: URLSessionDataTask = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
// Get the HTTP status code of the request.
let statusCode = (response as! HTTPURLResponse).statusCode
if statusCode == 201 {
// Convert the received JSON data into a dictionary.
guard ((try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any]) != nil else {
print("Not containing JSON")
return
}
print("successfully posted.")
}
}
task.resume()
}, error: { [unowned self] (error) -> Void in
self.writeConsoleLine("Encounter error: \(error.localizedDescription)")
}, cancel: { [unowned self] () -> Void in
self.writeConsoleLine("User Cancelled!")
})
LinkedIn v1 API is no longer supported. You will need to use their v2 APIs: https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin?context=linkedin/consumer/context
Your target URL should use the ugcPosts endpoint:
POST https://api.linkedin.com/v2/ugcPosts
In addition to Christopher's point, I'm afraid Linkedin doesn't appear to be processing the queue of people waiting for access to v2 of the API - we requested access 5 months ago, nothing has changed. We were using v1 of the API for 2 years without any issues, then one day they switched us off with no method of getting transferred to the new API.
U P D A T E D... The function with what works!
I would like to incorporate the yelp api into an app but can't successfully pass my authorization token on the URL string. Do I need to do something to connect the URLRequest to the URLSessoin call and its not using the header? Maybe the key value pairs is wrong? The below function returns:
error = {
code = "TOKEN_MISSING";
description = "An access token must be supplied in order to use this endpoint.";
};
I was able to use postman to get the yelp API call working, but only by clicking the "Header" section on postman and putting in Bearer and then my yelp key. I googled around a bit and found some links that indicate that you can add a header to the URLSession that I assume would work the way postman does but I haven't been able to get it to work.
I know there are some githubs with yelp API repos but I am trying to not install a large set of code that I don't understand into my app, when all I want is the JSON that I can see is coming through on postman. Can anyone help me understand how I would edit code similar to the Here example below so that I can get the Authorization/Bearer that yelp requires?
func getYelp() {
let appSecret = "Bearer <YELP APIKEY>"
let link = "https://api.yelp.com/v3/businesses/search?latitude=37.786882&longitude=-122.399972"
if let url = URL(string: link) {
// Set headers
var request = URLRequest(url: url)
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue(appSecret, forHTTPHeaderField: "Authorization")
print("Attempting to get places around location from Yelp")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject // Added "as anyObject" to fix syntax error in Xcode 8 Beta 6
print("Printing all JSON/n/n//n--------------------------")
print(jsonResult)
print("Printing from results/n/n//n--------------------------")
if let description = ((jsonResult["search"] as? NSDictionary)?["context"] as? NSDictionary)?["href"] as? String {
} else {
print("JSON pull failed/n/n//n--------------------------")
}
} catch {
print("JSON Processing Failed/n/n//n--------------------------")
}
}
}
}
task.resume()
} else {
resultLabel.text = "Couldn't get results from Here"
}
}
You're mixing up between the headers and the url, you need to set your headers correctly
if let url = URL(string: "https://places.cit.api.here.com/places/v1/discover/around?at=37.776169%2C-122.421267&app_id=\(app_id)&app_code=\(app_code)") {
var request = URLRequest(url: url)
// Set headers
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue("Authorization", forHTTPHeaderField: "Bearer " + token // Token here)
print("Attempting to get places around location")
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// ...
Lets say you have an api with "https://google.com" (this is just an example with fake keys)
and an api key that is "ApiKey: 92927839238293d92d98d98d92".
You would then take this information and do this.
let uri = URL(string:"https://google.com")
if let unwrappedURL = uri {
var request = URLRequest(url: unwrappedURL)request.addValue("92927839238293d92d98d98d92", forHTTPHeaderField: "ApiKey")
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
// you should put in error handling code, too
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
// HERE'S WHERE YOUR DATA IS
print(json)
} catch {
print(error.localizedDescription)
}
}
}
dataTask.resume()
}
Please remember that you would replace the google.com with your GET address and the APIKey header with your own api key values.
Also, this will print out all the JSON like in PostMan.
If this works for you, then I also have a link on accessing the JSON Objects.
I confuse by getting HTTP response in post method. when i check response on postman, then the required response is got and profile updated successfully. But in programmatically i got error notice. What was the problem? how to solve it? please, refer screenshots. Thanks in advance!
Code i have try
override func viewDidLoad() {
super.viewDidLoad()
self.updateDetails()
}
func updateDetails()
{
let postString = "api=update_people&user_id=18&email=rajesh#gmail.com&first_name=Raejsh&phone=456562&age=26&gender=male&blood_group=A"
print(postString)
// let alertMessage = alert()
let url = NSURL(string: "http://kuruthi.in/portal/api/register")
let request = NSMutableURLRequest(url: url as! URL)
request.httpBody = postString.data(using: String.Encoding.utf8)
request.httpMethod = "POST"
request.addValue("123456", forHTTPHeaderField: "X-API-KEY")
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest) { data,response,error in
guard error == nil && data != nil else
{
print("Error:\(error)")
return
}
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200
{
if data?.count != 0
{
let responseString = String(data: data!, encoding: .utf8)
print(responseString)
}
else
{
print("No data got from url!")
}
}
else
{
print("error httpstatus code")
}
}
task.resume()
}
Response in Program output :
Response in postman:
The reason you are getting html code is that you are receiving some error from your web services look at the message "A PHP Error was encountered" in your output log.
The success in postman is because your request is in form-data. Compare the request from postman from Raw with the request you are generating.
You can refer this link for creating a request. But the code is in Objective-Cand you can use this link to convert the code, or you can use Alamofire to create requests and refer this link for creating multipart form-data requests using Alamofire
I am trying to make an HTTP request to the Imgur API. I am trying to retrieve all images associated with the tag "cats." The url, according to the Imgur API is: https://api.imgur.com/3/gallery/t/cats
the Imgur API states the following about the authorization needed to make get requests:
For public read-only and anonymous resources, such as getting image
info, looking up user comments, etc. all you need to do is send an
authorization header with your client_id in your requests. This also
works if you'd like to upload images anonymously (without the image
being tied to an account), or if you'd like to create an anonymous
album. This lets us know which application is accessing the API.
Authorization: Client-ID YOUR_CLIENT_ID
I've looked at the following questions and tried things suggested there, but none of them have helped.
JSON NSURLRequest with credentials
Swift GET request with parameters
How to make a Http get and set httpHeader in Swift?
My current code is this:
let string = "https://api.imgur.com/3/gallery/t/cats"
let url = NSURL(string: string)
let request = NSMutableURLRequest(URL: url!)
request.setValue("clientIDhere", forHTTPHeaderField: "Authorization")
//request.addValue("clientIDhere", forHTTPHeaderField: "Authorization")
request.HTTPMethod = "GET"
let session = NSURLSession.sharedSession()
let tache = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if let antwort = response as? NSHTTPURLResponse {
let code = antwort.statusCode
print(code)
}
}
tache.resume()
But I continually get a status code of 403, meaning authorization is required. What am I doing wrong?
I think you need to prepend Client-ID string to your actual client ID as for the header value:
request.setValue("Client-ID <your_client_id>", forHTTPHeaderField: "Authorization")
Updated for swift 4 :
func fetchPhotoRequest(YOUR_CLIENT_ID: String) {
let string = "https://photoslibrary.googleapis.com/v1/albums"
let url = NSURL(string: string)
let request = NSMutableURLRequest(url: url! as URL)
request.setValue(YOUR_CLIENT_ID, forHTTPHeaderField: "Authorization") //**
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let mData = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if let res = response as? HTTPURLResponse {
print("res: \(String(describing: res))")
print("Response: \(String(describing: response))")
}else{
print("Error: \(String(describing: error))")
}
}
mData.resume()
}