2013-04-10 4 views
8

Я весь день ломаю голову над этим.Внедрение OAuth 1.0 в приложении iOS

Я хочу интегрировать приложение iOS с Withings api. Он использует OAuth 1.0, и я не могу полностью понять, как его реализовать.

Я загружал несколько фреймов OAuth (, gtm-oauth, ssoauthkit), но не смог понять, что именно я должен делать.

Я много искал, также в переполнении стека для хороших ссылок о том, как реализовать реализацию OAuth 1.0 вообще &, интегрируя с Withings, в частности, без успеха.

Просьба пояснить поток интеграции приложения iOS с api, для которого требуется OAuth 1.0. Примеры кода были бы очень полезными. Рекомендуемые сторонние рамки тоже понравятся.

Чтобы уточнить, я полностью понимаю принципы OAuth 1.0, у меня просто проблемы с реализацией в моем приложении.

Я думаю, что тщательный ответ с примерами кода и хорошими ссылками был бы очень полезен для многих людей, поскольку я не мог его найти. Если у кого-то есть хороший опыт его реализации, пожалуйста, найдите время, чтобы поделиться им.

+0

Вы смотрели на [пример проекта включены в ГТМ-OAuth] (https://github.com/jdg/gtm-oauth/tree/master/Examples/OAuthSample)? – bdesham

+0

да есть. Эти примеры проектов действительно трудно ориентироваться и полностью их понимать. –

+0

Существует много плохого кода OAuth, особенно для iOS. Так что будьте осторожны. Единственным достойным, с которым я когда-либо сталкивался, был Google (gtm-oauth), так что я получил +1 от меня. –

ответ

11

TDOAuth, на мой взгляд, было лучшим решением. это чистый и простой, только один .h и .m файл для работы, а не сложные примеры проектов ..

Это является OAuth 1.0 поток:

шаг 1 - получить запрос маркера

//withings additional params 
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 
[dict setObject:CALL_BACK_URL forKey:@"oauth_callback"]; 

//init request 
NSURLRequest *rq = [TDOAuth URLRequestForPath:@"/request_token" GETParameters:dict scheme:@"https" host:@"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:nil tokenSecret:nil]; 

//fire request 
NSURLResponse* response; 
NSError* error = nil; 
NSData* result = [NSURLConnection sendSynchronousRequest:rq returningResponse:&response error:&error]; 
NSString *s = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; 
//parse result 
NSMutableDictionary *params = [NSMutableDictionary dictionary]; 
NSArray *split = [s componentsSeparatedByString:@"&"]; 
for (NSString *str in split){ 
    NSArray *split2 = [str componentsSeparatedByString:@"="]; 
    [params setObject:split2[1] forKey:split2[0]]; 
} 

token = params[@"oauth_token"]; 
tokenSecret = params[@"oauth_token_secret"]; 

шаг 2 - получить авторизацию маркера (загрузив запрос в UIWebView, метод webViewDidFinishLoad делегат будет обрабатывать вызов обратно ..)

//withings additional params 
NSMutableDictionary *dict2 = [NSMutableDictionary dictionary]; 
[dict setObject:CALL_BACK_URL forKey:@"oauth_callback"]; 

//init request 
NSURLRequest *rq2 = [TDOAuth URLRequestForPath:@"/authorize" GETParameters:dict2 scheme:@"https" host:@"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:token tokenSecret:tokenSecret]; 

webView.delegate = self; 
[DBLoaderHUD showDBLoaderInView:webView]; 
[webView loadRequest:rq2]; 

обрабатывать WebView, как следовать, чтобы начать шаг 3 (я знаю, что isAuthorizeCallBack пахнет много, но он делает работу, следует реорганизовать его ..)

- (void)webViewDidFinishLoad:(UIWebView *)aWebView 
{ 
    [DBLoaderHUD hideDBLoaderInView:webView]; 

    NSString *userId = [self isAuthorizeCallBack]; 
    if (userId) { 

     //step 3 - get access token 
     [DBLoaderHUD showDBLoaderInView:self.view]; 
     [self getAccessTokenForUserId:userId]; 
    } 

    //ugly patchup to fix an invalid token bug 
    if ([webView.request.URL.absoluteString isEqualToString:@"http://oauth.withings.com/account/authorize?"]) 
    [self startOAuthFlow]; 
} 

- (NSString *)isAuthorizeCallBack 
{ 
    NSString *fullUrlString = webView.request.URL.absoluteString; 

    if (!fullUrlString) 
     return nil; 

    NSArray *arr = [fullUrlString componentsSeparatedByString:@"?"]; 
    if (!arr || arr.count!=2) 
     return nil; 

    if (![arr[0] isEqualToString:CALL_BACK_URL]) 
     return nil; 

    NSString *resultString = arr[1]; 
    NSArray *arr2 = [resultString componentsSeparatedByString:@"&"]; 
    if (!arr2 || arr2.count!=3) 
     return nil; 

    NSString *userCred = arr2[0]; 
    NSArray *arr3 = [userCred componentsSeparatedByString:@"="]; 
    if (!arr3 || arr3.count!=2) 
     return nil; 

    if (![arr3[0] isEqualToString:@"userid"]) 
     return nil; 

    return arr3[1]; 
} 

- (void)startOAuthFlow 
{ 
    [self step1]; 
    [self step2]; 
} 

и, наконец, - шаг 3 - получить доступ токенов

- (void)getAccessTokenForUserId:(NSString *)userId 
{ 
    //step 3 - get access token 

    //withings additional params 
    NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 
    [dict setObject:CALL_BACK_URL forKey:@"oauth_callback"]; 
    [dict setObject:userId forKey:@"userid"]; 

    //init request 
    NSURLRequest *rq = [TDOAuth URLRequestForPath:@"/access_token" GETParameters:dict scheme:@"https" host:@"oauth.withings.com/account" consumerKey:WITHINGS_OAUTH_KEY consumerSecret:WITHINGS_OAUTH_SECRET accessToken:token tokenSecret:tokenSecret]; 

    //fire request 
    NSURLResponse* response; 
    NSError* error = nil; 
    NSData* result = [NSURLConnection sendSynchronousRequest:rq returningResponse:&response error:&error]; 
    NSString *s = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; 

    //parse result 
    NSMutableDictionary *params = [NSMutableDictionary dictionary]; 
    NSArray *split = [s componentsSeparatedByString:@"&"]; 
    for (NSString *str in split){ 
     NSArray *split2 = [str componentsSeparatedByString:@"="]; 
     [params setObject:split2[1] forKey:split2[0]]; 
    } 

    [self finishedAthourizationProcessWithUserId:userId AccessToken:params[@"oauth_token"] AccessTokenSecret:params[@"oauth_token_secret"]]; 
} 
+0

Я внедрил ваш код, но я застрял на шаге 3. Я показываю страницу входа Withings в webview, но всегда возвращается с «Недопустимый токен присяги». Я что-то упускаю? Заранее спасибо. – Dmorneault

+0

@Dmorneault, я отредактировал ответ с небольшим исправлением. посмотрите на метод webViewDidFinishLoad и добавьте код под маркой «уродливое исправление», чтобы исправить недопустимую ошибку маркера. обратите внимание на то, что он вызывает метод с именем «startOAuthFlow», который снова просто step1 и step2. Кажется, проблема кэширования, и я попытался разрешить ее с поддержкой Withings, но я закончил тем, что прожил этот уродливый, но рабочий патч. –

+0

как вы создали запросы на взаимодействие с API после аутентификации? –

0

Я предлагаю вам проверить этот проект как в качестве ссылки, так и в качестве действительно работающего класса OAuth. Он наследуется от другого замечательного проекта, поэтому вам нужно будет добавить и то, и другое. Проверьте, соответствует ли ваша лицензия вашим требованиям. https://github.com/rsieiro/RSOAuthEngine

+0

Если проект устарел, бесполезен для downvote. Во время ответа он отлично работал, и я успешно использовал приложение. – Andrea

2

Я дополнительно сохранить заголовки запроса здесь

NSMutableDictionary *dict2 = [NSMutableDictionary dictionary]; 
[dict2 setObject:CALL_BACK_URL forKey:@"oauth_callback"]; 
NSURLRequest *rq2 = [TDOAuth URLRequestForPath:@"/authorize" 
           GETParameters:dict2 
             scheme:@"https" 
              host:@"oauth.withings.com/account" 
            consumerKey:WITHINGS_OAUTH_KEY 
           consumerSecret:WITHINGS_OAUTH_SECRET 
            accessToken:self.token 
            tokenSecret:self.tokenSecret]; 
headers = rq2.allHTTPHeaderFields; 

И в методе обратного вызова я добавлю недостающие параметры в запрос. Делая это таким образом, я избегаю «уродливого исправления исправления».

- (BOOL)webView:(UIWebView *)wV shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ 
if (![request.allHTTPHeaderFields objectForKey:@"Authorization"] && 
    [request.URL.absoluteString rangeOfString:@"acceptDelegation=true"].location == NSNotFound){ 
    NSMutableURLRequest *mutableCp = [request mutableCopy]; 
    NSLog(@"request :::%@", request); 
    [mutableCp setAllHTTPHeaderFields:headers]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [webView loadRequest:mutableCp]; 
    }); 
    return NO; 
} 
return YES; 
} 

Я надеюсь, что это поможет кто-нибудь

Смежные вопросы