我有一個iPad應用程序,允許用戶使用OAuth2登錄到他們的Gmail帳戶。到目前爲止,登錄過程和電子郵件抓取都是成功的。但是,當應用程序關閉並在(很長)時間段後重新打開時,即使先前使用相同憑據的登錄成功,也會生成「無效憑據」錯誤。Google OAuth登錄錯誤:憑證無效
登錄流程: 1 )到Gmail使用OAuth 2. 2)用戶的電子郵件地址和oAuthToken由GTMOAuth2Authentication對象提供的用戶日誌保存用於以後登錄的核心數據。 3)IMAP會話使用保存的電子郵件地址和OAuthToken創建。
這裏是相關的代碼
Google登錄
- (void)gmailOAuthLogin
{
NSDictionary *googleSettings = [[EmailServicesInfo emailServicesInfoDict] objectForKey:Gmail];
GTMOAuth2ViewControllerTouch *googleSignInController =
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:GmailScope clientID:GmailAppClientID clientSecret:GmailClientSecret keychainItemName:KeychainItemName completionHandler:^(GTMOAuth2ViewControllerTouch *googleSignInController, GTMOAuth2Authentication *auth, NSError *error){
if (error != nil) {
//handle error
} else {
[[ModelManager sharedInstance] authenticateWithEmailAddress:[auth userEmail]
oAuthToken:[auth accessToken] imapHostname:[googleSettings objectForKey:IMAPHostName] imapPort:[[googleSettings objectForKey:IMAPPort]integerValue] smtpHostname:[googleSettings objectForKey:SMTPHostName] smtpPort:[[googleSettings objectForKey:SMTPPort]integerValue] type:EmailProtocolTypeImapAndSmtpGMail success:^(Account *account) {
//create IMAP session using above arguments
} failure:^(NSError *error) {
//handle error
}];
}
}];
[self presentGoogleSignInController:googleSignInController];
}
創建IMAP會話使用MailCore2
- (void)authenticateWithEmailAddress:(NSString *)emailAddress password:(NSString *)password oAuthToken:(NSString *)oAuthToken imapHostname:(NSString *)imapHostname imapPort:(NSInteger)imapPort smtpHostname:(NSString *)smtpHostname smtpPort:(NSInteger)smtpPort success:(void (^)())success failure:(void (^)(NSError *))failure
{
self.imapSession = [[MCOIMAPSession alloc] init];
self.imapSession.hostname = imapHostname;
self.imapSession.port = imapPort;
self.imapSession.username = emailAddress;
self.imapSession.connectionType = MCOConnectionTypeTLS;
self.imapSession.password = nil;
self.imapSession.OAuth2Token = oAuthToken;
self.imapSession.authType = nil != oAuthToken ? MCOAuthTypeXOAuth2 :
self.imapSession.authType;
[self.imapSession setConnectionLogger:^(void * connectionID, MCOConnectionLogType type,
NSData * data){
NSLog(@"MCOIMAPSession: [%i] %@", type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
self.smtpSession = [[MCOSMTPSession alloc] init];
self.smtpSession.hostname = smtpHostname;
self.smtpSession.port = smtpPort;
self.smtpSession.username = emailAddress;
self.smtpSession.connectionType = MCOConnectionTypeTLS;
self.smtpSession.password = nil;
self.smtpSession.OAuth2Token = oAuthToken;
self.smtpSession.authType = nil != oAuthToken ? MCOAuthTypeXOAuth2 :
self.smtpSession.authType;
[self.smtpSession setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data){
NSLog(@"MCOSMTPSession: [%i] %@", type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
[[self.imapSession checkAccountOperation] start:^(NSError *error) {
if (nil == error) {
success();
} else {
failure(error); //FAILS WITH INVALID CREDENTIALS ERROR
}
}];
}
再次,上面的代碼工作正常,除非應用程序還沒有在一段時間內使用。我不知道如果我需要刷新OAuthToken與否,所以我試着做在啓動應用程序的以下情況:
GTMOAuth2Authentication *auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:KeychainItemName clientID:GmailAppClientID clientSecret:GmailClientSecret];
BOOL canAuthorize = [auth canAuthorize]; //returns YES
NSDictionary *googleSettings = [[EmailServicesInfo emailServicesInfoDict] objectForKey:Gmail];
[[ModelManager sharedDefaultInstance] authenticateWithEmailAddress:[auth userEmail] oAuthToken:[auth refreshToken] imapHostname:[googleSettings objectForKey:IMAPHostName] imapPort:[[googleSettings objectForKey:IMAPPort]integerValue] smtpHostname:[googleSettings objectForKey:SMTPHostName] smtpPort:[[googleSettings objectForKey:SMTPPort]integerValue] type:EmailProtocolTypeImapAndSmtpGMail success:^(Account *account) {
//create IMAP session
} failure:^(NSError *error) {
NSLog(@"failure %@", error);
}];
但我仍然得到同樣的錯誤。我不知道爲什麼OAuth令牌停止工作或如何解決此問題。由於用戶能夠保存多個帳戶,我想知道是否需要爲核心數據中的每個帳戶保存刷新令牌,並在訪問令牌停止工作時使用該令牌?
感謝您的回覆。這是有道理的,只有一點困惑:如果我的應用程序允許用戶保存多個Gmail帳戶並在它們之間來回切換,那麼keychainItemName是否會因爲添加每個新帳戶而被覆蓋? (如果這個問題沒有意義,請原諒我,我仍然圍繞着這一切如何運作的大腦)。如果是這樣,那麼我不知道我將如何獲得特定帳戶的身份驗證對象以從中獲取新的令牌。 – jac300
你的問題是有道理的。每個用戶帳戶都需要爲您的應用程序授予一個單獨的刷新令牌。從粗略的代碼檢查看起來好像gtm-oauth2庫一次只能存在一個,但我不是100%確定的。也許嘗試合成併爲第二個和後續帳戶指定一個不同的keychainItemName? – aeijdenberg
謝謝,我會嘗試。這明確說明了一些事情。 – jac300