ios - Best solution to refresh token automatically with AFNetworking? -


once user logged in, token (digest or oauth) set http authorization header , gives authorization access web service. if store user's name, password , token somewhere on phone (in user defaults, or preferably in keychain), user automatically logged in each time application restarts.

but if token expires? "simply" need ask new token , if user did not change password, should logged in once again automatically.

one way implement token refreshing operation subclass afhttprequestoperation , take care of 401 unauthorized http status code in order ask new token. when new token issued, can call once again failed operation should succeeds.

then must register class each afnetworking request (getpath, postpath, ...) uses class.

[httpclient registerhttpoperationclass:[retryrequestoperation class]] 

here exemple of such class:

static nsinteger const khttpstatuscodeunauthorized = 401;  @interface retryrequestoperation () @property (nonatomic, assign) bool isretrying; @end  @implementation retryrequestoperation - (void)setcompletionblockwithsuccess:(void (^)(afhttprequestoperation *, id))success                               failure:(void (^)(afhttprequestoperation *, nserror *))failure {     __unsafe_unretained retryrequestoperation *weakself = self;      [super setcompletionblockwithsuccess:success failure:^(afhttprequestoperation *operation, nserror *error) {         // in case of 401 error, authentification email/password tried once renew token.         // if succeeds, opration sent again.         // if fails, failure operation block called.         if(([operation.response statuscode] == khttpstatuscodeunauthorized)            && ![weakself isauthenticateurl:operation.request.url]            && !weakself.isretrying)         {             nsstring *email;             nsstring *password;              email = [sessionmanager currentuseremail];             password = [sessionmanager currentuserpassword];             // trying authenticate again before relaunching unauthorized request.             [servicemanager authenticatewithemail:email password:password completion:^(nserror *logerror) {                 if (logerror == nil) {                     retryrequestoperation *retryoperation;                      // authenticated again, same request can launched again.                     retryoperation = [operation copy];                     // tell retry. ensures not retry indefinitely if there still unauthorized error.                     retryoperation.isretrying = yes;                     [retryoperation setcompletionblockwithsuccess:success failure:failure];                     // enqueue operation.                     [servicemanager enqueueobjectrequestoperation:retryoperation];                 }                 else                 {                     failure(operation, logerror);                     if([self httpcodefromerror:logerror] == khttpstatuscodeunauthorized)                     {                         // authentication returns unauthorized error, user seems not authorized anymore.                         // maybe password has changed?                         // user logged out redirected login view.                         [sessionmanager logout];                     }                 }             }];         }         else         {             failure(operation, error);         }     }]; }  - (bool)isauthenticateurl:(nsurl *)url {     // path depends on implementation, can "auth", "oauth/token", ...     return [url.path hassuffix:kauthenticatepath]; }  - (nsinteger)httpcodefromerror:(nserror *)error {     // how http status code depends on implementation.     return error.userinfo[khttpstatuscodekey]; } 

please, aware code not work is, relies on external code depends on web api, kind of authorization (digest, oath, ...) , kind of framework use on afnetworking (restkit example).

this quite efficient , has proved work both digest , oauth authorization using restkit tied coredata (in case retryrequestoperation subclass of rkmanagedobjectrequestoperation).

my question is: best way refresh token? wondering if nsurlauthenticationchallenge used solve situation in more elegant manner.

your current solution works , have code it, there might reasonable amount of code achieve approach has merits.

using nsurlauthenticationchallenge based approach means subclassing @ different level , augmenting each created operation setwillsendrequestforauthenticationchallengeblock:. in general better approach single operation used perform whole operation rather having copy , update details, , operation auth support doing auth task instead of operation completion handler. should less code maintain, code understood less people (or take longer understand most) maintenance side of things balances out on all.

if you're looking elegance, consider changing, given have working solution there little gain otherwise.


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -