2013-08-17 20 views
5

Staram się uzyskać token dostępu w Quizlet (oauth2). Wszystko działa bez zarzutu tak daleko, mogę sprawić użytkownikowi przyjęcie mojej aplikacji na Quizlet, przekierowanie, ale podczas żądania tokenu dostępu poprzez NSURLConnection, zawsze pojawia się następujący błąd:Niepoprawny parametr/parametr parametru grant_type w POST dla żądania tokenu dostępu

2013-08-17 09:39:33.422 Abiliator[49549:c07] Returned data in string format: {"http_code":400,"error":"invalid_request","error_title":"Not Allowed","error_description":"Invalid grant_type parameter or parameter missing"}

Oto kod dla uwierzytelniania użytkowników (musi być za pośrednictwem przeglądarki zgodnie ze specyfikacją):

- (void) authenticateQuizletUser 
{ 

NSString *quizletRandomString = [abiliatorAppDelegate GetUUID]; 
NSString *authURLString = [@"https://quizlet.com/authorize/?response_type=code&client_id=" stringByAppendingString:@"<myID>&scope=read"]; 
authURLString = [authURLString stringByAppendingString:@"&state="]; 
authURLString = [authURLString stringByAppendingString:quizletRandomString]; 
authURLString = [authURLString stringByAppendingString:@"&redirect_uri=Abiliator://after_oauth"]; 

NSLog(@"Authentication URL sent: %@", authURLString); 
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: authURLString]]; 

} 

To działa dobrze, jak już wspomniałem. Aplikacja uruchamia Safari, a użytkownik musi potwierdzić żądanie podania identyfikatora użytkownika i hasła, a serwer przekierowuje do mojej aplikacji, którą przechwytuję w poniższej metodzie, która następnie zgłasza opisany błąd.

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { 
if (!url) { return NO; } 
NSString *URLString = [url absoluteString]; 
NSLog(@"Received URL: %@", URLString); 
NSString *myURLQuery = [url query]; 
NSString *myAuthCode = [self getAuthorizationCodeFromURL:myURLQuery]; 
NSLog(@"Component1: %@", myAuthCode); 
NSString *authPasswd = @"myPasswd"; 
NSString *[email protected]"myUserName"; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.quizlet.com/oauth/token"]]; 

request.HTTPMethod = @"POST"; 

[request setValue:@"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; 
[request setValue:@"Abiliator://after_oauth" forHTTPHeaderField:@"redirect_uri"]; 

// According to Quizlet API doc: You must set this (grant_type) to the string "authorization_code". 
[request setValue:@"authorization_code" forHTTPHeaderField:@"grant_type"]; 
[request setValue:myAuthCode forHTTPHeaderField:@"code"]; 

NSString *authStr = [NSString stringWithFormat:@"%@:%@", username, authPasswd]; 
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding]; 
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodedString]]; 
[request setValue:authValue forHTTPHeaderField:@"Authorization"]; 

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 


return YES; } 

Każda pomoc jest wysoko ceniona.

Odpowiedz

1

OAuth2 defines 4 ways zdobyć token dostępu. Najbezpieczniejszym i najbardziej skomplikowanym jest Authorization Code Grant używany przez Quizlet zgodnie z opisem here.

Autoryzacja Kod Grant składa się z dwóch etapów:

  • uzyskać kod autoryzacyjny (użytkownik uwierzytelnia tutaj poza aplikacją przed przepływa strumień z powrotem do Ciebie poprzez przekierowanie)
  • zmienić kod autoryzacji w token dostępu

Zrobiłeś pierwsze połączenie w prawo. Problem z drugim wywołaniem polega na umieszczeniu parametru grant_type w niewłaściwym miejscu żądania. W tej linii można traktować go jako nagłówka HTTP:

[request setValue:@"authorization_code" forHTTPHeaderField:@"grant_type"]; 

I tu również traktować kod autoryzacji jako nagłówka HTTP:

[request setValue:myAuthCode forHTTPHeaderField:@"code"]; 

Ale OAuth2 wymaga, aby umieścić zarówno na ciele Twoja prośba.Oto przykład poprawnej życzenie:

POST /oauth/token/ HTTP/1.1 
Content-Type: application/x-www-form-urlencoded;charset=UTF-8 
Content-Length: 999 
Authorization: Basic xxx 

grant_type=authorization_code&code=theCodeYouGotInTheFirstStep& 
scope=somescope&redirect_uri=theSameUriYouIncludedEarlier 

