Use RestSharp to get MS Graph token - vb.net

I am new to using MS Graph and the new version of RestSharp. I put together a simple console app in VB.NET to learn the process. Have spent way too much time looking at solutions on the internet, but not getting the answers I want. The ultimate goal is to upload files to a OneDrive account autonomously.
So I created an App registration on Azure for this app. Then to test I created a console app to test how the process works. I am using the latest version of RestSharp which is very different from the version I was using. The console app calls a simple subroutine shown below to get the token to make calls to Graph. When I run I get the errors: "System.Net.ProtocolViolationException' in System.dll" and "System.Net.ProtocolViolationException' in mscorlib.dll". Code follows:
Dim client As New RestClient("https://login.microsoftonline.com/f8cde-----/oauth2/v2.0/token")
Dim request As New RestRequest(Method.Post)
request.AddHeader("Content-Type", "application/x-www-form-urlencoded")
request.AddHeader("Host", "login.microsoftonline.com")
Dim body As String = "client_id=8e4---------" &
"scope=api://8e4da056-8425-4-.default" &
"client_secret=Piy7Q~7----------" &
"grant_type=client_credentials"
request.AddBody(body)
Dim response As RestSharp.RestResponse = Await client.ExecuteAsync(request)
Console.Write(response.Content.ToString)
Console.ReadKey()
End Sub
I admit I really don't know what I am doing here, but want to learn.

I can suggest spending time reading the documentation. RestSharp forms the request correctly if you use the RestRequest API to build the request.
Here is what you need to do:
Dim options = New RestClientOptions("https://login.microsoftonline.com/f8cde-----/oauth2/v2.0/token")
options.BaseHost = "login.microsoftonline.com"
Dim client = New RestClient(options)
Dim request As New RestRequest(Method.Post)
request.AddParameter("client_id", "8e4---------")
request.AddParameter("client_secret", "Piy7Q~7----------")
request.AddParameter("grant_type", "client_credentials")
Dim response = Await client.ExecuteAsync(request)

Related

RestSharp RestClient.Execute errors Bad Gateway - but works if I step through the code

Background
an existing VB.NET application has been working for 5+ years, recently started to error when POST data to an API
Async Function Post(body, path) As Task(Of RestResponse)
Dim request = New RestRequest(path, Method.Post)
request.AddJsonBody(body, "application/json")
Dim client As RestClient = New RestClient(psURL)
client.UseNewtonsoftJson()
Dim response As RestResponse = Await client.PostAsync(request)
PostREST = response
End Function
When I debug the application, and add a breakpoint on the
Dim response As RestResponse = client.Execute(request) line, then it works as expected.
Note: I've upgraded to v108.0.1.0 and getting the same error

HTTP Post to Onedrive RestAPI

I'm trying to use C# for connecting to Onedrive Rest API platform, The URL that I need to connect is:
"asdfasdfLJLKJLKJK"
and the code I'm trying to run is as below:
using System.Net.Http;
using (var client = new HttpClient())
{
var content_new = new FormUrlEncodedContent(new[]{ new KeyValuePair<string, string>("access_token", "asdKJHKJH")});
var content = new FormUrlEncodedContent(values);
client.BaseAddress = new Uri("https://api.onedrive.com/v1.0");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response_web = await client.PostAsync("/drive", content_new);
var responseString = await response_web.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Console.ReadLine();}
But for some odd reason it fails, also would like to know if I can read the data that PostAsync sends to the server? I mean the request URL as that might help troubleshooting too.
Looking at your request you are performing a POST operation on a drive, the OneDrive API does not support that action on the drive node.
If you are looking to create a new folder or upload a file, you'll want to perform that operation on https://api.onedrive.com/drive/root or where ever you'd like the operation to happen in the user's account.
To look up all of the supported actions and example requests see the OneDrive API resource model.

Why Does my Service Account Attempt to Connect to Google API via OAuth2 Return an 'invalid_grant' error?

