So I have two other topics open, one was a general question regarding getting documentation for a Windows program and the other was about registering a Windows program, and since posting those I have been researching what my problem might be - the API simply wasn’t working for a variety of reasons.
Someone on stackoverflow posted a question titled “Connecting to asana using webrequests” and since it was a comprehensive example in code that I understand (VB.NET, though my application is C#) I copied it into a new project, ran it, and it worked. Then I created a new C# project, converted the code, ran it and it did not work. The error is 401 unauthorized.
Why would I be authorized in the VB.NET version of the code but not in C#?
response = GetResponse("https://app.asana.com/api/1.0/tasks/x/stories?opt_pretty")
End Sub
Public Function GetResponse(uri As String, Optional data As String = "", Optional method As String = "GET") As String
System.Diagnostics.Trace.WriteLine(uri)
' Thanks to this person, https://stackoverflow.com/questions/39906750/cant-deserialize-asana-user-data-into-c-sharp-class, I know I have to do this (even though it's no C# anymore...)
' ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
' create request
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(uri), HttpWebRequest)
request.PreAuthenticate = True
request.Method = method
request.ContentType = "application/x-www-form-urlencoded"
' log in
Dim authInfo As String = "x/xxxxxxxxxxxxx" & ":" & ""
' blank password
authInfo = Convert.ToBase64String(Encoding.[Default].GetBytes(authInfo))
request.Headers("Authorization") = "Basic " & authInfo
' send data
If data <> "" Then
Dim paramBytes As Byte() = Encoding.ASCII.GetBytes(data)
request.ContentLength = paramBytes.Length
Dim reqStream As Stream = request.GetRequestStream()
reqStream.Write(paramBytes, 0, paramBytes.Length)
reqStream.Close()
End If
' get response
Try
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
Return New StreamReader(response.GetResponseStream()).ReadToEnd()
Catch ex As WebException
Dim response As HttpWebResponse = DirectCast(ex.Response, HttpWebResponse)
Throw New Exception((uri & " caused a " & CInt(response.StatusCode) & " error." & vbLf) + response.StatusDescription)
End Try
End Function
End Class
C#
using System;
using System.Text;
using System.Net;
using System.Windows.Forms;
using System.IO;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string response;
response = GetResponse(“https://app.asana.com/api/1.0/users/me”);
}
I am idiot! And/or you have younger eyes than I!
Yes, that is it. They are both working now.
Can I just ask, because it was a long road to this perhaps simple, obvious code - why was it so hard to find this? I was trying code with client id’s and secrets and none of it was needed and didn’t work. This person’s VB.NET code was the only comprehensive example that I could run successfully.
These are different methods of authentication. In your code use are using what is called Basic Auth. The downside of this method is that you need to hard code (or provide) login + password inside your code. It means, that if your code is going to be stolen by someone, they will have a full access to your account.
Another method is oAuth : you don’t need login and password (and you don’t send them via open protocols as in Basic Auth and e.g. main-in-the-middle attack cannot be done to reveal your credentials). You just have a temporary token (together with secret to be able to verify that this is the correct client) which allows you to access only to resources that this token is authorized for. It means, that this method is much more secure and now widely used.
In addition, using oAuth you can authenticate your user with popular services (as Google, Facebook, Twitter, …) without the need of creating your own authentication mechanism.
Excuse me for being naive, where in my code is there a login and password? Is it because I am running the application that the external app I am running can access asana as I’ve supplied id/pw separately? Or did you mean the PAT isn’t safe to hardcode and send along?
Of course I want my application to be as safe as possible. What else would the posted code need to use oAuth?
OAuth-based authentication is a more complex process than what you’re using now which presumably is using a Personal Access Token - but OAuth is the more desirable approach if you’re building a solution that you plan to have other people use (as opposed to something just for you, in which case the PAT approach is fine).
OAuth is most typically done via a web server but can be done in a Windows desktop application. I’d recommend googling “OAuth Windows desktop application” and you’ll find lots of resources. For example, here are some code samples you might find helpful.
I am going to open a new thread to continue this. My plan was that I was always going to get back to this, I just wanted to have some fun using the API first since I was so happy to be connected! So I am displaying asana stories in my application. I have a command button to add a note. When a user tested this, her note was attributed to me! I guess now is the time I have to work more on authentication, so I don’t have the entire Customer Service department adding new notes authored by me. LOL!