(Rzeczy poniżej pustą linią jest ciało Twoje zapytanie'S)
(dodałem linebreak w organizmie tylko do odczytu - nie musi zawierać go w żądaniu)

Odpowiedź premiowa: należy pamiętać, że OAuth2 jest domyślnie niezabezpieczony: jeśli nie wykonasz dodatkowej pracy, Twoja aplikacja będzie narażona na ataki z użyciem Cross-Site Request Forgery, nawet jako mentioned in the OAuth2 RFC. Aby temu zapobiec, OAuth2 oferuje parametr state. Musisz wygenerować wartość domyślną dla swojego state i uwzględnić ją w pierwszym żądaniu. Nie możesz zwolnić drugiego żądania, jeśli zwrócony przez serwer state nie jest tym samym, który wygenerowałeś wcześniej.

+0

Wielkie dzięki. Jeśli chodzi o bezpieczeństwo, przekazuję parametr stanu, zobacz pierwszy kod w moim pytaniu. Po prostu nie zaimplementowałem jeszcze sprawdzania poprawności. Jeśli chodzi o ciało, próbowałem tego samego, tego samego rezultatu. Zaktualizowałem swój post z fragmentem treści, tak jak zaimplementowałem. – renesteg

+0

@renesteg nikt inny nie może zobaczyć twojego wyciętego fragmentu, ponieważ edycja została odrzucona, ale Ty też pominąłeś metodę grant_type, ale wstawiłeś rzeczy, które należą do nagłówka, takie jak typ zawartości i podstawowa autoryzacja. Spróbuj ponownie, używając ciągu, który umieściłem w mojej odpowiedzi. –

+0

Dziwne, że edycje są odrzucane, tak czy inaczej, tutaj snipped używam dla metody body: [bodyData appendData: [postMethodString dataUsingEncoding: NSUTF8StringEncoding]]; [bodyData appendData: [authCodeString dataUsingEncoding: NSUTF8StringEncoding]]; [bodyData appendData: [contentTypeString dataUsingEncoding: NSUTF8StringEncoding]]; [bodyData appendData: [basicAuthorizationString dataUsingEncoding: NSUTF8StringEncoding]]; , a następnie używam [request setHTTPBody: bodyData]; powinno być w porządku, prawda? – renesteg

1

Może być przydatny, aby zobaczyć resztę realizacji. Jak uzyskać code? Co używasz poświadczeń (authPasswd & Powinny to być Twoje aplikacje (w przeciwieństwie do użytkownika końcowego). Dostajesz je w Dev Dashboard Quizleta.

Note: this OAuth flow is not recommended for devices, as it requires secrets to be stored in the device. Using the implicit flow is, but I'm not sure Quizlet supports it.

+0

Dziękuję Eugenio za opinię. Używam danych uwierzytelniających dla mojej aplikacji, ponieważ Quizlet określa: Dokonałem edycji mojego posta, aby pokazać pierwszy krok procesu oauth 2. W ogóle nie ma problemu. Jedyne, czego jeszcze nie mam, to porównywanie wysłanego losowego ciągu znaków dla stanu. Ale to nie powinno być problemu, ponieważ jest to dodatkowe zabezpieczenie tylko po stronie aplikacji. Co do twojej notatki: co masz na myśli przez niejawny przepływ? – renesteg

+0

Wszystko wygląda dobrze na powierzchni ... czy możesz umieścić ślad sieciowy, aby zobaczyć, co faktycznie jest wysyłane, gdy żądasz tokena? "implicit" jest po prostu kolejnym przepływem, w którym można żądać tokena bezpośrednio (bez wymiany kodu). Zobacz: http://stackoverflow.com/questions/16321455/oauth-2-0-difference-between-2-workflows-when-to-use-authorization-code-flow/16341985#16341985 –

+0

To jest 3-legged pływ. Implicit grant jest używany, gdy klient jest zaufany. Implicit odcina przepływ wysyłania kodu auth z powrotem do klienta, w przeciwnym razie klient musi przedstawić swoje poświadczenia i parametry wraz z kodem uwierzytelniającym, aby wygenerować token dostępu, a głównym powodem jest sprawdzenie, czy kod Auth jest prezentowany kup tego samego klienta dla którego został wygenerowany, (tutaj jest obowiązkowe redirect_uri). –

0

Wyślij swoje parametry oauth jako ładunek. Nie powinieneś wysyłać ich jako nagłówków. Dla przykładu Wniosek powinien wygląda

POST /token 

Headers: 

Authorization: Basic R0cxSWJdHpINDVhang5Y0VlSUxxalBSOW5SU0NBWA== 

Content-Type: application/x-www-form-urlencoded 

Payload: 

grant_type=authorization_code&code=Wirr951e&scope=READ&redirect_uri=www.google.com 
Powiązane problemy