I am attempting to use a Service Account to talk to the Admin SDK Directory API via the .Net Client Library. However, the response I keep getting is a 400 Bad Request with a json response content of "error":"invalid_grant".
Here is my code
Public Sub New()
Dim _certificate = New X509Certificate2("c:\path\to\file.psk", "notasecret" _
, X509KeyStorageFlags.Exportable)
Dim _serviceAccountEmail = "email#developer.gserviceaccount.com"
Dim _scopes As IList(Of String) = New List(Of String)()
_scopes.Add(directory_v1.DirectoryService.Scope.AdminDirectoryUserReadonly)
Dim credential = New ServiceAccountCredential(New
ServiceAccountCredential.Initializer(_serviceAccountEmail) With {
.Scopes = _scopes}.FromCertificate(_certificate))
Dim service = New directory_v1.DirectoryService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = credential,
.ApplicationName = "AeriesConnect"})
Dim request = service.Users.List()
request.Domain = "my.domain.com"
Dim users As directory_v1.Data.Users = request.Execute()
For Each user In users.UsersValue
System.Diagnostics.Debug.WriteLine("userName ID: " & user.Id)
Next
End Sub
Service Object
My service object has the following properties. All other properties are empty collections of the UsersResource or GroupsResource
service.BaseUri = 'https://www.googleapis.com/admin/directory/v1"
service.HttpClientInitializer Properties
Notice that the Token property is empty. Does that matter? It seems like it does. Is that my fault?
Request Object
I get the error right at the Execute and the exception is from Google and is a Google.Apis.Auth.OAuth2.Responses.TokenResponseException.
I think I've granted all the permissions I need to BUT keep in mind, this is for a Google Apps for Education account.
Logging in as a Super User to the Developer Console, I've created a project and enabled the Admin SDK API. I've also created the Credentials.
As a 'Super User' in that GAFE, I've gone to the "Security --> Advanced Settings --> Manage API Client Access" area and added my Client ID (not email) and the scope as https://www.googleapis.com/auth/admin.directory.user
Request Header
My request header that is POST to https://accounts.google.com/o/oauth2/token has this
assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6Imh0dHBzOi8vd3d3L
mdvb2dsZWFwaXMuY29tL2F1dGgvYWRtaW4uZGlyZWN0b3J5LnVzZXIiLCJpc3MiOiI2OTY3MTQyNzg2OS1hb
XFmMjVzY204Y2N1azhycHJrMDQ2djAzb2cybGducEBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSAiLC
JhdWQiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvdG9rZW4iLCJleHAiOjE0MTQ2MTY
3NDMsImlhdCI6MTQxNDYxMzE0M30.T9H-3tgOQSNdSj3MrUjJNNR5YqsxuJ97bCMJrrEJQ1Noewyv2mj
Dp96AZSZmzSxseAWrgptUv7sR4Mi21CWNACmjQjWPw8BI48sAyIclUPq6UhtMhRZDB1xX7t-Tq8NSbddJt
yJWxTc-IEAT7ixVpjjrosdG8Zcs0MgTuUgKHb8
&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
...and the last bits of it feel wrong. Why does it feel like it suddenly has been HTML encoded?
Question
What have I done wrong? I'm assuming it think's I'm not authenticated. But what do I need to do differently? I've used their examples to help, but I can't quite figure it out.
My problem was that I had the wrong value in the Service Account Email field. Simple solution. Took me two days to figure it out. Ugh!

Getting Error 400 when using Authentication Broker in Win 8 App for Stackexchange API

I'm trying to connect to StackExchange API using OAuth.
So far i've been able to get a token and retrive data that does not require authentication.
When i try do query that uses the authentication, i'm getting error 400 - Bad request.
Heres the code:
Dim Key As String = "(app_key)"
Dim RequestURL As String = "https://api.stackexchange.com/2.2/me/questions?access_token=" & Token & "key=" & Key & "&order=desc&sort=activity&site=stackapps"
Dim Handler As HttpClientHandler = New HttpClientHandler()
If Handler.SupportsAutomaticDecompression Then
Handler.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate
End If
Dim HttpClient As HttpClient = New HttpClient(Handler)
Dim query = Await HttpClient.GetAsync(RequestURL)
If query.IsSuccessStatusCode = True Then
'(query.Content.ReadAsStringAsync())
End If
Tried using only key, only access token, or none in the request, but received the same error. Also tried adding "OAuth" header and "access_token":
HttpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("OAuth", Token)
HttpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("access_token", Token)
Any help appreciated.
Solved it! Turns out a was using the wrong key. I managed to make it work by using both access_token and key in the RequestUrl, not using the request headers.

Reporting Services Authentication issue

I am trying to programmatically render a PDF using Azure Reporting Services. I suspect that the actual PDF retrieval is fine, but I cannot find a way to authenticate the connection before requesting the report (via URL). I am working in the services layer of my web application and I cannot use a web reference (might not work with Azure) and it doesn't make sense to use a ReportViewer control (since it's a service layer method).
I have all the details to connect, but I suspect that I require a cookie to authenticate and I'm not sure how to manually create this. Any suggestions/solutions?
Here's my code so far:
string userName = BJConfigurationManager.GetSetting("ReportingServiceUsername");
string password = BJConfigurationManager.GetSetting("ReportingServicePassword");
NetworkCredential networkCredential = new NetworkCredential(userName, password);
Domain.Report report = GetReportById(id);
int timeout = 30; //seconds
string url = "https://bleh.ctp.reporting.database.windows.net/ReportServer/Pages/ReportViewer.aspx?...";
string destinationFileName = "#C:\\Temp.pdf";
// Create a web request to the URL
HttpWebRequest MyRequest = (HttpWebRequest)WebRequest.Create(url);
MyRequest.PreAuthenticate = true;
MyRequest.Credentials = networkCredential;
MyRequest.Timeout = timeout * 1000;
try
{
// Get the web response -- THE RESPONSE COMES BACK AS UNAUTHENTICATED...
HttpWebResponse MyResponse = (HttpWebResponse)MyRequest.GetResponse();
Check out the section titled "SOAP Management Endpoint Programmatic Access":
http://msdn.microsoft.com/en-us/library/windowsazure/771e88b6-ab0f-4910-a5fa-5facd8d56767#SOAPManagement.
It explains how to authenticate using a cookie container without a ReportViewer control.
I don't think that is going to work. Azure Reporting uses Forms Authentication and as I understand it, you aren't going to be able to match the Forms Auth cookie along with the MachineKey for encryption.
I was trying to accomplish the same task..but using a WebRequest was impossible.
I changed the approach using a ServerReport class like this:
ServerReport report;
report = new ServerReport();
report.ReportServerUrl = new Uri(reportServerName + "/ReportServer");
report.ReportPath = "/ReportPath";
report.ReportServerCredentials = new ReportServerCredentials();
report.SetParameters(new Microsoft.Reporting.WebForms.ReportParameter("param1", param1));
report.SetParameters(new Microsoft.Reporting.WebForms.ReportParameter("param2", param1));
return report.Render(reportParams.OutputFormat);
The ReportServerCredentials class must implement the IReportServerCredentials interface like this.
More info about the IReportServerCredentials interface and implementation here.