HttpClient Digest authentication VB.Net - vb.net

I'm writing an .NET application that uses HttpClient to connect to the API and retrieve video.
The Documentation provided for "Cookie-based authentication" details the following to login:
Call GET /api/getNonce
In response you'll get a JSON object with realm and nonce (nonce is a session key for this user)
Calculate authentication hash auth_digest, using realm and nonce (see algorithm below)
Call and pass the "auth" parameter in the json request body GET /api/cookieLogin
Server will check authentication and set session cookies
Which then expands on "Calculating Authentication Hash" with the following steps:
Call GET /api/getNonce
In response you'll get a JSON object with realm and nonce
Translate user's username to the lower case
Check the required method ("GET" for HTTP GET requests, "POST" for HTTP POST
requests, "PLAY" for RTSP etc)
digest = md5_hex(user_name + ":" + realm + ":" + password)
partial_ha2 = md5_hex(method + ":")
simplified_ha2 = md5_hex(digest + ":" + nonce + ":" + partial_ha2)
auth_digest = base64(user_name + ":" + nonce + ":" + simplified_ha2)
Here auth_digest is the required authentication hash
I use this Article written in C# as a reference, converted it to VB.NET, change a little bit of code in it according to the requirement above and then implemented it into my program. But I always get an error like this
"The remote server returned an error: (403) Forbidden."
When I debug the program, the problem appears when reading DigestAuthFixer.vb class in GrabResponse Function on this line response = CType(request2.GetResponse(), HttpWebResponse) . I suspect that "auth_digest" didn't return the correct value so the web service to deny the request with a 403 error. My question is how to properly implement digest authentication using VB.Net ? Are there any standard methods or do I have to do it from scratch? Thanks in advance.
This is the code that I use to connect to the API and retrieve the video:
Download HTTPClient
Private Shared _host As String = "http://127.0.0.1:7001"
Private Shared _username As String = "user"
Private Shared _password As String = "password"
Dim auto As Boolean = False
Shared ReadOnly client As HttpClient = New HttpClient()
Public Async Function Download_HttpClient(ByVal cameraID As String _
, ByVal videoDT As String _
, ByVal duration As String _
, ByVal resolution As String _
, ByVal path As String) As Task(Of String)
Dim cookieContainer As New CookieContainer
Dim httpClientHandler As New HttpClientHandler
httpClientHandler.AllowAutoRedirect = True
httpClientHandler.UseCookies = True
httpClientHandler.CookieContainer = cookieContainer
Dim httpClient As New HttpClient(httpClientHandler)
Dim err As Boolean = False
Dim downloadFileName As String
'SET HTTPCLIENT HEADERS
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)")
'httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml")
httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+json,application/json")
httpClient.DefaultRequestHeaders.Add("Accept-Charset", "ISO-8859-1")
Dim downloadId As String = Nothing
Try
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls12 Or SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls
'GET USER RIGHTS
Dim login_url As String = _host + "/api/getNonce"
Dim login_parameter As String = "?user_name =" + _username + "&password=" + _password
Dim login_response As HttpResponseMessage = Await httpClient.GetAsync(login_url + login_parameter)
Dim login_contents As String = Await login_response.Content.ReadAsStringAsync()
'CALCULATE AUTHENTICATION HASH
Dim dir As String = "/dir/index.html"
Dim url As String = _host + "/api/getNonce"
Dim digest As NUI.DigestAuthFixer = New NUI.DigestAuthFixer(url, _username.ToLower, _password)
Dim auth As String = digest.GrabResponse(dir)
'CALL POST /api/cookieLogin
Dim client As HttpClient = New HttpClient
client.DefaultRequestHeaders.Accept.Add(New System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"))
Dim postData As New List(Of KeyValuePair(Of String, String))
postData.Add(New KeyValuePair(Of String, String)("auth_digest ", auth))
Dim content As New FormUrlEncodedContent(postData)
content.Headers.ContentType = New Headers.MediaTypeHeaderValue("application/x-runtime-guid")
Dim response As HttpResponseMessage = client.PostAsync(New Uri(_host + "/api/cookieLogin"), content).Result
If response.IsSuccessStatusCode Then
MsgBox("POST CookieLogin Successfully")
Else
MsgBox(response)
End If
Catch ex As Exception
MessageBox.Show("Invalid response from the server due to connection limitation or firewall blocking your request")
Return ex.ToString()
End Try
'CREATE DOWNLOAD URL
Dim download_url As String = _host + "/media/" + cameraID + ".mkv"
Dim download_param As String = "?pos=" + videoDT + "&duration=" + duration + "&resolution=" + resolution
Dim downloadFile As String = download_url + download_param
'GET REQUEST AND DOWNLOAD
Dim file_response = Await httpClient.GetAsync(downloadFile)
Dim file_header = file_response.Content.Headers.GetValues("Content-Disposition")
Dim temp_string() As String = file_header.ToArray()
temp_string = temp_string(0).Split("=")
downloadFileName = temp_string(1).Replace("""", "")
Try
Using fs As New FileStream(path & downloadFileName, FileMode.Create)
Await file_response.Content.CopyToAsync(fs)
End Using
Catch ex As Exception
MessageBox.Show("Directory does not exists, please manually change the folder target")
Return ex.ToString()
End Try
Return "Download successfully"
End Function
DigestAuthFixer.vb class
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Security.Cryptography
Imports System.Text.RegularExpressions
Imports System.Net
Imports System.IO
Imports System.Net.Http
Namespace NUI
Public Class DigestAuthFixer
Private Shared _host As String
Private Shared _user As String
Private Shared _password As String
Private Shared _realm As String
Private Shared _nonce As String
Private Shared _qop As String
Private Shared _cnonce As String
Private Shared _cnonceDate As DateTime
Private Shared _nc As Integer
Public Sub New(ByVal host As String, ByVal user As String, ByVal password As String)
_host = host
_user = user
_password = password
End Sub
Private Function CalculateMd5Hash(ByVal input As String) As String
Dim inputBytes As Byte() = Encoding.GetEncoding("ISO-8859-1").GetBytes(input)
Dim hash = MD5.Create().ComputeHash(inputBytes)
Dim sb As New System.Text.StringBuilder()
For Each b In hash
sb.Append(b.ToString("x2"))
Next b
Return sb.ToString()
End Function
Private Function GrabHeaderVar(ByVal varName As String, ByVal header As String) As String
Dim regHeader = New Regex(String.Format("{0}=""([^""]*)""", varName))
Dim matchHeader = regHeader.Match(header)
If matchHeader.Success Then Return matchHeader.Groups(1).Value
Throw New ApplicationException(String.Format("Header {0} not found", varName))
End Function
Private Function GetDigestHeader(ByVal dir As String) As String
Dim digest = CalculateMd5Hash(_user.ToLower + ":" + _realm + ":" + _password)
Dim partial_ha2 = CalculateMd5Hash("GET" + ":")
Dim simplified_ha2 = CalculateMd5Hash(digest + ":" + _nonce + ":" + partial_ha2)
Dim auth_digest = (_user.ToLower + ":" + _nonce + ":" + simplified_ha2)
Return auth_digest
End Function
Public Function GrabResponse(ByVal dir As String) As String
Dim url = _host & dir
Dim uri = New Uri(url)
Dim request = CType(WebRequest.Create(uri), HttpWebRequest)
If Not String.IsNullOrEmpty(_cnonce) AndAlso DateTime.Now.Subtract(_cnonceDate).TotalHours < 1.0 Then
request.Headers.Add("Authorization", GetDigestHeader(dir))
End If
Dim response As HttpWebResponse
Try
response = CType(request.GetResponse(), HttpWebResponse)
Catch ex As WebException
If ex.Response Is Nothing OrElse (CType(ex.Response, HttpWebResponse)).StatusCode <> HttpStatusCode.Unauthorized Then Throw
Dim wwwAuthenticateHeader = ex.Response.Headers("WWW-Authenticate")
_realm = GrabHeaderVar("realm", wwwAuthenticateHeader)
_nonce = GrabHeaderVar("nonce", wwwAuthenticateHeader)
_qop = "auth"
_nc = 0
_cnonce = New Random().[Next](123400, 9999999).ToString()
_cnonceDate = DateTime.Now
Dim request2 = CType(WebRequest.Create(uri), HttpWebRequest)
request2.Headers.Add("Authorization", GetDigestHeader(dir))
response = CType(request2.GetResponse(), HttpWebResponse)
End Try
Dim reader = New StreamReader(response.GetResponseStream())
Return reader.ReadToEnd()
End Function
End Class
End Namespace

