LoginSignup
22
23

More than 5 years have passed since last update.

Safariを使った端末側でのTwitter OAuth認証方法

Posted at

Twitter-OAuth-iPhoneを参考に、セキュリティコードのスクレイピングをしないものを作る。

OAuthConsumer を使う。
ARCへはXcodeで変換するか、上手くいかなければ手動で。
(※いちおう私がforkして変換したレポジトリはここにある)

以下のステップで見るようにコールバックURLとしてはiOSのカスタムURLスキームに割り当てるから本来設定は不要だが、Twitterのページにはhttp(s)しか指定できず、指定しないとなぜか以下のOAuth認証ステップが失敗するため、何でもよいのでhttp(s)の正常なURLを指定しておく。

  • iOSにてリクエストトークンを取得する。

-(void)requestRequestToken{
    self.consumer =[[OAConsumer alloc] initWithKey:@"consumer_key" secret:@"consumer_secret"];
    OAMutableURLRequest             *request = [[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"]  consumer: self.consumer token:nil realm:nil signatureProvider: nil];
    if (!request) return;

    [request setHTTPMethod: @"POST"];

    /*
     Added oauth_callback param to the request, which is required for OOB (out-of-band) authentication, without which
     twitter does not return a pin but redirects to the callback url set in the app on twitter.com, hence failing the authentication.
     https://dev.twitter.com/docs/auth/pin-based-authorization
     */
    NSMutableArray *params =  [[NSMutableArray alloc] initWithArray:request.parameters];
    [params addObject:[[OARequestParameter alloc] initWithName:@"oauth_callback" value:@"sample-app://" ]];
    request.parameters = params;

    self.fetcher = [[OADataFetcher alloc] init];
    [self.fetcher fetchDataWithRequest: request delegate: self didFinishSelector:@selector(setRequestToken:withData:)  didFailSelector: @selector(outhTicketFailed:data:)];

}

sample-app://はこのアプリで使うURL-Scheme
取得後には以下を呼ぶようにした。


- (void) setRequestToken: (OAServiceTicket *) ticket withData: (NSData *) data {
    if (!ticket.didSucceed || !data){
    }else{
        NSString *dataString = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
        if (!dataString) {

        }else{
            self.requestToken = [[OAToken alloc] initWithHTTPResponseBody:dataString];
            self.fetcher = nil;
            NSString *urlString = [NSString stringWithFormat:@"%@?oauth_token=%@",@"https://api.twitter.com/oauth/authorize", self.requestToken];
    [[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlString]];
        }
    }
}

これでSafariでTwitter認証のページが開かれる。
認証が終わると、-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urlにパラメータ付きで返ってくる。


-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
    if ([url.absoluteString hasPrefix:@"sample-app://"]) {
        NSDictionary *params = [NSDictionary parameterDictionaryWithURL:url];
        if (params[@"oauth_verifier"]) {
            [self requestAuthTokenWithOAuthToken:params[@"oauth_token"] verifier:params[@"oauth_verifier"]];
            return YES;
        }else{
            return NO;
        }
    }else{
        return NO;
    }
}


上記のようにoauth_verifierをパーズし、アクセストークンを取得しに行く。



-(void)requestAuthTokenWithOAuthToken:(NSString *)oauthToken verifier:(NSString *)verifier{
        if (![self.requestToken.key isEqualToString:oauthToken] || ! verifier.length) {

        }else{
            NSString *urlString = [ @"https://api.twitter.com/oauth/access_token" stringByAppendingFormat:@"?oauth_verifier=%@", verifier];
            OAMutableURLRequest     *request = [[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]  consumer: self.consumer token:self.requestToken realm:nil signatureProvider: nil];
            if (!request) return;
            [request setHTTPMethod: @"POST"];
            NSMutableArray *params =  [[NSMutableArray alloc] initWithArray:request.parameters];
            [params addObject:[[OARequestParameter alloc] initWithName:@"oauth_verifier" value:verifier]];
            [params addObject:[[OARequestParameter alloc]initWithName:@"oauth_token" value:oauthToken]];
            self.fetcher = [[OADataFetcher alloc] init];
            [self.fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(setAccessToken:withData:) didFailSelector:@selector(getAccessTokenFailed:data:)];
        }
    }
}

結果が返ってくると以下の関数が呼ばれるようにした。


- (void) setAccessToken: (OAServiceTicket *) ticket withData: (NSData *) data {
    if (!ticket.didSucceed || !data) return;

    NSString *dataString = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
    if (!dataString) return;
}

screen_name, user_id, oauth_token, oauth_token_secret が URLパラメータの形式で返ってくる。
例) screen_name=hoge&user_id=...

取得したtoken/token_secretのペアを用いて、この端末に関わらずTwitter APIにアクセスが可能になる。
TwitterのOAuth トークンは今のところ期限が設けられていないらしいので、ユーザが自身でリボークするまで使用できる。

22
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23