Authorization header required Fitbit Swift oauth - swift

So the error I am getting is:HTTP Status 401: Unauthorized, Response: {"errors":[{"errorType":"invalid_request","message":"Authorization header required.
The code I have to authorize Fitbit is :
func authorizeFitbit(completion: (result: Bool) -> Void ){
oauthswift.accessTokenBasicAuthentification = true
let state: String = generateStateWithLength(20) as String
oauthswift.authorizeWithCallbackURL( NSURL(string: "xxxxxxxxx")!, scope: "xxxxxxxxxxxxx", state: state, success: {
credential, response, parameters in
self.getUserProfile(){
(result: Bool) in
completion(result: result)
}
}, failure: { error in
print(error.localizedDescription)
completion(result: false)
})
}
I am able to grab profile information but when I am trying to grab more information from fitbit by clicking on an IBAction button, I am required to use this authorize function again to grab the number of steps.

The question may need more details to be properly answered.
What OAuth grant type are you using?
What is the oauthswift class you are using? Your own or third party?
You are stating that you are able to grab profile information. Should that be read as you been able to get the whole way through for whatever grant type you are using but get problems when you want to execute a new request to the resource server?
Some other OAuth implementations require you to set the Authorization HTTP-header with the actual token type and the actual access_token when you send your requests to the resource server. The following is an example for Microsoft Azure AD using Authorization Code flow:
GET /v1.0/me/messages
Host: https://graph.microsoft.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU...
Another possibility, if I compare to the "Authorization Code" grant type, the "invalid_request" error implies that you have not got pass the first stage in the request flow, that error you get before requesting the access token.
EDIT: Didn't see how old this question was. Well, I let the reply be here anyway, maybe it helps someone one day...

Related

HUAWEI Push - API for obtaining an access token not working

When I use this api to get access token:
https://oauth-login.cloud.huawei.com/oauth2/v3/token?grant_type=client_credentials&client_id=****&client_secret=****
it always returns
{
"sub_error": 20001,
"error_description": "missing required parameter: client_id",
"error": 1102 }
although I send client_id parameter
To solve the issue, Please make sure the below points
You are doing post request to the server
Make sure that the POST URL is “https://oauth-login.cloud.huawei.com/oauth2/v3/token”. Do not include post parameters in the URL
Add below parameters in body of POST request but not in the URL as mentioned here ( https://oauth-login.cloud.huawei.com/oauth2/v3/token?grant_type=client_credentials&client_id=****&client_secret=**** )
grant_type=client_credentials
client_id=****
client_secret=****
For more details about fetching the access token, please refer the below link:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/open-platform-oauth-0000001053629189-V5#EN-US_TOPIC_0000001053629189__section12493191334711
Please use the following scheme instead for oath authentication:
https://oauth-login.cloud.huawei.com/oauth2/v3/authorize?grant_type=client_credentials&client_id=\*\*\*\*&client_secret=\*\*\*
If you don't give this a valid client_id it will say that you have a "invalid client_id" instead of saying it's empty. Hope this helps. (The change is that the original says .../token? and this says .../authorize?)

Calling Google Sheets API in Swift with GTMAppAuth

I'm trying to read/write to Google Sheets in Swift on macOS.
I'm using the GAppAuth library which in turn makes use of GTMAppAuth.
I managed to get authorized and get back both the access token and the refresh token but I still get an HTTP status code of 403 when I try to make a call to one of the Google Sheets' endpoints.
In applicationDidFinishLaunching(_:) I appended the following authorization scope, as detailed in the documentation:
GAppAuth.shared.appendAuthorizationRealm("https://www.googleapis.com/auth/spreadsheets.readonly")
But still, I get 403. What am I doing wrong? Am I adding the scope properly?
This is the code where I make the API call:
#IBAction func getSpreadsheet(_ sender: NSButton) {
let fetcherService = GTMSessionFetcherService()
fetcherService.authorizer = authorization
let spreadsheetInfo = URL(string: "https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetID}")
let fetcher = GTMSessionFetcher(url: spreadsheetInfoEndpoint)
fetcher.beginFetch { (data, error) in
//Error code 403
}
}
I got it working by looking at the cURL request with the Google API Explorer. The access token parameter was missing:
https://sheets.googleapis.com/v4/spreadsheets/[SPREADSHEETID]/values/[RANGE]?access_token=[access_token]
Also thanks to Jacques-Guzel Heron, in the comment section, who let me know of the official Google Auth Library for Swift. I'll check it out.

Realm Sync Facebook Authentication not working

I am trying to enable Facebook authentication in Realm Sync, but keep getting an error on login.
I have been using these guides:
https://docs.realm.io/sync/v/3.x/using-synced-realms/user-authentication/additional-providers#facebook
https://docs.realm.io/sync/v/3.x/self-hosted/customize/authentication/included-third-party-auth-providers/facebook-authentication
I have the Access Token provided by the Facebook API/SDK enabling me to log in/sign up a user.
When I use Realm's libraries to log in a user with the Facebook Access Token, I get an error stating the 'provider' parameter is invalid, but this parameter is defined by Realm's own classes.
I have successfully authenticated a user with an email & password so do I need to set up something else on Facebook/Realm Sync? It seems Facebook authentication just doesn't work in Realm Sync and the above help files are pretty useless.
Authentication code
func authenticateWithFacebook(facebookToken: String, completion: #escaping (RealmAuthenticationResult) -> ()) {
let credentials = SyncCredentials.facebook(token: facebookToken)
print("------FACEBOOK LOGIN-------")
print("Token: \(facebookToken)")
login(credentials) { (result, userId) in
completion(result)
}
}
private func login(_ credentials: SyncCredentials, completion: #escaping (RealmAuthenticationResult, String?) -> ()) {
SyncUser.logIn(with: credentials, server: RealmConnection.AUTH_URL, onCompletion: { (user, err) in
if let _ = user {
print("User has logged in/signed up")
return completion(RealmAuthenticationResult.success(true), user?.identity)
} else if let error = err {
print(error.localizedDescription)
return completion(RealmAuthenticationResult.failure(error), user?.identity)
}
})
}
The error
Error Domain=io.realm.sync.auth Code=601 "Your request parameters did
not validate. provider: Invalid parameter 'provider'!;"
UserInfo={NSLocalizedDescription=Your request parameters did not
validate. provider: Invalid parameter 'provider'!;}
Other things I have tried
I have tried directly instantiating the base provider class 'RLMIdentityProvider' and creating SyncCredentials with that, but no dice.
A workaround is to get the account information from the Facebook API/SDK and use the account's email to login/signup with a username/password setup. However, it seems to make Facebook authentication redundant.
That Realm Documentation link is outdated. See the 3.16.0 Documentation (or later) as a lot was changed.
At the moment Password, JWT & Firebase are the only auth options with Firebase Authentication being a very solid solution. Integrating Firebase is also covered in the Realm Documentation in the Using Sync'd Realms -> Authentication section. I won't link it as the documentation is being frequently updated now days.
As stated by the Realm Team (several times) extensive auth options are not a priority as other companies (like Firebase) handle it very well.
There were a number of posts on the Realm forums speaking to this but Ian's response to this question is very succinct.
we have and will continue to prioritize synchronization features for
mobile
and then
This is why we recommend that a production app should outsource user
management and authentication to a company which specialized in these
features.

Is it a good practice to reload credentials before every request?

I'm working on an iOS app that works with a backend made in laravel, this api manage login and information exchange via JSON web tokens.
To prevent the user to access a web route with an expired token I check the user's credentials before every web call.
My question is, is it a good practice? Because when I started thinking about it the user is accessing twice the amount of times to my server.
For example this is the function to access they're information.
/// Get user's info form the database
///
/// - Parameter completed: Completition Block
func getInfo(completed: #escaping DownloadComplete){
let token = self.getToken()
print(self.getError())
if(token != nil && token != ""){
//Here is where I check credentials.
self.checkCredentials(completed: {
let url = "\(Base_URL)\(myInfo)\(self.getToken() ?? "")"
Alamofire.request(url, method: HTTPMethod.get).responseJSON { respone in
if let result = respone.result.value as? Dictionary<String, AnyObject>{
if let user = result["User"] as? Dictionary<String, AnyObject>{
var Info = Alumno()
if let id = user["id"] as? Int64!{
Info.id = id
}
...
self.userInfo = Info
completed()
}
}
}
})
}
}
The check credentials functions asks the server if the user's token is still valid and if it is it returns
{
"Status": "Success"
}
My answer assumes your server validates the token, and you are not relying on the app to validate the token.
With that assumption, I think it depends on what you can do if the token is expired.
If the only thing you can do is prompt the user to sign in again, then I would probably just make the web request and handle the 401 Not Authorized.
However, if you have the ability to silently refresh the user's token, you may want to preemptively refresh the token if is close to expiring.
In my application, before every web request the app checks if the user's access token will expire within the next 3 minutes, and if so, attempts to refresh it before making the request. If the refresh is successful, the web request is made with the new access token. If the refresh fails, the web request is not made and the app prompts the user to sign in instead. If for any reason the web request still fails after that with 401, the app prompts the user to sign in.
I would do it like once every time the user opens the app not every call.
Other options:
You could also give them a code that they enter that's good for so long.
You could have them sign in when they first download the app. Then they would always be logged in. Then when the token is expired a little popup would say "Something Something Something"

Non-Google Account Using chrome.identity

I'm trying to make a Gogle Chrome extension that requires user authorization to a SugarCRM 7.5 instance with OAuth 2.0 and I need to store the access token that's retrieved. I may need more clarification on how launchWebAuthFlow works.
Firstly, I can retrieve an access token from SugarCRM by using a POST request (not a GET request) that returns an access and a refresh token.
When I tried using the code below I kept getting the error: "authorization url can not be loaded" and when I checked the background console (I already know that my auth URL is wrong). Any help is appreciated even if you don't know SugarCRM. Just a general answer that can get me started is much appreciated.
manifest.json
{
"name": "Auth Sample",
"version": "1",
"manifest_version": 2,
"minimum_chrome_version": "29",
"key": "<long key>",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
"identity",
"https://<sugar instance>/*"
]
}
Background.js
chrome.identity.launchWebAuthFlow(
{'url': '<url-to-do-auth>', 'interactive': true},
function(redirect_url) { console.log(redirect_url); });
My URL is definitely not gonna work here but it's something like this:
var client_id = '<client id from Oauth 2.0>';
var redirectUri = chrome.identity.getRedirectURL("sugarcrm");
var url = "https://<sugar instance base url>/rest/v10/oauth2/token?client_id=" + client_id + "&callbackURL=" + redirectUri + "&response_type=token"
What's the url-to-do-auth (is this the URL to do a regular login (username and password) to SugarCRM or is it a GET request through the REST API to do login)
I don't have a UI web auth flow for my SugarCRM instance. Is it possible to create one from the application or should that be on the server?
I can only make POST requests to get an access token. Will that still work with launchWebAuthFlow?
Update
I ended up storing the token using the local chrome.storage api and only stored the refresh token which will keep getting a new access token every time the application is run(I think it's more secure than just storing the access token as that will force it to always keep changing without passing other credentials)
After more search on launchWebAuthFlow. I found out that the url launchWebAuthFlow takes as parameter will launch a web page(with interactive parameter set to true) which is hosted on the server, that will let the user login and will return an access token if success. This url is actually an endpoint on the restful server. You need to create this endpoint that will be a get request with some parameters including a callbackURL, client_id and response_type. Then it will respond with another function that will be a post request and will take the username and password. If credentials are correct, it will return the access token as a parameter in the callbackURL(chrome extension specific url that contains the extension ID).
Please feel free to correct me or add something if I'm wrong.