Related

Google Drive v3 Resumable Upload

I am trying to figure out how to use Google drive v3 resumable upload on vb.net to upload big files.
I've checked this https://developers.google.com/drive/v3/web/resumable-upload and was able to upload small files using basic upload but can't find any code samples for resumable upload using vb.net.
I managed to get it done, here's the final code in case somebody else needs:
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Drive.v3
Imports Google.Apis.Services
Imports Google.Apis.Upload
Imports Google.Apis.Util.Store
Module Module1
Dim credential As UserCredential
Dim ApplicationName As String = "NET"
Dim Scopes As String() = {DriveService.Scope.Drive}
Sub Main()
Using stream = New FileStream("client_secret.json", FileMode.Open, FileAccess.Read)
Dim credPath As String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json")
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result
Console.WriteLine(Convert.ToString("Credential file saved to: ") & credPath)
End Using
Dim service = New DriveService(New BaseClientService.Initializer() With {
.HttpClientInitializer = credential,
.ApplicationName = ApplicationName
})
Task.Run(Async Function()
Await UploadFileAsync(service, credential.Token.AccessToken, "welcome.mp4", "video/mp4", DateTime.Now.ToString("HH:mm:ss tt"))
End Function).GetAwaiter().GetResult()
Console.WriteLine("Press any key to continue...")
Console.ReadKey()
End Sub
Private Async Function UploadFileAsync(service As DriveService, accessToken As String, filePath As String, mimeType As String, newFileName As String) As Task(Of Boolean)
Dim uri As Uri
Dim uploadStream = New System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)
Using client = New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken)
client.DefaultRequestHeaders.Add("X-Upload-Content-Type", mimeType)
client.DefaultRequestHeaders.Add("X-Upload-Content-Length", uploadStream.Length.ToString())
Dim request = New HttpRequestMessage(HttpMethod.Post, "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable")
request.Content = New StringContent("{""name"": """ + newFileName + """, ""parents"":[""folder_id_goes_here""]}")
request.Content.Headers.ContentType = New MediaTypeHeaderValue("application/json")
Dim response = Await client.SendAsync(request)
uri = response.Headers.Location
End Using
Dim uploader = ResumableUpload.CreateFromUploadUri(uri, uploadStream, New ResumableUploadOptions())
AddHandler uploader.ProgressChanged, AddressOf Upload_ProgressChanged
Dim progress As IUploadProgress
progress = Await uploader.UploadAsync()
If progress.Status <> UploadStatus.Completed Then
While (Await uploader.ResumeAsync()).Status <> UploadStatus.Completed
Await Task.Delay(10000)
End While
End If
uploadStream.Dispose()
Return True
End Function
Private Sub Upload_ProgressChanged(progress As IUploadProgress)
Console.WriteLine(progress.Status.ToString() & " " & progress.BytesSent)
End Sub
End Module

Connecting a VB.NET application with a Google Docs Spreadsheet

I'm creating a small application that can order stuff. The way a user can order something is to input the correct information through a google form, which then would be automatically converted to a Google Spreadsheet.
Now, I want to connect it to my VB application. How can I do that?
You should install sheetsapi v4 to your app.
Here is the code:
Public Class Form3
Shared Scopes As String() = {SheetsService.Scope.SpreadsheetsReadonly}
Shared ApplicationName As String = "Google Sheets API .NET Quickstart"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim credential As UserCredential
Using stream = New FileStream("client_secret.json", FileMode.Open, FileAccess.Read)
Dim credPath As String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
credPath = Path.Combine(credPath, ".credentials/sheets.googleapis.com-dotnet-quickstart.json")
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result
Console.WriteLine(Convert.ToString("Credential file saved to: ") & credPath)
End Using
Dim service = New SheetsService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = credential, _
.ApplicationName = ApplicationName })
Dim spreadsheetId As [String] = "your sheet id"
Dim range As [String] = "A2:F"
Dim request As SpreadsheetsResource.ValuesResource.GetRequest = service.Spreadsheets.Values.[Get](spreadsheetId, range)
Dim response As ValueRange = request.Execute()
Dim values As IList(Of IList(Of [Object])) = response.Values
Dim son As String
If values IsNot Nothing AndAlso values.Count > 0 Then
ListBox1.Items.Add("Name, Major")
For Each rol In values
son = rol(0) + " " + rol(1) + " " + rol(2) + " " + rol(4)
' Print columns A and E, which correspond to indices 0 and 4.
ListBox1.Items.Add(son)
Next
End If
End Sub
End Class

call http get using proxy

How can I edit the code to accept proxy?
CallHttp functions
Public Shared Function CallHttp(ByVal url As String, _
ByVal params As String, _
ByVal httpPost As Boolean) As String
If httpPost Then
Return CallHttpPost(url, params)
Else
Return CallHttpGet(url, params)
End If
End Function
CallHttpPost function:
Protected Shared Function CallHttpPost(ByVal url As String, _
ByVal params As String) As String
Dim loHttp As HttpWebRequest
'params = QueryStringEncode(params, TypeEncodeEnum.urlEncode)
loHttp = CType(WebRequest.Create(url), HttpWebRequest)
loHttp.Method = "POST"
Dim requestWriter As StreamWriter = New StreamWriter(loHttp.GetRequestStream())
If Not String.IsNullOrEmpty(params) Then
requestWriter.Write(params)
End If
requestWriter.Close()
loHttp.ContentType = "application/x-www-form-urlencoded"
loHttp.Headers.Set("Pragma", "no-cache")
loHttp.AllowAutoRedirect = True
loHttp.KeepAlive = True
loHttp.Timeout = 30 * 1000
'loHttp.Referer = url
Dim loWebResponse As HttpWebResponse = CType(loHttp.GetResponse(), HttpWebResponse)
Dim enc As Encoding = System.Text.Encoding.UTF8
Dim loResponseStream As StreamReader = New StreamReader(loWebResponse.GetResponseStream(), enc)
Dim lcHtml As String = loResponseStream.ReadToEnd()
loWebResponse.Close()
loResponseStream.Close()
Return lcHtml
End Function
Im behind a corporate firewall and I get a 407 proxy authentication required error if I use the function like this
strXML = CallHttp(API_URL, sb.ToString, False)
any ideas?
user and pass are the authentication of your proxy
Dim myProxy As New WebProxy("192.168.1.2:8080")
Dim authentication As New System.Net.NetworkCredential("user", "pwd")
myProxy.Credentials = authentication
Dim loHttp As HttpWebRequest
loHttp .Proxy = myProxy

Upload File to Amazon S3

Let me explain my requirement..
I want to store files uploaded to my app (by clients) to Amazon S3..
File Size ~ 1-10 MB
However, the client interface has to be a REST API
provided by my application. Consequently, after parsing file upload (HTTP POST) request, my application must store the file in S3.
As a result, I have to store file temporarily on disk before uploading to S3..
Is there a workaround? Can I do away with temporary file store on my server.. Please let me know if I am not clear..
EDIT - Is it OK to get byte array from FileItem object and store it rather than the file itself..?
Your whole idea is to avoid I/O right ? you don't need to save the file before doing the upload, you could simple send the array of bytes to amazon REST API.
Here is my sample VB.NET code that do both upload and download:
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Net
Imports System.Security.Cryptography
Imports System.Text
Imports System.Threading.Tasks
Module Module1
Sub Main()
Dim obj As New Program
obj.UploadFile()
'obj.DownloadFile() 'Download Example
End Sub
End Module
Class Program
Private Const KeyId As String = "yourkey"
Private Const AccessKey As String = "your/access"
Private Const S3Url As String = "https://s3.amazonaws.com/"
Public Sub DownloadFile()
Dim bucketName As String = "yourbucket"
Dim FileName As String = "file.png"
Dim timeStamp As String = String.Format("{0:r}", DateTime.UtcNow)
Dim stringToConvert As String = Convert.ToString((Convert.ToString((Convert.ToString("GET" & vbLf + vbLf + vbLf + vbLf + "x-amz-date:") & timeStamp) + vbLf + "/") & bucketName) + "/") & FileName
Dim ae = New UTF8Encoding()
Dim signature = New HMACSHA1() With { _
.Key = ae.GetBytes(AccessKey) _
}
Dim bytes = ae.GetBytes(stringToConvert)
Dim moreBytes = signature.ComputeHash(bytes)
Dim encodedCanonical = Convert.ToBase64String(moreBytes)
' Send the request
Dim request As HttpWebRequest = DirectCast(HttpWebRequest.Create(Convert.ToString((Convert.ToString("https://") & bucketName) + ".s3.amazonaws.com" + "/") & FileName), HttpWebRequest)
'request.ContentType = "application/octet-stream";
request.Headers.Add("x-amz-date", timeStamp)
request.Headers.Add("Authorization", "AWS " + KeyId + ":" + encodedCanonical)
request.Method = "GET"
' Get the response
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
Dim ReceiveStream As Stream = response.GetResponseStream()
Console.WriteLine(response.StatusCode)
End Sub
Public Sub UploadFile()
Dim fileData = File.ReadAllBytes("C:\file.png")
Dim timeStamp As String = String.Format("{0:r}", DateTime.UtcNow)
Dim stringToConvert As String = (Convert.ToString("PUT" & vbLf + vbLf + "application/octet-stream" & vbLf + vbLf + "x-amz-acl:public-read" + vbLf + "x-amz-date:") & timeStamp) + vbLf + "/celso711/file.png"
'resource
Dim ae = New UTF8Encoding()
Dim signature = New HMACSHA1() With { _
.Key = ae.GetBytes(AccessKey) _
}
Dim bytes = ae.GetBytes(stringToConvert)
Dim moreBytes = signature.ComputeHash(bytes)
Dim encodedCanonical = Convert.ToBase64String(moreBytes)
Dim url = "https://bucket.s3.amazonaws.com/file.png"
Dim request = TryCast(WebRequest.Create(url), HttpWebRequest)
request.Method = "PUT"
request.Headers("x-amz-date") = timeStamp
request.Headers("x-amz-acl") = "public-read"
request.ContentType = "application/octet-stream"
request.ContentLength = fileData.Length
request.Headers("Authorization") = (Convert.ToString("AWS ") & KeyId) + ":" + encodedCanonical
Dim requestStream = request.GetRequestStream()
requestStream.Write(fileData, 0, fileData.Length)
requestStream.Close()
Using response = TryCast(request.GetResponse(), HttpWebResponse)
Dim reader = New StreamReader(response.GetResponseStream())
Dim data = reader.ReadToEnd()
End Using
End Sub
End Class

Creating webrequest POST for Twitter API using VB.NET

There are quite a few Twitter API related posts, but none seem to answer my questions directly.
I know how to send an HttpWebRequest as POST.
I am fairly sure I need to send the webrequest to: "https://api.twitter.com/1/statuses/update.json" (not totally clear)
I know there are many libraries out there that all you have to do is pass your consumer keys and token keys. However, I need to create some very short code, in a function, that simple posts a hard coded string to Twitter. When I get this working that hard coded string will be replaced by variable.
I've no need to status updates or any kind of information from Twitter. Just POST "Hello World!" to start with, and I can go from there.
I am forced to use VB.NET. I am using Visual Studio Web Developer 2010.
Now, that all said, I have looked at Nikolas Tarzia's VB.NET port of C-Sharp code here:
http://oauth.googlecode.com/svn/code/vbnet/oAuth.vb
I can see roughly what the functions do by looking at them, but have no idea which ones I need to call to create a webresponse and send to Twitter! Also I believe this code contains more than I need. If I just want to create a POST, then likely I only need to hash function and the nonce function and my tokens and keys. Is that right? If so, could someone please help me narrow this down? In the process helping me understand a bit better what properly formed webrequest needs to be sent to Twitter to make a quick Tweet?
Thanks,
Will
PS - I finally put together some code, based on looking at OAuth documentation, a neat little code example on using POST request in VB, and the Twitter Developer area OAuth tool to generate some Base String for the request. Unfortunately while it compiles and runs okay, I am not getting a tweet. Could someone have a look at the code and see if they can spot any glaring issues? Obviously I replaced my tokens and consumer keys with "xxxxx". All I want for Christmas is to run this code and make a quick Tweet on my Twitter account! ;)
Public Shared Function Tweet(strText As String) As Boolean
Dim boolResult As Boolean = False
Dim urlAddress As Uri = New Uri("https://api.twitter.com/1/statuses/update.json")
Dim strData As StringBuilder
Dim byteData() As Byte
Dim postStream As Stream = Nothing
Dim strConsumerKey As String = "xxxxxx"
Dim strConsumerSecret As String = "xxxxxx"
Dim strAccessToken As String = "xxxxxx"
Dim strAccessTokenSecret As String = "xxxxxx"
Dim objRequest As HttpWebRequest
Dim objResponse As HttpWebResponse = Nothing
Dim objReader As StreamReader
Dim objHeader As HttpRequestHeader = HttpRequestHeader.Authorization
Try
objRequest = DirectCast(WebRequest.Create(urlAddress), HttpWebRequest)
objRequest.Method = "POST"
objRequest.ContentType = "application/x-www-form-urlencoded"
strData = New StringBuilder()
strData.Append("&Hello_World%2521%3D%26oauth_consumer_key%3D" + strConsumerKey + "%26oauth_nonce%3Dda6bb8ce7e48547692f4854833afa680%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1329746260%26oauth_token%3D" + strAccessToken + "%26oauth_version%3D1.0")
objRequest.Headers.Add(objHeader, "Authorization: OAuth oauth_consumer_key=""xxxx"", oauth_nonce=""da6bb8ce7e48547692f4854833afa680"", oauth_signature=""xxxx"", oauth_signature_method=""HMAC-SHA1"", oauth_timestamp=""1329750426"", oauth_token=""xxxx"", oauth_version=""1.0""")
' Create a byte array of the data we want to send
byteData = UTF8Encoding.UTF8.GetBytes(strData.ToString())
' Set the content length in the request headers
objRequest.ContentLength = byteData.Length
Try
postStream = objRequest.GetRequestStream()
postStream.Write(byteData, 0, byteData.Length)
Finally
If Not postStream Is Nothing Then postStream.Close()
End Try
boolResult = True
Catch ex As Exception
boolResult = False
HttpContext.Current.Session.Add("Error", ex.ToString())
End Try
Try
' Get response
objResponse = DirectCast(objRequest.GetResponse(), HttpWebResponse)
' Get the response stream into a reader
objReader = New StreamReader(objResponse.GetResponseStream())
' Console application output
Console.WriteLine(objReader.ReadToEnd())
Finally
If Not objResponse Is Nothing Then objResponse.Close()
End Try
Return boolResult
End Function
I´ve made this class to post in twitter using API1.1.
It expects the oauth token, oauth token secret, oauth "consumer" key (this means API key) and oauth consumer secret (this means API secret) in the constructor. If you want to post in your own account, the four values will be in the API keys tab of your application in https://apps.twitter.com/. If you want to post on your visitors account you'll have to create some extra code to redirect them to twitter for login and get the access token.
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Text
Imports System.Security.Cryptography
Imports System.Net
Imports System.IO
Public Class SBTwitter
Private oauth_token As String
Private oauth_token_secret As String
Private oauth_consumer_key As String
Private oauth_consumer_secret As String
Public Sub New(ByVal APIKey As String, ByVal APISecret As String, ByVal oauthToken As String, ByVal oauthTokenSecret As String)
oauth_token = oauthToken
oauth_token_secret = oauthTokenSecret
oauth_consumer_key = APIKey
oauth_consumer_secret = APISecret
End Sub
Public Function PostInTwitter(ByVal post As String) As String
Try
Dim oauth_version = "1.0"
Dim oauth_signature_method = "HMAC-SHA1"
Dim oauth_nonce = Convert.ToBase64String(New ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()))
Dim timeSpan = DateTime.UtcNow - New DateTime(1970, 1, 1, 0, 0, 0, _
0, DateTimeKind.Utc)
Dim oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString()
Dim resource_url = "https://api.twitter.com/1.1/statuses/update.json"
Dim status = post
Dim baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" & "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&status={6}"
Dim baseString = String.Format(baseFormat, oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_timestamp, oauth_token, _
oauth_version, Uri.EscapeDataString(status))
baseString = String.Concat("POST&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString))
Dim compositeKey = String.Concat(Uri.EscapeDataString(oauth_consumer_secret), "&", Uri.EscapeDataString(oauth_token_secret))
Dim oauth_signature As String
Using hasher As New HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey))
oauth_signature = Convert.ToBase64String(hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)))
End Using
Dim headerFormat = "OAuth oauth_nonce=""{0}"", oauth_signature_method=""{1}"", " & "oauth_timestamp=""{2}"", oauth_consumer_key=""{3}"", " & "oauth_token=""{4}"", oauth_signature=""{5}"", " & "oauth_version=""{6}"""
Dim authHeader = String.Format(headerFormat, Uri.EscapeDataString(oauth_nonce), Uri.EscapeDataString(oauth_signature_method), Uri.EscapeDataString(oauth_timestamp), Uri.EscapeDataString(oauth_consumer_key), Uri.EscapeDataString(oauth_token), _
Uri.EscapeDataString(oauth_signature), Uri.EscapeDataString(oauth_version))
Dim postBody = "status=" & Uri.EscapeDataString(status)
ServicePointManager.Expect100Continue = False
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(resource_url), HttpWebRequest)
request.Headers.Add("Authorization", authHeader)
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
Using stream As Stream = request.GetRequestStream()
Dim content As Byte() = ASCIIEncoding.ASCII.GetBytes(postBody)
stream.Write(content, 0, content.Length)
End Using
Dim response As WebResponse = request.GetResponse()
Return response.ToString
Catch ex As Exception
Return ex.Message
End Try
End Function
End Class