GTM OAuth does not download Refresh Token - iOS

*爱你&永不变心* 提交于 2019-12-13 18:22:14

问题


I am using Google's GTMOAuth for iOS/Mac SDK in order to be able to connect with APIS such as YouTube API and Instagram API. It all works fine, however when the user authenticates, I can only get access token. This is all well and good, but after a while the access tokens expire and the user has to re-login which is awful.

My problem is that when the user authenticates, I ONLY GET back an access token and nothing else...

Thanks for you're help :)


回答1:


May be this one help you..!

I am using Google oauth 2.0, for google drive authentication.

In the Google finished with authentication method save the accesstoken and refresh token values in NSUSerDefaults like this.

 - (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)authResult

           error:(NSError *)error
    {

        if (error != nil)
        {

          [self showAlert:@"Authentication Error" message:error.localizedDescription];

            self.driveService.authorizer = nil;

        }
        else
        {
            self.driveService.authorizer = authResult;

            self.auth = authResult;

            NSLog(@"\n accessToken value is %@",self.auth.accessToken);

            [[NSUserDefaults standardUserDefaults] setValue:self.auth.refreshToken forKey:@"refreshToken"];

            [[NSUserDefaults standardUserDefaults] setValue:self.auth.accessToken forKey:@"accessToken"];

            [[NSUserDefaults standardUserDefaults] synchronize];


        }

    }

After that when ever you want to use the acces token for performing api call first make a call using existing accesstoken value from the NSUSERDefaults, after that in the url response check the status code. If you are getting status code '401' means your access token is expired, and not valid. Then you have to request for refresh token using saved refresh token value in NSUserDefaults like this.

This is your first api call to check accesstoken valid or not.

    - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
    {
        NSLog(@"Did Receive Response %@", response);
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        //int responseStatusCode = [httpResponse statusCode];
        if (httpResponse.statusCode == 200) {
//Your api call success and accesstoken is valid.


        } else if(httpResponse.statusCode == 401 && connection == self.conn2) {

            [[self appDelegate] refreshAccessToken];
        } 
    }

This is for request new accesstoken from refresh token.

-(void)refreshAccessToken {


    NSString *requestString = [NSString stringWithFormat:@"https://accounts.google.com/o/oauth2/token"];
        NSString *string = [NSString stringWithFormat:@"client_id=%@&client_secret=%@&refresh_token=%@&grant_type=refresh_token",kClientID,kClientSecret,[[NSUserDefaults standardUserDefaults] valueForKey:@"refreshToken"]];
    NSData *postData = [string dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString]];
    NSLog(@"\n request str : %@",request);

    NSLog(@"\n refresh token value is %@",[[NSUserDefaults standardUserDefaults] valueForKey:@"refreshToken"]);
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];//connectionWithRequest:request delegate:self];
    if(connection)
    {
        NSLog(@"Connection Successful");
    }
    else
    {
        NSLog(@"Connection could not be made");
    }

    [connection start];


}

In response check for status code again and if status code is 200.Then update the value in userdafaults.

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"Did Receive Response %@", response);
    //NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
    self.data = [NSMutableData data];
}

- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    NSLog(@"Did Receive Data %@", data);
    [self.data appendData:data];
}

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
    NSLog(@"Did Fail %@",error);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Did Finish");
    // Do something with responseData
    NSError *err;
    id JSon = [NSJSONSerialization JSONObjectWithData:self.data options:kNilOptions error:&err];
    if (err) {
        NSLog(@"%@",err);
    }
    else {
        NSLog(@"Json %@",JSon);
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"accessToken"];
        [[NSUserDefaults standardUserDefaults] setObject:[JSon valueForKey:@"access_token"] forKey:@"accessToken"];
        [[NSUserDefaults standardUserDefaults] synchronize];

    }
}

This is my first answer on stack overflow. Sorry for any mistakes.

UPDATE BELOW - Written by Supertecnoboff

Also keep this in mind. For some API's such as Google, you need to add "approval_prompt=force" and "access_type=offline" if you want it to give you a refresh token. In order to add these parameters, you have to edit the GTMOAuth2SignIn.m file and replace the "paramsDict" with this NSMutableDictionary:

NSMutableDictionary *paramsDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                 @"code", @"response_type",
                                 clientID, @"client_id",
                                 scope, @"scope", // scope may be nil
                                 @"force", @"approval_prompt",
                                 @"offline", @"access_type",
                                 nil];



回答2:


You can also use the GTMOAuth2Authentication´s authorizeRequest:completionHandler: method

If your application saves the authorization to the keychain (by setting the controller's keychainItemName), it can be retrieved the next time the application launches:

GTMOAuth2Authentication *auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                                                          clientID:kClientID
                                                                                    clientSecret:kClientSecret];

NSLog(@"accessToken: %@", auth.accessToken); //If the token is expired, this will be nil

and then you can refresh the access token like this:

// authorizeRequest will refresh the token, even though the NSURLRequest passed is nil
[auth authorizeRequest:nil
             completionHandler:^(NSError *error) {
                 if (error) {
                     NSLog(@"error: %@", error);
                 }
                 else {
                     NSLog(@"accessToken: %@", auth.accessToken); //it shouldn´t be nil
                 }
             }];

The token will be then refreshed and you can keep making queries.



来源:https://stackoverflow.com/questions/21633968/gtm-oauth-does-not-download-refresh-token-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!