2017-11-01 6 views
12

Mam zainstalowaną aplikację na iOS i backend napisany wiosną z mechanizmem OAuth2.AppAuth iOS. Jak zapisać informacje o tokenie, gdy użytkownik zarejestruje konto na moim własnym serwerze OAuth2

Mam punkt końcowy signup w moim zapleczu, który akceptuje niektóre dane użytkownika i zwraca odpowiedź OAuth2, np.

{ 
    "access_token":"9154140d-b621-4391-9fdd-fbba9e5e4188", 
    "token_type":"bearer", 
    "refresh_token":"dd612036-7cc6-4858-a30f-c548fc2a823c", 
    "expires_in":89, 
    "scope":"write" 
} 

Po tym chcę zapisać OIDAuthState w moim pęku kluczy, więc należy wykonać następujące czynności:

func saveTokenResponse(responseDict: [String: NSCopying & NSObjectProtocol]) { 
     let redirectURI = URL(string: kRedirectURI) 
     let configuration = OIDServiceConfiguration(authorizationEndpoint: URL(string: kAuthorizationEndpoint)!, tokenEndpoint: URL(string: kTokenEndpoint)!) 
     let request = OIDAuthorizationRequest(configuration: configuration, clientId: self.kClientID, scopes: ["write"], redirectURL: redirectURI!, responseType: OIDResponseTypeCode, additionalParameters: nil) 

     let accessToken = responseDict["access_token"] ?? nil 
     let tokenType = responseDict["token_type"] ?? nil 
     let refreshToken = responseDict["refresh_token"] ?? nil 
     let expiresIn = responseDict["expires_in"] ?? nil 
     let scope = responseDict["scope"] ?? nil 

     let response = OIDAuthorizationResponse(request: request, parameters: [ 
      "access_token": accessToken!, 
      "token_type": tokenType!, 
      "refresh_token": refreshToken!, 
      "expires_in": expiresIn!, 
      "scope": scope! 
      ] 
     ) 
     let authState = OIDAuthState(authorizationResponse: response) //here authState.refreshToken is nil, so it won't be serialized. 

     updateAuthState(authState: authState) // it just saves it in keychain 
    } 

Wszystko działa dobrze, ale mam problem, kiedy wygasa token. Aplikacja umożliwia wywołanie backend i AppAuth nie jest w stanie odświeżyć znak:

OIDAuthState does not have refresh token

widzę, że token odświeżania nie jest obecny w obiekcie OIDAuthState. Sprawdziłem inicjowanie OIDAuthState od OIDAuthorizationResponse i okazało się, że token nie jest przypisany w tym przypadku.

Czy ktoś może pomóc, w jaki sposób mogę zapisać OIDAuthState z odpowiedzi OAuth otrzymanej od mojego zaplecza? Czy robię coś w niewłaściwy sposób?

Dzięki,

Osman

+0

W jaki sposób przygotowujesz pierwotne żądanie autoryzacji? Czy używasz do tego AppAuth? –

+0

@TomHarrington Nie, nie składam żadnego wstępnego żądania autoryzacji, ponieważ jest to punkt końcowy "Zarejestruj się", który powinien zostać wywołany bez żadnej autoryzacji. W przeciwnym razie może mi brakować czegoś. – fiks

+0

Jak uzyskać początkowy token, który chcesz odświeżyć? –

Odpowiedz

5

Jeśli token wygaśnie następnie przenieść na ekran logowania (znak wywoławczy z funkcji) jak wszystkich aplikacji (systemu bankowego, Amazon, Paytm i Facebook). Więc użytkownik po zalogowaniu się przy użyciu poświadczeń, a następnie uzyskanie takich samych odpowiedzi, jak chcesz i trzeba odświeżyć tokena. Otrzymujesz samilowe informacje w serwisie internetowym logowania, jak poniżej. Mam nadzieję, że to działa dobrze

let accessToken = responseDict["access_token"] ?? nil 
    let tokenType = responseDict["token_type"] ?? nil 
    let refreshToken = responseDict["refresh_token"] ?? nil 
    let expiresIn = responseDict["expires_in"] ?? nil 
    let scope = responseDict["scope"] ?? nil 

    let response = OIDAuthorizationResponse(request: request, parameters: [ 
     "access_token": accessToken!, 
     "token_type": tokenType!, 
     "refresh_token": refreshToken!, 
     "expires_in": expiresIn!, 
     "scope": scope!] 
     ) 
+0

Jeśli wygasa token dostępu, powinienem użyć tokena odświeżania, aby uzyskać nowy token dostępu. Taki jest cel tokena odświeżania, aby użytkownik nie musiał logować się ponownie. – fiks

+0

Masz więc połączenie z nowym serwisem WWW dla nowego tokena! –

+0

dlatego używam AppAuth i automatycznie wywołuje usługę sieciową dla nowego tokena, ale problem polega na tym, że nie może on nawiązać połączenia, ponieważ nie jest w stanie przekształcić deseriunku tokena, ponieważ ma on wartość null. Więc kiedy początkowo zapisuję 'OIDAuthState', to nie zapisuję tokena odświeżania. – fiks

2

Nie wiem, co dokładnie robisz, ale proponuję używać inny mechanizm które są powszechnie wykorzystywane.

Za każdym razem, gdy użytkownik loguje się w Google, token dostępu jest wysyłany przez Google i wygasa w krótkim czasie.

  1. Dostęp tokena pojawi się na zalogowaniu, należy przesłać na serwer po prostu zobaczyć i sprawdzić, czy użytkownik jest autentyczny i wszystkie jego dane osobowe mogą być pobrane wraz z nim także (poprzez GoogleAPI rozmowy).
  2. Wyślij to token dostępu do swojego serwera, gdy tylko użytkownik zaloguje się przez Google. Przetwórz ten token na serwerze.
  3. Po uwierzytelnieniu tokena dostępu, wyślij mu swój unikalny token z serwera (z czasem wygaśnięcia lub nie).
  4. Użytkownik kontynuuje korzystanie z aplikacji dzięki temu unikatowemu tokenowi.
+1

Robię dokładnie to samo, gdy użytkownik loguje się za pomocą FB. Jednak, jak pisałem w moich pytaniach, mam własną implementację serwera OAuth2 (jest to inicjatywa Spring Boot). I pozwala mi to zrobić dokładnie to samo, co opisałeś. W moim przypadku mój serwer OAuth2 zachowuje się dokładnie tak samo, jak każdy inny dostawca OAuth2 (FB, Google itp.) I działa doskonale z logiem w punkcie końcowym. Jednak, gdy użytkownik się zarejestruje, nie ma API w AppAuth, aby zapisać token ręcznie, więc robię to z własnego kodu, a to nie działa. – fiks

0

Zmień ciąg na let redirectURI = URL(string: kRedirectURI) na małe, oAuth dla ios jest wybredny. Można również spróbować użyć Okta jako usługi pośrednika, która podłącza się do oAuth.

0

Wpadłem na ten sam problem, używając AppAuth dla iOS (refreshToken miał wartość NULL).Udało mi się to zrobić działając dodając do moich zakresów "offline_access".

let request = OIDAuthorizationRequest(configuration: configuration!, clientId: self.kClientID, scopes: [OIDScopeOpenID, OIDScopeProfile, "api", "offline_access"], redirectURL: redirectURI! as URL, responseType: OIDResponseTypeCode, additionalParameters: nil) 
Powiązane problemy