简短版:
我想使用Google OAuth2 client for Objective C创建一个有效的GTMOAuth2Authentication
对象供我在我的应用中使用,我可以从后端获取一个离线访问令牌。我怎么能做到这一点?
我的情况:
我的应用使用Google Analytics只读范围来获取有关用户网站的一些数据。我完成此操作的方法是使用Google OAuth2客户端为Objective C提供的GTMOAuth2ViewControllerTouch
ViewController登录。然后我会向我提供有效的GTMOAuth2Authentication
对象,我可以使用该对象查询Google Analytics通过Google API client。
现在,我们不希望为用户提供Google Analytics访问权限(有些人没有Google帐户,一般情况下,我们希望通过应用程序保持信息简单)。这意味着我们必须使用我们的帐户登录(可以访问所有网站的Google Analytics数据)。显然我们无法向用户提供我们的凭据,因此我们必须找到解决方案。
我的计划:
我认为可以通过从我们的后端(通过SSL加密)请求我们的(离线访问)令牌字符串来解决此问题,将其保存到用户的钥匙串,并在应用程序中进一步使用它来查询Analytics。然后我们让用户登录我们的服务(这样我们就可以确定用户可以访问哪些网站),并显示数据。
我的问题:
我到处搜索,查看了Google的(非常薄的)文档,检查了GTMOAuth2Authentication
源代码,但我似乎无法解决问题。在我看来会有这样的解决方案(因为我在CMS中使用类似的方法让用户发布到我们的Facebook墙上),所以我在这里缺少什么?
当前登录代码:
GTMOAuth2ViewControllerTouch *viewController = [[GTMOAuth2ViewControllerTouch alloc]
initWithScope:scope
clientID:kMyClientID
clientSecret:kMyClientSecret
keychainItemName:kKeychainItemName
completionHandler:
^(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error) {
if (error != nil) {
// Authentication failed
DebugLog(@"Failed!");
} else {
// Authentication succeeded
DebugLog(@"Success!");
// Update interface
self.loginButton.hidden = YES;
self.authentication = auth;
}
}];
我尝试了什么:
我尝试手动创建GTMOAuth2Authentication
对象并自行设置所有参数(范围,clientid,secretid,访问令牌,刷新令牌,callbackuri,令牌url等),但我得到了返回401:登录我尝试将对象用于查询时所需的错误。所以我猜这不是这样做的方法。
链接:
感谢阅读!
答案 0 :(得分:6)
您不需要GTMOAuth2Authentication实例。 您需要的是创建自己的类来实现GTMFetcherAuthorizationProtocol协议,并将其指定为您的授权者。
MyAuth *myAuth = [[MyAuth alloc] initWithAccessToken:accessToken];
googleService.authorizer = myAuth;
此类需要根据您已有的访问令牌授权请求。 这个类的代码应该与此类似。
@interface MyAuth : NSObject<GTMFetcherAuthorizationProtocol>
@property (copy, nonatomic) NSString *accessToken;
@property (copy, readonly) NSString *userEmail;
@end
@implementation MyAuth
- (void)authorizeRequest:(NSMutableURLRequest *)request
delegate:(id)delegate
didFinishSelector:(SEL)sel {
if (request) {
NSString *value = [NSString stringWithFormat:@"%s %@", GTM_OAUTH2_BEARER, self.accessToken];
[request setValue:value forHTTPHeaderField:@"Authorization"];
}
NSMethodSignature *sig = [delegate methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:sel];
[invocation setTarget:delegate];
[invocation setArgument:(__bridge void *)(self) atIndex:2];
[invocation setArgument:&request atIndex:3];
[invocation invoke];
}
- (void)authorizeRequest:(NSMutableURLRequest *)request
completionHandler:(void (^)(NSError *error))handler {
if (request) {
NSString *value = [NSString stringWithFormat:@"%@ %@", @"Bearer", self.accessToken];
[request setValue:value forHTTPHeaderField:@"Authorization"];
}
}
- (BOOL)isAuthorizedRequest:(NSURLRequest *)request {
return NO;
}
- (void)stopAuthorization {
}
- (void)stopAuthorizationForRequest:(NSURLRequest *)request {
}
- (BOOL)isAuthorizingRequest:(NSURLRequest *)request {
return YES;
}
希望它有所帮助。
答案 1 :(得分:1)
您需要创建自己的实现GTMFetcherAuthorizationProtocol
协议的类,并将其分配为您的授权者。
这是Xcode 10.1(2019)更新的固定的非崩溃版本:
NSString *accessToken = "ya29.c.Elu-Bmq2eNaGPnIe3-Q4GuTAhuQZmyC6ylm6zCROBtyKEJQFJdlIBTUVlUjOOoaT0cQae_OGdxNM4ayRT_0yg121kD8ouX4SGbllPWRkiGHRbsZRuMPX2QCgMoIO";
MyAuth *auth = [[MyAuth alloc] initWithAccessToken:accessToken];
googleService.authorizer = auth;
MyGTMFetcherAuthorization.m
#import <Foundation/Foundation.h>
#import <GTMSessionFetcher/GTMSessionFetcher.h>
@interface MyAuth : NSObject<GTMFetcherAuthorizationProtocol>
+ (MyAuth *)initWithAccessToken:(NSString *)accessToken;
@end
// Until all OAuth 2 providers are up to the same spec, we'll provide a crude
// way here to override the "Bearer" string in the Authorization header
#ifndef GTM_OAUTH2_BEARER
#define GTM_OAUTH2_BEARER "Bearer"
#endif
@interface MyAuth ()
@property (strong, nonatomic) NSString *accessToken;
@end
@implementation MyAuth
+ (MyAuth *)initWithAccessToken:(NSString *)accessToken {
MyAuth *auth = [[MyAuth alloc] init];
auth.accessToken = [accessToken copy];
return auth;
}
- (void)authorizeRequest:(NSMutableURLRequest *)request
delegate:(id)delegate
didFinishSelector:(SEL)sel {
[self setTokeToRequest:request];
NSMethodSignature *sig = [delegate methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:sel];
[invocation setTarget:delegate];
[invocation setArgument:(&self) atIndex:2];
[invocation setArgument:&request atIndex:3];
[invocation invoke];
}
- (void)authorizeRequest:(NSMutableURLRequest *)request
completionHandler:(void (^)(NSError *error))handler {
[self setTokeToRequest:request];
}
- (void)setTokeToRequest:(NSMutableURLRequest *)request {
if (request) {
NSString *value = [NSString stringWithFormat:@"%s %@", GTM_OAUTH2_BEARER, self.accessToken];
[request setValue:value forHTTPHeaderField:@"Authorization"];
}
}
- (BOOL)isAuthorizedRequest:(NSURLRequest *)request {
return NO;
}
- (void)stopAuthorization {
}
- (void)stopAuthorizationForRequest:(NSURLRequest *)request {
}
- (BOOL)isAuthorizingRequest:(NSURLRequest *)request {
return YES;
}
@end