I am trying to authenticate my web application with google oauth2. I am using vb.net as code behind.
At first step I added a hyperlink which redirect to https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=%2Fprofile&redirect_uri=http%3A%2F%2Flocalhost:2690%2Ftest1.aspx&response_type=code&client_id=XXX.apps.googleusercontent.com
Now after receiving code from code, I used code on page load of test1.aspx
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsNullOrEmpty(Request.QueryString("code")) Then
Dim buffer As Byte() = Encoding.UTF8.GetBytes("code=" + Request.QueryString("code") + "&client_id=XXX.apps.googleusercontent.com&client_secret=XXX&redirect_uri=https%3A%2F%2Flocalhost:2690%2Ftest1.aspx&grant_type=authorization_code")
Dim req As HttpWebRequest = WebRequest.Create("https://accounts.google.com/o/oauth2/token")
req.Method = "POST"
req.ContentType = "application/x-www-form-urlencoded"
req.ContentLength = buffer.Length
Dim strm As Stream = req.GetRequestStream()
strm.Write(buffer, 0, buffer.Length)
strm.Close()
Try
Dim res As HttpWebResponse = req.GetResponse()
Response.Write(res.StatusDescription)
Catch wex As WebException
Response.Write(wex.Data.ToString + "<br/>" + wex.InnerException.ToString + "<br/>" + wex.Message + "<br/>" + wex.TargetSite.ToString)
End Try
End If
End Sub
Each time I am getting bad request error from server. Please help me to find out what I am doing wrong. I also tried to use dotnetopenauth but each example is using mvc and c# and I only know vb.net.
Thanks for your help….
Is this code URLencoding the values in the body of the POST request.
Also keep in mind that the code is to be exchanged once for tokens.
Related
I try to GET query from MVC app to OWIN SelfHost. Both have WindowsAuth. MVC is running from Visual Studio in one virtual machine, OWIN SelfHost works as service in other virtual machine. Response is always 401. I tried to set Credentials,PreAuthenticate in WebRequest - nothing changed. I can't let anonymous auth in my system. How I should make request? Thanks.
The solution was found:
WebRequest req = WebRequest.Create(Properties.Settings.Default.SelfHostAdress + "/api/data/GetReportsOrgStructTreeView?currentUserName=" + currentUsername + "&parentNodeId=" + parentNodeId + "&filterId=" + filterId);
req.UseDefaultCredentials = true;
req.PreAuthenticate = true;
WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
content = sr.ReadToEnd();
return content;
Using MVC.
Function Login(ByVal token As String) As ActionResult
Using client As New WebClient
Try
Dim jsonResponse As String = client.DownloadString(URL & "/Getuser&token=" & token)
Dim obj As UserInfo = Newtonsoft.Json.JsonConvert.DeserializeObject(Of UserInfo)(jsonResponse)
Response.Cookies.Add(New HttpCookie("token", token))
Response.Cookies.Add(New HttpCookie("user_id", obj.id))
Return Json(obj)
Catch ex As WebException
Return Content("ERROR")
Catch ex As Exception
Return Content("ERROR")
End Try
End Using
End Function
I am sending a token to this function.
Then Using this token to get the User Info from a certain API
Then Storing this token in a HttpCookie
All this has been working fine for almost a month,
Until it stopped working.
When I debugged, token had a value, and it stored it in the HttpCookie, but when I called Request.Cookies("token").Value it returned ''
Any help would be appreciated.
I did a trace on the Token..
I am writing the parameter "token" in a file before storing it in the cookie.
then I am writing the cookie Request.Cookies("token").Value in a file,
Function Login(ByVal token As String) As ActionResult
WriteToFile("TOKEN RECEIVED = ", token)
Using client As New WebClient
Try
Dim jsonResponse As String = client.DownloadString(URL & "/Getuser&token=" & token)
Dim obj As UserInfo = Newtonsoft.Json.JsonConvert.DeserializeObject(Of UserInfo)(jsonResponse)
Response.Cookies.Add(New HttpCookie("token", token))
Response.Cookies.Add(New HttpCookie("user_id", obj.id))
WriteToFile("TOKEN COOKIE = ", Request.Cookies("token").Value)
Return Json(obj)
Catch ex As WebException
Return Content("ERROR")
Catch ex As Exception
Return Content("ERROR")
End Try
End Using
End Function
it returns the following:
TOKEN RECEIVED = X132WEeRT3AASDV
TOKEN COOKIE =
When I try to write both Request and Response Cookies:
WriteToFile("TOKEN COOKIE = ", Request.Cookies("token").Value)
WriteToFile("TOKEN COOKIE = ", Response.Cookies("token").Value)
Request.Cookies("token").Value Returns Empty String
Response.Cookies("token").Value Returns Actual Value
Maybe your cookie just expire after one month? When using cookies don't forget to set expiration date, and check web browser settings (example: if you are using "tor browser bundle" this can be an issue).
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie["Font"] = "Arial";
myCookie["Color"] = "Blue";
myCookie.Expires = DateTime.Now.AddDays(1d);
Response.Cookies.Add(myCookie);
https://msdn.microsoft.com/en-us/library/78c837bd%28v=vs.140%29.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Make sure you access the cookies only during the actual Http request. Maybe you have changed the way (or place where) you call this function.
This is an old question on SO but for those interested, .NET team has created a new method to properly handle cookies.
This is available in .NET 4.7.1 and not earlier versions:
See under the section ASP.NET HttpCookie parsing here
https://blogs.msdn.microsoft.com/dotnet/2017/09/13/net-framework-4-7-1-asp-net-and-configuration-features/
I have successfully done this in the past for other services, however with box.com I get an error and I've tried everything I could think off and that others have suggested here.
I'm using .NET C#;
string postdata = "";
postdata += "client_id=" + HttpUtility.UrlEncode(client_id) + "&";
postdata += "client_secret=" + HttpUtility.UrlEncode(client_secret) + "&";
postdata += "refresh_token=" + HttpUtility.UrlEncode(refreshToken) + "&";
postdata += "redirect_uri=" + HttpUtility.UrlEncode(_redirectUri) + "&";
postdata += "grant_type=refresh_token";
var json = PostResponse(new Uri(#"https://www.box.com/api/oauth2/token"), postdata);
I've tried both with and without urlencoding of the values. Normally urlencoding is not needed in my experience.
I've also tried different order of parameters.
private string PostResponse(Uri uri, string postdata)
{
var bytes = Encoding.UTF8.GetBytes(postdata);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
request.ContentLength = bytes.Length;
Stream OutputStream = request.GetRequestStream();
OutputStream.Write(bytes, 0, bytes.Length);
var response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
This code fails with error 400 (bad request). Similar code works fine with for example Google Drive.
Can anyone spot what I'm doing wrong with box.com? Thanks!
Got it working using box_device_id and box_device_name (indirectly part of my problem) plus examining the response in details which showed that a json error message was returned stating that the refresh token had expired. Turns out that Box expires refresh tokens when using them, issuing a new one. This is different from the other cloud drives I've integrated with.
I have been looking for a way to remove an attachment from Jira using the SOAP Api, but it seems that this is not possible natively, and I would prefer not having to implement a new plugin for Jira, as suggested in the accepted answer to this question, or recompiling the existing plugin to support this as mentioned here.
This answer to the abovementioned question seems to do exactly what I want, but alas, I can't get i to work. The response i get is an error stating that:
XSRF Security Token Missing
JIRA could not complete this action due to a missing form token.
You may have cleared your browser cookies, which could have resulted in the expiry of your current form token. A new form token has been reissued.
As I am using Asp.Net MVC C#, I have used the code from the answer, as is, with only the server url adjusted, as well as with different credentials (a Jira user) and the username/password passed through as request parameters using:
os_username=jirausername&os_password=xxxxxxx
The code I am currently using is as follows:
public void RemoveAttachment(string issueid, string attachmentid)
{
using (System.Net.WebClient client = new System.Net.WebClient())
{
//Compute jira server base url from WS url
string baseUrl = _service.Url.Substring(0, _service.Url.IndexOf("/rpc/"));
//Compute complete attachment url
string attachmenturl = baseUrl + "/secure/DeleteAttachment.jspa?id=" +
issueid + "&deleteAttachmentId=" + attachmentid;
client.Credentials = new System.Net.NetworkCredential("jirausername", "xxxxxxx");
string response = client.DownloadString(attachmenturl);
}
}
I ended up using a method that first requests the deletion confirmation form, then extracts a required token from the form, and finally posts something equivalent to the form content in order to delete the attachment. Code below.
public void RemoveAttachment(string issueid, string attachmentid)
{
//Compute jira server base url from WS url
string baseUrl = _service.Url.Substring(0, _service.Url.IndexOf("/rpc/"));
//Compute complete attachment deletion confirm url
string confirmurl = baseUrl + "/secure/DeleteAttachment!default.jspa?id=" +
issueid + "&deleteAttachmentId=" + attachmentid + "&os_username=jirauser&os_password=xxxxxx";
//Create a cookie container to maintain the xsrf security token cookie.
CookieContainer jiracontainer = new CookieContainer();
//Create a get request for the page containing the delete confirmation.
HttpWebRequest confirmrequest = (HttpWebRequest)WebRequest.Create(confirmurl);
confirmrequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
confirmrequest.CookieContainer = jiracontainer;
//Get the response and the responsestream.
WebResponse confirmdeleteresponse = confirmrequest.GetResponse();
Stream ReceiveStream = confirmdeleteresponse.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader confirmreader = new StreamReader(ReceiveStream);
// Read the content.
string confirmresponse = confirmreader.ReadToEnd();
//Create a regex to extract the atl/xsrf token from a hidden field. (Might be nicer to read it from a cookie, which should also be possible).
Regex atl_token_matcher = new Regex("<input[^>]*id=\"atl_token\"[^>]*value=\"(?<token>\\S+)\"[^>]*>", RegexOptions.Singleline);
Match token_match = atl_token_matcher.Match(confirmresponse);
if (token_match.Success)
{
//If we found the token get the value.
string token = token_match.Groups["token"].Value;
//Compute attachment delete url.
string deleteurl = baseUrl + "/secure/DeleteAttachment.jspa";
//Construct form data.
string postdata = "atl_token=" + HttpContext.Current.Server.UrlEncode(token) + "&id=" + issueid + "&deleteAttachmentId=" + attachmentid + "&Delete=Delete&os_username=jirauser&os_password=xxxxxx";
//Create a post request for the deletion page.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(deleteurl);
request.KeepAlive = false;
request.CookieContainer = jiracontainer; // Remember to set the cookiecontainer.
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";
//Turn our request string into a byte stream
byte[] postBytes = Encoding.ASCII.GetBytes(postdata);
//Make sure you specify the proper type.
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
//Send the post.
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
//Get the response.
WebResponse deleteresponse = request.GetResponse();
// Open the responsestream using a StreamReader for easy access.
StreamReader deleteresponsereader = new StreamReader(deleteresponse.GetResponseStream());
// Read the content.
string deleteresponsecontent = deleteresponsereader.ReadToEnd();
// do whatever validation/reporting with the response...
}
else
{
//We couldn't find the atl_token. Throw an error or something...
}
}
Edit:
Same thing works for removing comments. Replace 'attachment' with 'comment' and 'deleteAttachmentId' with 'commentId' and you should be good to go.
I'm trying to create an ASP.Net MVC endpoint to authenticate externally. The idea is so that I can call the endpoint from a console app, WPF app or whatever, and use the MVC pattern for my service, returning JSON to authenticated users, checking authentication via the attribute etc. I'm using a console app for now just because it's quick and simple.
I have this so far:
In my console app:
Public Sub MakeLoginRequest()
Dim address As Uri = New Uri("http://localhost:50536/Account/LogIn")
Dim request As HttpWebRequest = HttpWebRequest.Create(address)
request.Method = "POST"
request.ContentType = "application/json; charset=utf-8"
Dim loginModel As New LogOnModel With {.UserName = "Richard",
.Password = "Password1",
.RememberMe = False}
Dim jsonData As String = JsonConvert.SerializeObject(loginModel)
Dim bytes As Byte() = System.Text.Encoding.ASCII.GetBytes(jsonData)
request.GetRequestStream.Write(bytes, 0, bytes.Count)
Dim response As HttpWebResponse = request.GetResponse()
End Sub
In my controller:
<HttpPost()>
Public Function LogIn(model As LogOnModel) As ActionResult
If ModelState.IsValid Then
If Membership.ValidateUser(model.UserName, model.Password) Then
Dim cookie As HttpCookie = FormsAuthentication.GetAuthCookie(model.UserName, False)
cookie.Expires = DateTime.Now.AddMinutes(20)
Request.Cookies.Add(cookie)
Request.Cookies.Add(New HttpCookie("Barney", "Rubble"))
Return Content("Logged In Ok")
Else
Return New HttpUnauthorizedResult
End If
Else
Return New HttpUnauthorizedResult
End If
End Function
Now when I inspect the response in the console app, there are never any cookies - neither the real Auth cookie, nor my bogus Barney Rubble cookie actually appear!
However... I make the same call in Chrome and inspect the response... and both cookies are there!
Anyone any ideas as to what's going wrong?
You need to set a CookieContainer on your request as described here:
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.cookiecontainer.aspx