AFOAuth2Client no puede acceder al recurso

Al usar AFOAuth2Client y AFNetworking en iOS 6, puedo get un token de acceso, pero no puedo acceder a un recurso, el server responde con un código de estado de 401 no autorizado. Esto está en contra de un backend personalizado de Rails 3 API que usa el portero como proveedor de OAuth. El siguiente código de Ruby del cliente, que usa la gem OAuth2, funciona bien:

client = OAuth2::Client.new(app_id, secret, site: "http://subdomain.example.com/") access_token = client.password.get_token('username', 'password') access_token.get('/api/1/products').parsed 

El código de iOS es el siguiente, en el manejador del button de inicio de session, autenticé usando el nombre de usuario y la contraseña, y almacena las cnetworkingenciales:

 - (IBAction)login:(id)sender { NSString *username = [usernameField text]; NSString *password = [passwordField text]; NSURL *url = [NSURL URLWithString:kClientBaseURL]; AFOAuth2Client *client = [AFOAuth2Client clientWithBaseURL:url clientID:kClientID secret:kClientSecret]; [client authenticateUsingOAuthWithPath:@"oauth/token" username:username password:password scope:nil success:^(AFOAuthCnetworkingential *cnetworkingential) { NSLog(@"Successfully received OAuth cnetworkingentials %@", cnetworkingential.accessToken); [AFOAuthCnetworkingential storeCnetworkingential:cnetworkingential withIdentifier:client.serviceProviderIdentifier]; [self performSegueWithIdentifier:@"LoginSegue" sender:sender]; } failure:^(NSError *error) { NSLog(@"Error: %@", error); [passwordField setText:@""]; }]; } 

y he subclasificado AFHTTPClient para mi punto final y en initWithBaseURL recupera las cnetworkingenciales y establece el encabezado de autorización con el token de acceso:

 - (id)initWithBaseURL:(NSURL *)url { self = [super initWithBaseURL:url]; if (!self) { return nil; } [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; [self setDefaultHeader:@"Accept" value:@"application/json"]; AFOAuthCnetworkingential *cnetworkingential = [AFOAuthCnetworkingential retrieveCnetworkingentialWithIdentifier:@"subdomain.example.com"]; [self setAuthorizationHeaderWithToken:cnetworkingential.accessToken]; return self; } 

¿Es esta la forma correcta de usar AFOAuth2Client y AFNetworking? ¿Y alguna idea de por qué esto no funciona?

Administrado para lograr que esto funcione al cambiar:

  AFOAuthCnetworkingential *cnetworkingential = [AFOAuthCnetworkingential retrieveCnetworkingentialWithIdentifier:@"subdomain.example.com"]; [self setAuthorizationHeaderWithToken:cnetworkingential.accessToken]; 

a:

  AFOAuthCnetworkingential *cnetworkingential = [AFOAuthCnetworkingential retrieveCnetworkingentialWithIdentifier:@"subdomain.example.com"]; NSString *authValue = [NSString stringWithFormat:@"Bearer %@", cnetworkingential.accessToken]; [self setDefaultHeader:@"Authorization" value:authValue]; 

ACTUALIZAR

Lo que no había notado fue que AFOAuth2Client es en sí mismo una subclass de AFHTTPClient por lo que se puede usar como la class base de la class API, por ejemplo:

 @interface YFExampleAPIClient : AFOAuth2Client + (YFExampleAPIClient *)shanetworkingClient; /** */ - (void)authenticateWithUsernameAndPassword:(NSString *)username password:(NSString *)password success:(void (^)(AFOAuthCnetworkingential *cnetworkingential))success failure:(void (^)(NSError *error))failure; @end 

Y la implementación se convierte en:

 @implementation YFExampleAPIClient + (YFExampleAPIClient *)shanetworkingClient { static YFExampleAPIClient *_shanetworkingClient = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURL *url = [NSURL URLWithString:kClientBaseURL]; _shanetworkingClient = [YFExampleAPIClient clientWithBaseURL:url clientID:kClientID secret:kClientSecret]; }); return _shanetworkingClient; } - (void)authenticateWithUsernameAndPassword:(NSString *)username password:(NSString *)password success:(void (^)(AFOAuthCnetworkingential *cnetworkingential))success failure:(void (^)(NSError *error))failure { [self authenticateUsingOAuthWithPath:@"oauth/token" username:username password:password scope:nil success:^(AFOAuthCnetworkingential *cnetworkingential) { NSLog(@"Successfully received OAuth cnetworkingentials %@", cnetworkingential.accessToken); [self setAuthorizationHeaderWithCnetworkingential:cnetworkingential]; success(cnetworkingential); } failure:^(NSError *error) { NSLog(@"Error: %@", error); failure(error); }]; } - (id)initWithBaseURL:(NSURL *)url clientID:(NSString *)clientID secret:(NSString *)secret { self = [super initWithBaseURL:url clientID:clientID secret:secret]; if (!self) { return nil; } [self setDefaultHeader:@"Accept" value:@"application/json"]; return self; } @end 

Tenga en count que initWithBaseURL se reemplaza para establecer el encabezado de aceptación de HTTP.

El código fuente completo está disponible en GitHub – https://github.com/yellowfeather/rails-saas-ios