2013-02-01 9 views
10

iPadアプリケーションでOauthを実装する方法は?AFOAuth2Clientおよびリフレッシュトークン

AFOAuth2Clientは、oauth 2.0でリフレッシュトークンメカニズムをどのように管理しますか?

クラス内で実装する方法はありますか、独自の方法で実装する必要はありますか?トークンの期限切れをチェックする方法は?

答えて

11

私がこれを解決した方法は、必要に応じてアクセストークンをリフレッシュするコードブロックですべてのリクエストをラップすることです。

成功と失敗のブロックのためのいくつかのtypedefを追加します。

typedef void (^YFRailsSaasApiClientSuccess)(AFJSONRequestOperation *operation, id responseObject); 
typedef void (^YFRailsSaasApiClientFailure)(AFJSONRequestOperation *operation, NSError *error); 

そして、リクエストメソッドがある:

- (void)getProductsWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure { 
    NSLog(@"getProductsWithSuccess"); 

    success = ^(AFJSONRequestOperation *operation, id responseObject) { 
     [self getPath:@"api/1/products" 
      parameters:nil 
       success:^(AFHTTPRequestOperation *operation, id responseObject) { 
        NSLog(@"getProductsWithSuccess: success"); 

        // TODO: handle response 

        if (success) { 
         success((AFJSONRequestOperation *)operation, responseObject); 
        } 
       } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
        NSLog(@"getProductsWithSuccess: failure"); 
       if (failure) { 
        failure((AFJSONRequestOperation *)operation, error); 
       } 
      }]; 
    }; 

    [self refreshAccessTokenWithSuccess:success failure:failure]; 
} 

とトークンの有効期限をチェックし、必要に応じてそれを更新する方法は次のとおりです。

- (void)refreshAccessTokenWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure { 
    NSLog(@"refreshAccessTokenWithSuccess"); 

    if (self.credential == nil) { 
     if (failure) { 
      NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary]; 
      [errorDetail setValue:@"Failed to get credentials" forKey:NSLocalizedDescriptionKey]; 
      NSError *error = [NSError errorWithDomain:@"world" code:200 userInfo:errorDetail]; 
      failure(nil, error); 
     } 
     return; 
    } 

    if (!self.credential.isExpired) { 
     NSLog(@"refreshAccessTokenWithSuccess: credential has not expired"); 

     if (success) { 
      success(nil, nil); 
     } 
     return; 
    } 

    NSLog(@"refreshAccessTokenWithSuccess: refreshing credential"); 

    [self authenticateUsingOAuthWithPath:@"oauth/token" 
          refreshToken:self.credential.refreshToken 
           success:^(AFOAuthCredential *newCredential) { 
            NSLog(@"Successfully refreshed OAuth credentials %@", newCredential.accessToken); 
            self.credential = newCredential; 
            [AFOAuthCredential storeCredential:newCredential 
                withIdentifier:self.serviceProviderIdentifier]; 

            if (success) { 
             success(nil, nil); 
            } 
           } 
           failure:^(NSError *error) { 
            NSLog(@"An error occurred refreshing credential: %@", error); 
            if (failure) { 
             failure(nil, error); 
            } 
           }]; 
} 

GitHub:https://github.com/yellowfeather/rails-saas-iosで完全なソースコードが公開されています。

+0

さらに、資格情報の格納者をプロパティの設定者に移動することもできます。 – conradev

+2

これは、ネットワークの遅延(問題の可能性があります)があっても、時計がサーバと同期していると仮定し、サーバが実際にexpires_inの値を設定していることを前提とするトークンのexpires_in正しく。 expires_inは推奨されていますが、仕様に必須ではありません。これは、expires_inをサポートしていないサーバーでは、トークンによる要求でエラーが受信された後にリフレッシュを実行する必要があることを示しています。リフレッシュを引き起こす典型的なエラーは401です。この解決策が機能するかもしれないが、必ずしも機能しないことに注意してください。 – ptoinson

+0

@ptoinsonあなたが正しいですが、私はこの問題に取り組んでいます。リフレッシュを実行し、リフレッシュされたトークンでリクエストを送信する共有するコードサンプルがありますか?私はAFNetworkingOperationDidFinishNotificationを観察しようとしていますが、満足のいく解決策を思いつくことはできません。 – Newcode