Open chrisfoulds opened 8 years ago
So managed to get it working with a hack
In NXOauth2Connection.m / - (NSURLConnection *)createConnection;
I added in :
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", client.clientId, client.clientSecret];
[startRequest setValue:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField:@"Authorization"];
@chrisfoulds hey i had the same problem as you although your solution did not help me. do you think you could send your code
That is it ! - all the code I had to add was those two lines. I can't give the entire source file as it's under copyright
@chrisfoulds oh, i see.. I'm extremely new to github and oauth so any help would be very useful. I believe the error that I am still getting (the same one you got) has to do with the NXOAuth2Connect.m file. I may not have placed the code you used to hack it in the correct spot but its in the createConnetion method. All I can think of is that there is a bit of code in that method that has been deprecated to NSURLSession. I believe everything else I have is correct I just get the error 'Authorization header required' whenever I make a GET request.
//This is the code in my AppDelegate.m file
//OAuth config
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NXOAuth2AccountStore sharedStore] setClientID:@"XxXxXx"
secret:@"XxXxXxXxXx"
scope:[NSSet setWithObjects:@"activity", @"heartrate", @"location", @"nutrition", @"profile", @"settings", @"sleep", @"social", @"weight", nil]
authorizationURL:[NSURL URLWithString:@"https://www.fitbit.com/oauth2/authorize?response_type=token&client_id=227NJP&redirect_uri=myapp://handleOauthLogin&scope=activity%20heartrate%20location%20nutrition%20nutrition%20profile%20settings%20sleep%20social%20weight&expires_in=2592000"]
tokenURL:[NSURL URLWithString:@"https://api.fitbit.com/oauth2/access_token"]
redirectURL:[NSURL URLWithString:@"myapp://handleOauthLogin"]
keyChainGroup:@""
tokenType:@"Bearer"
forAccountType:@"fitbit"];
NSMutableDictionary *configuration = [NSMutableDictionary dictionaryWithDictionary:[[NXOAuth2AccountStore sharedStore] configurationForAccountType:@"fitbit"]];
NSDictionary *customHeaderFields = [NSDictionary dictionaryWithObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"];
[configuration setObject:customHeaderFields forKey:kNXOAuth2AccountStoreConfigurationCustomHeaderFields];
[[NXOAuth2AccountStore sharedStore] setConfiguration:configuration forAccountType:@"fitbit"];
[[NXOAuth2AccountStore sharedStore] requestAccessToAccountWithType:@"fitbit"];
return YES;
}
//Callback
- (BOOL) application:(UIApplication *)app openURL:(NSURL *)url options: (NSDictionary<NSString *, id> *)options
{
NSLog(@"We received a callback");
return [[NXOAuth2AccountStore sharedStore] handleRedirectURL:url];
}
//This is the code in my ViewController.m file
//I have two buttons - one handling login, the other using a GET to access a profile
- (IBAction)fitbitBtn:(id)sender
{
[[NXOAuth2AccountStore sharedStore]
requestAccessToAccountWithType:@"Fitbit"];
NSLog(@"LOGIN");
}
- (IBAction)getData:(id)sender
{
NSLog(@"GET DATA");
NXOAuth2Account *account = [[NXOAuth2AccountStore sharedStore] accountWithIdentifier:@"fitbit"];
[NXOAuth2Request performMethod:@"GET"
onResource:[NSURL URLWithString:@"https://api.fitbit.com/1/user/-/profile.json"]
usingParameters:nil
withAccount: account
sendProgressHandler:nil
responseHandler:
^(NSURLResponse *response, NSData *responseData, NSError *error){
NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[responseData bytes]]);
}];
}
//Here is the code in my NXOAuth2Connect.m file under -(NSURLConnection *)createConnection
- (NSURLConnection *)createConnection;
{
// if the request is a token refresh request don't sign it and don't check for the expiration of the token (we know that already)
NSString *oauthAuthorizationHeader = nil;
if (client.accessToken &&
![[requestParameters objectForKey:@"grant_type"] isEqualToString:@"refresh_token"]) {
// if token is expired don't bother starting this connection.
NSDate *tenSecondsAgo = [NSDate dateWithTimeIntervalSinceNow:(-10)];
NSDate *tokenExpiresAt = client.accessToken.expiresAt;
if (client.accessToken.refreshToken && [tenSecondsAgo earlierDate:tokenExpiresAt] == tokenExpiresAt) {
[self cancel];
[client refreshAccessTokenAndRetryConnection:self];
return nil;
}
NSString *tokenType = client.accessToken.tokenType;
if (tokenType == nil) {
tokenType = client.tokenType;
}
if (tokenType == nil) {
tokenType = @"OAuth";
}
oauthAuthorizationHeader = [NSString stringWithFormat:@"%@ %@", tokenType, client.accessToken.accessToken];
}
NSMutableURLRequest *startRequest = [request mutableCopy];
[self applyParameters:requestParameters onRequest:startRequest];
if (oauthAuthorizationHeader) {
[startRequest setValue:oauthAuthorizationHeader forHTTPHeaderField:@"Authorization"];
}
if (client.userAgent && ![startRequest valueForHTTPHeaderField:@"User-Agent"]) {
[startRequest setValue:client.userAgent forHTTPHeaderField:@"User-Agent"];
}
if (client.acceptType) {
[startRequest setValue:client.acceptType forHTTPHeaderField:@"Accept"];
}
//This next line gives the following warning - 'initWithRequest:delegate:startImmediately:' is deprecated: first deprecated in iOS 9.0 - Use NSURLSession (see NSURLSession.h)
//Not sure if that is part of the problem
NSURLConnection *aConnection = [[NSURLConnection alloc] initWithRequest:startRequest delegate:self startImmediately:NO];
[aConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[aConnection start];
if (!sendConnectionDidEndNotification) [[NSNotificationCenter defaultCenter] postNotificationName:NXOAuth2ConnectionDidStartNotification object:self];
sendConnectionDidEndNotification = YES;
//Here is the code you previously provided.. not sure if i placed it in the correct area
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", client.clientId, client.clientSecret];
[startRequest setValue:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField:@"Authorization"];
NSLog(@"%@", aConnection);
return aConnection;
}
@chrisfoulds also, not sure if this helps but if I move the two lines you provided in the 'NXOAuth2Connection.m' file up right before the NSURLConnection *aConnection bit I get the following error..
{"errors":[{"errorType":"invalid_client","message":"Invalid authorization header. Client id invalid. Visit https://dev.fitbit.com/docs/oauth2 for more information on the Fitbit Web API authorization process."}],"success":false}oper/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/Accounts.framework/Accounts
Like I said I'm not sure if I have your code in the correct location but I suppose that error shows that its a problem with the encoding for the clientID. I honestly have no clue what to do :(
Your error is different to mine... however So I just took a look at the code and my notes, totally forget I dropped this Oauth2 client as I could never get it to work. I used https://github.com/AFNetworking/AFOAuth2Manager and was up and running in less than a day. You do have to add the Bearer credential on each request (one line of code) but that is it.
@chrisfoulds ok thank you very much I will look into using AFNetworking
Hello, I had the same error. I added the next lines to fix this:
NSMutableDictionary *configuration = [NSMutableDictionary dictionaryWithDictionary:[[NXOAuth2AccountStore sharedStore] configurationForAccountType:@"fitbit"]];
NSString *authHeader = [NSString stringWithFormat:@"Basic %@", [[NSString stringWithFormat:@"%@:%@", kClientId, kClientSecretKey] base64EncodedString]];
[configuration setObject:@{@"Content-Type": @"application/x-www-form-urlencoded", @"Authorization": authHeader} forKey:kNXOAuth2AccountStoreConfigurationCustomHeaderFields];
[[NXOAuth2AccountStore sharedStore] setConfiguration:configuration forAccountType:@"fitbit"];
I am trying to connect to Fitbit in an iOS App https://dev.fitbit.com/docs/oauth2/#authorization-page
I have put this code in the app startup
In my callback I do
and I invoke the auth using :
and I have the notification handlers that return as failure.
The app launches, safari, I login , say everything is ok, it then asks to return to my app. I say ok, it returns but the notification from storing the token says
I just can not see what I have missed, any help appreciated.