使用AFOAuth2Manager

时间:2016-11-14 19:58:09

标签: ios oauth-2.0 afnetworking-3 afoauth2manager

我有一台服务器,其中实现了OAuth 2.0以发布访问权限和刷新令牌。该服务器的客户端是用Objective-C编写的iOS应用程序。我目前正在使用AFNetworking 3.0进行HTTP请求,使用AFOAuth2Manager来处理授权。我想在访问令牌到期之前使用服务器发出的刷新令牌刷新存储在iOS应用程序中的访问令牌(服务器返回到期的秒数为{'expires_in':3600}(一小时))。在访问令牌到期之前,一切正常。以下是处理请求和授权的代码。

- (AFJSONRequestSerializer *)setRequestSerializer
{
    AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];

    [serializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [serializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];

    User *currentUser = [User currentUser];
    if (currentUser){
        AFOAuthCredential *credentials = [AFOAuthCredential retrieveCredentialWithIdentifier:kEndpointServer];
        if (!credentials.isExpired){
            [serializer setAuthorizationHeaderFieldWithCredential:credentials];
        }
    }

    return serializer;
}

- (AFJSONResponseSerializer *)setResponseSerializer
{
    AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];

    return serializer;
}

- (AFSecurityPolicy *)setSecurityPolicy
{
    NSString *certFilePath = [[NSBundle mainBundle] pathForResource:@"cert" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:certFilePath];
    NSSet *pinnedCerts = [NSSet setWithObject:certData];

    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:pinnedCerts];
    [policy setAllowInvalidCertificates:YES]; // DEVELOPMENT ONLY
    [policy setValidatesDomainName:NO];

    return policy;
}

- (AFHTTPSessionManager *)sessionManager
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    manager.securityPolicy = [self setSecurityPolicy];
    manager.requestSerializer = [self setRequestSerializer];
    manager.responseSerializer = [self setResponseSerializer];

    return manager;
}

- (AFOAuth2Manager *)OAuth2Manager
{
    NSURL *baseURL = [NSURL URLWithString:kEndpointServer];
    AFOAuth2Manager *manager = [[AFOAuth2Manager alloc] initWithBaseURL:baseURL clientID:kParamAPIClientId secret:kParamAPIClientSecret];
    manager.securityPolicy = [self setSecurityPolicy];
    return manager;
}

- (void)loginUser:(NSDictionary *)user block:(void (^)(BOOL, NSError *))result
{
    // Set endpoint URL
    NSString *loginEndpointURL = [NSString stringWithFormat:@"%@%@", kEndpointServer, kEndpointLogin];

    AFHTTPSessionManager *manager = [self sessionManager];

    if ([self internetConnectionAvailable]){
        [manager POST:loginEndpointURL parameters:user progress:nil success:^(NSURLSessionDataTask *task, id responseObject){

            NSDictionary *responseDict = (NSDictionary *)responseObject;
            BOOL success = (BOOL)[(NSNumber *)[responseDict objectForKey:kParamSuccess] boolValue];
            NSString *msg = (NSString *)[responseDict objectForKey:kParamMessage];

            if (success){

                // Get user
                NSDictionary *userLoggedIn = (NSDictionary *)[responseDict objectForKey:kParamUser];

                //NSLog(@"Logged in.");

                NSString *tokenEndpointURL = [NSString stringWithFormat:@"/api%@%@", kEndpointOAuth, kEndpointToken];
                OAuth2Manager *OAuth2Manager = [self OAuth2Manager];
                [OAuth2Manager authenticateUsingOAuthWithURLString:tokenEndpointURL username:(NSString *)[user objectForKey:kParamEmail] password:(NSString *)[user objectForKey:kParamPassword] scope:nil success:^(AFOAuthCredential *credentials){
                    NSLog(@"Credentials:");
                    NSLog(@"Access Token: %@", credentials.accessToken);
                    NSLog(@"Refresh Token: %@", credentials.refreshToken);

                    // Store credentials
                    [AFOAuthCredential storeCredential:credentials withIdentifier:kEndpointServer];

                    // Set current user
                    [User setCurrentUser:userLoggedIn];

                    result(YES, nil);
                }failure:^(NSError *error){
                    NSLog(@"Error authenticating user: %@", error);
                    result(NO, error);
                }];
            } else {
                result(NO, [NSError errorWithDomain:msg code:kEDHTTPRequestFailedErrorCode userInfo:nil]);
            }
        }failure:^(NSURLSessionDataTask *task, NSError *error){
            result(NO, error);
        }];
    } else {
        result(NO, [NSError errorWithDomain:kEDNoInternetConnectionErrorDomain code:kEDNoInternetConnectionErrorCode userInfo:nil]);
    }
}

我在SO上发现了类似的问题:

How to automatically refresh expired token with AFOAuth2Manager?

但给出答案的问题是它已经过时(适用于AFNetworking 2.X.X,但不适用于AFNetworking 3.0)。

自动处理访问令牌刷新的最佳做法是什么?

0 个答案:

没有答案