get authorization from Fitbit using Oauth in iOS - ios

I want implement OAuth authentication for Fitbit to read the data from FitBit Api in my iOS app. I registered my app and i got clientId and client secret. I have been searched from past 2 days for tutorial, libraries. I am not any getting any idea about it. Please suggest me.

Note - According to https://dev.fitbit.com/docs/oauth2/
Applications should upgrade to OAuth 2.0 by March 14, 2016
Use safari or SFSafariViewController to open authorization page
Solution starts from here
please replace CLIENT_ID, REDIRECT_URI and other text to correct information
Point1-
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.fitbit.com/oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=activity%20nutrition%20heartrate%20location%20nutrition%20profile%20settings%20sleep%20social%20weight"]];
give proper scheme url, so that after successful login you will be redirected to your application. In openURL method you will get a OAUTHCODE
Point2-
Now get OAUTHTOKEN by using this OAUTHCODE
-(void)toGetRequestToken:(id)sender
{
NSString *strCode = [[NSUserDefaults standardUserDefaults] valueForKey:#"auth_code"];
NSURL *baseURL = [NSURL URLWithString:#"https://www.fitbit.com/oauth2/authorize"];
AFOAuth2Manager *OAuth2Manager = [AFOAuth2Manager managerWithBaseURL:baseURL clientID:CLIENT_ID secret:CONSUMER_SECRET];
OAuth2Manager.responseSerializer.acceptableContentTypes = [OAuth2Manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
NSDictionary *dict = #{#"client_id":CLIENT_ID, #"grant_type":#"authorization_code",#"redirect_uri":#"Pro-Fit://fitbit",#"code":strCode};
[OAuth2Manager authenticateUsingOAuthWithURLString:#"https://api.fitbit.com/oauth2/token" parameters:dict success:^(AFOAuthCredential *credential) {
// you can save this credential object for further use
// inside it you can find access token also
NSLog(#"Token: %#", credential.accessToken);
} failure:^(NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Point3-
now you can hit other FitBit requests like for "UserProfile" --
-(void)getFitbitUserProfile:(AFOAuthCredential*)credential{
NSURL *baseURL = [NSURL URLWithString:#"https://www.fitbit.com/oauth2/authorize"];
AFHTTPSessionManager *manager =
[[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
[manager.requestSerializer setAuthorizationHeaderFieldWithCredential:credential];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:#"https://api.fitbit.com/1/user/-/profile.json"
parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dictResponse = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
NSDictionary *userDict =[dictResponse valueForKey:#"user"];
NSLog(#"Success: %#", userDict);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"Failure: %#", error);
}];
}

Related

working with the latest token sent in my web service

I have a problem to find the latest token .. back end make the token change in every request so if I use it once it turned to be invalid in the next time, and they send the next valid token in Authorization header.
I am trying to get the latest token.
+(void)askServerUsingToken:(void (^)(NSDictionary * json,bool isSuccess))completionBlock{
// NSString* urlString = [NSString stringWithFormat:#"%#%#",baseURL,action];
//check token
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *token = [defaults stringForKey:#"token"];
if (token!= nil) {
NSString *finalyToken = [[NSString alloc]initWithFormat:#"%#",token];
NSString *profile=[NSString stringWithFormat:#"%#profile?token=%#",baseURL,finalyToken];
NSLog(#"%#",profile);
AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
manager.responseSerializer=[AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:finalyToken forHTTPHeaderField:#"Authorization"];
[manager GET:profile parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject){
dispatch_async(dispatch_get_main_queue(), ^{
// NSError *errorJson=nil;
// NSDictionary *jsonList=[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&errorJson];
NSDictionary *jsonList=(NSDictionary*)responseObject;
// completionBlock(jsonList,true);
if (jsonList !=nil) {
completionBlock(jsonList,true);
}else{
completionBlock(jsonList,false);
}
});
}failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error){
dispatch_async(dispatch_get_main_queue(),^{
completionBlock(nil,false);
});
}];
}else{
NSLog(#"no token");
}`enter code here`
}

Refresh access token automatically using AFOAuth2Manager

I have a server with OAuth 2.0 implemented for issuing access and refresh tokens. The client for this server is an iOS App written in Objective-C. I am currently using AFNetworking 3.0 for HTTP requests and AFOAuth2Manager to handle authorization. I want to refresh my access token stored in iOS app using the refresh token issued by the server before the access token expires (server returns number of seconds to expire as { 'expires_in': 3600 } (one hour)). Everything is working fine until the access token expires. Below is my code for handling requests and authorization.
- (AFJSONRequestSerializer *)setRequestSerializer
{
AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
User *currentUser = [User currentUser];
if (currentUser){
AFOAuthCredential *credentials = [AFOAuthCredential retrieveCredentialWithIdentifier:kEndpointServer];
if (!credentials.isExpired){
[serializer setAuthorizationHeaderFieldWithCredential:credentials];
}
}
return serializer;
}
- (AFJSONResponseSerializer *)setResponseSerializer
{
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
return serializer;
}
- (AFSecurityPolicy *)setSecurityPolicy
{
NSString *certFilePath = [[NSBundle mainBundle] pathForResource:#"cert" ofType:#"cer"];
NSData *certData = [NSData dataWithContentsOfFile:certFilePath];
NSSet *pinnedCerts = [NSSet setWithObject:certData];
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:pinnedCerts];
[policy setAllowInvalidCertificates:YES]; // DEVELOPMENT ONLY
[policy setValidatesDomainName:NO];
return policy;
}
- (AFHTTPSessionManager *)sessionManager
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = [self setSecurityPolicy];
manager.requestSerializer = [self setRequestSerializer];
manager.responseSerializer = [self setResponseSerializer];
return manager;
}
- (AFOAuth2Manager *)OAuth2Manager
{
NSURL *baseURL = [NSURL URLWithString:kEndpointServer];
AFOAuth2Manager *manager = [[AFOAuth2Manager alloc] initWithBaseURL:baseURL clientID:kParamAPIClientId secret:kParamAPIClientSecret];
manager.securityPolicy = [self setSecurityPolicy];
return manager;
}
- (void)loginUser:(NSDictionary *)user block:(void (^)(BOOL, NSError *))result
{
// Set endpoint URL
NSString *loginEndpointURL = [NSString stringWithFormat:#"%#%#", kEndpointServer, kEndpointLogin];
AFHTTPSessionManager *manager = [self sessionManager];
if ([self internetConnectionAvailable]){
[manager POST:loginEndpointURL parameters:user progress:nil success:^(NSURLSessionDataTask *task, id responseObject){
NSDictionary *responseDict = (NSDictionary *)responseObject;
BOOL success = (BOOL)[(NSNumber *)[responseDict objectForKey:kParamSuccess] boolValue];
NSString *msg = (NSString *)[responseDict objectForKey:kParamMessage];
if (success){
// Get user
NSDictionary *userLoggedIn = (NSDictionary *)[responseDict objectForKey:kParamUser];
//NSLog(#"Logged in.");
NSString *tokenEndpointURL = [NSString stringWithFormat:#"/api%#%#", kEndpointOAuth, kEndpointToken];
OAuth2Manager *OAuth2Manager = [self OAuth2Manager];
[OAuth2Manager authenticateUsingOAuthWithURLString:tokenEndpointURL username:(NSString *)[user objectForKey:kParamEmail] password:(NSString *)[user objectForKey:kParamPassword] scope:nil success:^(AFOAuthCredential *credentials){
NSLog(#"Credentials:");
NSLog(#"Access Token: %#", credentials.accessToken);
NSLog(#"Refresh Token: %#", credentials.refreshToken);
// Store credentials
[AFOAuthCredential storeCredential:credentials withIdentifier:kEndpointServer];
// Set current user
[User setCurrentUser:userLoggedIn];
result(YES, nil);
}failure:^(NSError *error){
NSLog(#"Error authenticating user: %#", error);
result(NO, error);
}];
} else {
result(NO, [NSError errorWithDomain:msg code:kEDHTTPRequestFailedErrorCode userInfo:nil]);
}
}failure:^(NSURLSessionDataTask *task, NSError *error){
result(NO, error);
}];
} else {
result(NO, [NSError errorWithDomain:kEDNoInternetConnectionErrorDomain code:kEDNoInternetConnectionErrorCode userInfo:nil]);
}
}
I have found a similar question on SO:
How to automatically refresh expired token with AFOAuth2Manager?
But the problem with the answer given is that it is outdated (Works with AFNetworking 2.X.X, but does not work with AFNetworking 3.0).
What is the best practice for handling the refreshing of the access token automatically?

retry request when the internet connection is back - IOS

I am using AFNetworking 3.0 to perform Web request in my application.
Is there a way to automatically retry a request when the internet is back?
This is the request code:
#try {
NSString *urlMuniByGov = [NSString stringWithFormat:#"%#/%#", URL_MUNICIPALITES, selectedGov.govID];
NSURL *url = [NSURL URLWithString:urlMuniByGov];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] init];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.securityPolicy.allowInvalidCertificates = YES;
[manager GET:url.absoluteString
parameters:nil
progress:nil
success:^(NSURLSessionDataTask * task, id responseObject) {
NSArray *muniNSArray = [responseObject objectForKey:#"municipalites"];
if ([muniNSArray isKindOfClass:[NSArray class]]){
for (NSDictionary *dictionary in muniNSArray) {
Municipality *munModel = [Municipality new] ;
munModel.munID = [dictionary objectForKey:#"id"];
munModel.munNameAr = [[dictionary objectForKey:#"nom"] objectForKey:#"ar"];
munModel.munNameFr = [[dictionary objectForKey:#"nom"] objectForKey:#"fr"];
[self.munsArray addObject:munModel];
[self.munsString addObject:munModel.munNameAr];
}
}
[municipalityText setItemList:[NSArray arrayWithArray:self.munsString]];
} failure:^(NSURLSessionDataTask * task, NSError * error) {
NSLog(#"Error: %#", error);
}];
}
#catch (NSException *exception) {
NSLog(#"Exception: %#", exception);
}
[[AFNetworkReachabilityManager sharedManager]setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Reachability: %#", AFStringFromNetworkReachabilityStatus(status));}];
if any changes in the net connection this block will call , so here u can retry a request
for additional information follow the link https://github.com/AFNetworking/AFNetworking#network-reachability-manager

YouTube api v3 Invalid Credentials access token

I am getting 401 Invalid Credentials error trying to use the Youtube API in the OAuth 2.0.
I used google sign in sdk and get access_token with params:
GIDSignIn *sharedSignIn = [GIDSignIn sharedInstance];
sharedSignIn.shouldFetchBasicProfile = NO;
sharedSignIn.scopes = [NSArray arrayWithObjects:
#"https://www.googleapis.com/auth/youtube.force-ssl",
#"https://www.googleapis.com/auth/youtube",
#"https://www.googleapis.com/auth/youtube.readonly",
// #"https://www.googleapis.com/auth/youtube.upload",
nil];
[sharedSignIn signIn];
Than I used AFNetworking library for GET request
- (void) getInformationWithParams: (NSDictionary *) params
method: (NSString *) method
onSuccess: (void(^)(NSDictionary *responseObject)) success
onFailure: (void (^) (NSError *error)) failure {
[self.requestOperationManager GET:method
parameters:params
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary *responseObject) {
NSLog(#"%#", responseObject);
if (success) {
success(responseObject);
}
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"getInformationWithParams Error: %#", error);
if (failure) {
failure(error);
}
}];
}
previously I did baseURL init
NSURL *baseURL = [NSURL URLWithString:#"https://www.googleapis.com/youtube/v3"];
self.requestOperationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
and in the end I get request through
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"snippet", #"part",
#"true", #"home",
myApiKey, #"key",
myAccessToken, #"access_token",
nil];
[[SMServerManager sharedManager] getInformationWithParams:params
method:#"activities"
onSuccess:^(NSDictionary *responseObject) {
}
onFailure:^(NSError *error) {
}];
I don't understand what I'm doing wrong.
PS: Requests work if they don't need to use acces_token.
It was a very stupid mistake. I'm confused in several google accounts and make wrong files for project.

iOS, How to like a page on facebook?

is there a way to like a page on a button Click.
I've tried many snippets like this one
NSURL *baseURL = [NSURL URLWithString:#"https://graph.facebook.com/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
NSString *link = [NSString stringWithFormat:#"/%#/likes", #"6783623567"];
NSDictionary *params = #{#"access_token" : [[[FBSession activeSession] accessTokenData] accessToken]};
[httpClient postPath:link parameters:params success:^(AFHTTPRequestOperation *op, id result) {
NSLog(#"result %#", result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error %#", error);
}];
but it fails with "Application does not have the capability to make this API call.","type":"OAuthException","code":3".
what I'm doing now is to open the link inside a webview.
Everything here for the code, and here for the publishing actions on Facebook, such as likes... :)

Resources