The OAuth documentation on http://apiwiki.twitter.com is atrocious. Therefore, I had to figure it out via trial and error.
First, you must obtain a key and secret when you register your application (http://twitter.com/oauth_clients/new). For Twitter, you must use the key and secret as assigned, unlike MySpace which requires you to prepend the API web address to the key.
In this example, I have a class named TTwitter defined below:
TTwitter = class(TObject) private FHTTP: TIdCustomHTTP; FSource: string; FTwitterClient: string; FTwitterClientVersion: string; FTwitterClientURL: string; FUserName: string; FPassword: string; FConsumer: TOAuthConsumer; FToken: TOAuthToken; FRequest: TOAuthRequest; FHMAC: TOAuthSignatureMethod_HMAC_SHA1; FKey: string; FSecret: string; FOAuth_token: string; FOAuth_token_secret: string; procedure SetSource(const Value: string); procedure SetTwitterClient(const Value: string); procedure SetTwitterClientVersion(const Value: string); procedure SetTwitterCLientURL(const Value: string); function UrlEncode(const S : String) : String; function _IntToHex(Value: Integer; Digits: Integer): string; function DeleteFirstChar(input: string): string; protected function GetTwitterOutputFormatType(TwitterOutputFormatType: TTwitterOutputFormatType): string; function GetTwitterObjectType(TwitterObjectType: TTwitterObjectType): string; function GetTwitterStatus(TwitterStatus: TTwitterStatus): string; function GetTwitterDirectMessage(TwitterDirectMessage: TTwitterDirectMessage): string; function GetTwitterFriendship(TwitterFriendship: TTwitterFriendship): string; function GetTwitterUser(TwitterUser: TTwitterUser): string; function GETCommand(URL: string): string; function POSTCommand(URL: string; Data: TStringList): string; public constructor Create; function GetPublicTimeLine(OutputFormatType: TTwitterOutputFormatType): string; function GetUserTimeLine(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string; function GetFriendsTimeLine(OutputFormatType: TTwitterOutputFormatType; since_id: string = ''; max_id: string = '';count: string = '' ; page: string = ''): string; function GetFriends(OutputFormatType: TTwitterOutputFormatType): string; function GetUserFollowers(OutputFormatType: TTwitterOutputFormatType): string; overload; function GetUserFollowers(parm: string; OutputFormatType: TTwitterOutputFormatType): string; overload; function Update(Status: string; OutputFormatType: TTwitterOutputFormatType): string; function Show(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string; function GetReplies(OutputFormatType: TTwitterOutputFormatType): string; function GetDirectMessages(OutputFormatType: TTwitterOutputFormatType): string; function GetDirectMessagesSent(OutputFormatType: TTwitterOutputFormatType): string; function PostDirectMessagesNew(OutputFormatType: TTwitterOutputFormatType; user, text: string): string; function PostDirectMessagesDestroy(id: string; OutputFormatType: TTwitterOutputFormatType): string; property Source: string read FSource write SetSource; property TwitterClient: string read FTwitterClient write SetTwitterClient; property TwitterClientVersion: string read FTwitterClientVersion write SetTwitterClientVersion; property TwitterClientURL: string read FTwitterClientURL write SetTwitterClientURL; property Consumer: TOAuthConsumer read FConsumer write FConsumer; property Token: TOAuthToken read FToken write FToken; property Request: TOAuthRequest read FRequest write FRequest; property HMAC: TOAuthSignatureMethod_HMAC_SHA1 read FHMAC write FHMAC; property Key: string read FKey write FKey; property Secret: string read FSecret write FSecret; property OAuth_token: string read FOAuth_token write FOAuth_token; property OAuth_token_secret: string read FOAuth_token_secret write FOAuth_token_secret; end;
In this example, I’m performing authentication on the OnShow event. Here, I create all necessary objects for the authentication process:
procedure TPTForm.FormShow(Sender: TObject); var Callback_URL: string; Key, Secret: string; Response, URL: string; endpos: integer; idHTTP: TIdHTTP; AuthForm: TAuthForm; oauth_token, oauth_token_secret: string; begin Twitter := TTwitter.Create; idHTTP := TIdHTTP.Create(nil); Twitter.Key := 'Twitter assigned key'; Twitter.Secret := 'Twitter assigned secret'; Twitter.Consumer := TOAuthConsumer.Create(Twitter.Key, Twitter.Secret); Twitter.HMAC := TOAuthSignatureMethod_HMAC_SHA1.Create;
The first step is to request a token, as demonstrated by the following code:
URL := 'http://twitter.com/oauth/request_token'; Twitter.Request := TOAuthRequest.Create(URL); Twitter.Request := Twitter.Request.FromConsumerAndToken(Twitter.Consumer, nil, URL); Twitter.Request.Sign_Request(Twitter.HMAC, Twitter.Consumer, nil); URL := URL + '?' + Twitter.Request.GetString; Response := idHTTP.Get(URL);
The server responds by sending back the oauth_token and oauth_token_secret. The following code parses the values from the response and creates the token object.
endpos := AnsiPos('&oauth_token_secret=', Response);
Twitter.OAuth_token := '';
Twitter.OAuth_token_secret := '';
Twitter.OAuth_token := Copy(Response, 13, endpos-13);
Response := Copy(Response, endpos, Length(Response));
Twitter.OAuth_token_secret := Copy(Response, 21, Length(Response));
Twitter.Token := TOAuthToken.Create(Twitter.OAuth_token, Twitter.OAuth_token_secret);
The next step is to request user authorization. In this example, I have created another form that contains an EmbeddedWB. This will allow the user to enter their credentials and authorize the application to access their data. The callback URL is specified in the OAuth specification, but is currently not used by Twitter.
URL := 'http://twitter.com/oauth/authorize'; Callback_URL := 'http://www.chuckbeasley.com'; URL := URL + '?' + 'oauth_token=' + Twitter.OAuth_token + '&' + 'oauth_token_secret=' + Twitter.OAuth_token_secret + '&oauth_callback=' + TOAuthUtil.urlEncodeRFC3986(Callback_URL); AuthForm := TAuthForm.Create(nil); AuthForm.EmbeddedWB1.Navigate(URL); AuthForm.ShowModal; AuthForm.Free;
After user authorization is obtained, the next step is to request the access token from the server.
URL := 'http://twitter.com/oauth/access_token'; Twitter.Consumer := nil; Twitter.Consumer := TOAuthConsumer.Create(Twitter.Key, Twitter.Secret, 'http://www.chuckbeasley.com'); Twitter.Request.HTTPURL := URL; Twitter.Request := Twitter.Request.FromConsumerAndToken(Twitter.Consumer, Twitter.Token, URL); Twitter.Request.Sign_Request(Twitter.HMAC, Twitter.Consumer, Twitter.Token); URL := URL + '?' + Twitter.Request.GetString; Response := idHTTP.Get(URL);
The server responds by sending back the access token oauth_token and oauth_token_secret. The following code parses the values from the response.
endpos := AnsiPos('&oauth_token_secret=', Response);
Twitter.OAuth_token := '';
Twitter.OAuth_token := Copy(Response, 13, endpos-13);
Response := Copy(Response, endpos, Length(Response));
endpos := AnsiPos('&user', Response);
Twitter.OAuth_token_secret := '';
Twitter.OAuth_token_secret := Copy(Response, 21, endpos-21);
end;
Now, we have everything necessary to request data from Twitter! The following code is the GetCommand method from the TTwitter class. This is a demonstration of how to request data from Twitter using OAuth.
function TTwitter.GETCommand(URL: string): string;
var
pos: integer;
begin
FConsumer := nil;
FConsumer := TOAuthConsumer.Create(FKey, FSecret, 'http://www.chuckbeasley.com');
FRequest := TOAuthRequest.Create(URL);
FRequest := Request.FromConsumerAndToken(FConsumer, nil, URL);
FRequest.HTTPURL := URL;
FToken := TOAuthToken.Create(FOAuth_token, FOAuth_token_secret);
FRequest := Request.FromConsumerAndToken(FConsumer, FToken, URL);
FRequest.Sign_Request(HMAC, Consumer, Token);
pos := AnsiPos('?', URL);
if pos = 0 then
URL := URL + '?' + Request.GetString
else
URL := URL + '&' + Request.GetString;
Result := FHTTP.Get(URL);
end;