Getting error for getting access token "HTTP method POST is not supported by this URL, StatusCode=405" - authentication

Getting issues for getting access token by using trigger and apex class. I am using "https://www.googleapis.com/auth/drive" as callback URL and endpoint of HTTP Request. My create folder method is working properly if valid access token is provided but I am not getting access token. But I am getting error "HTTP method POST is not supported by this URL, StatusCode=405"
Below is my code
public class GDriveFolderCreationClass {
private final String clientId ='3MVG98EE59.VIHmz7DO7_********************kb0NbJrDULh.q0CmS3TqSuItCtA6mxyxUaa_STYbpue';
private final String clientSecret = '8E70141F********************6307D13F5B72FD850ABA2C9A05124F3B7B9F';
private final String username = 'test#gmail.com';
public class deserializeResponse{
public String access_token;
}
public String ReturnAccessToken (GDriveFolderCreationClass acount){
deserializeResponse resp1= new deserializeResponse();
String reqbody = 'client_id='+clientId+'&client_secret='+clientSecret+'&username='+username;
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setBody(reqbody);
req.setMethod('POST');
req.setEndpoint('https://www.googleapis.com/auth/drive');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Accept','application/json');
HttpResponse res = h.send(req);
if(res.getstatusCode() == 200 && res.getbody() != null){
resp1 = (deserializeResponse)JSON.deserialize(res.getbody(),deserializeResponse.class);
}
return resp1.access_token;
}
#future(Callout=True)
public static void createFolderinDrive(String contentName){
GDriveFolderCreationClass account1 = new GDriveFolderCreationClass();
String accessToken;
accessToken = account1.ReturnAccessToken(account1);
createFolder();
}
//Working function for creating folder in google drive
public static void createFolder() {
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://www.googleapis.com/drive/v3/files');
req.setHeader('Authorization', 'Bearer '+accessToken);
req.setHeader('content-type', 'application/json');
String body = '{"name" : "'+'TestFolder'+'","mimeType" : "application/vnd.google-apps.folder"}';
req.setTimeout(60*1000);
req.setBody(body);
Http http = new Http();
HttpResponse res = http.send(req);
}
}
ConnectedAppSS
I have also used the AUTH provider and used callback URL as redirect URI but that also didn't worked. For that I am getting below error in debug log
error ss
Please help me to get access token for my fixed google account to create folder structure in my google drive. Let me know if you want any other details.
Thanks and regards

Firstly get the refresh token by using code authorization and then you can get access token by using refresh token.
Use "https://accounts.google.com/o/oauth2/token" as a endpoint to get access token again and again by using refresh token.

You are using https://www.googleapis.com/auth/drive as an endpoint to POST your request for a token. This URL does not return any authorization tokens.
See https://developers.google.com/identity/protocols/oauth2#2.-obtain-an-access-token-from-the-google-authorization-server.
The endpoint to get the auth tokens; which is easier to do using client libraries is: https://accounts.google.com/o/oauth2/v2/auth

Related

Using httpClient.postasync for web api calls .netcore

I am new to .netcore, I am working on web api that are running on docker container and while using postman the web api's are working really fine outputting the results. I want to make a program in .netcore calling the webapi endpoints and getting the response and using that particular response in other endpoints with MVC.
The explanation is given below.
The default username and password for admin is default set for example username:admin , password: helloworld
. The first time admin login the api requires a new personal password as shown in the Postman figure below.
The login api is: localhost://..../v1/users/login
The first question is How to give the values in Authorization->BasicAuth using .netcore.
The body of the api looks like the figure below.
After setting the new_password the response of the api is a token as given below.
The particular token is then use in the Environment to create user. The image for more clear problem is given below.
Lastly, the token then used to make other API calls such as creating a user.
API: https://localhost/..../v1/users
The image is below.
As a newbie in .netcore language, I am really struggling to do this kind of API calls, as most of the tutorials I tried are generating their own token from API, but here I just want to take the response token and save it and then use it in other API calls.
The StackOverflow community's support was always really handy for me.
The Code I'm trying is given below.
**Controller**
public class Login_AdminController : ControllerBase
{
[Route("/loginAdmin")]
[HttpPost]
public async Task<string> LoginAdminAsync([FromBody] dynamic content)
{
LoginAdmin L = new LoginAdmin();
var client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:9090");
var request = new HttpRequestMessage(HttpMethod.Post, "/v1/users/login");
var byteArray = new UTF8Encoding().GetBytes($"<{L.username}:{L.df_Password}>");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var formData = new List<KeyValuePair<string, string>>();
formData.Add(new KeyValuePair<string, string>("new_password", "helloWorld123!"));
request.Content = new FormUrlEncodedContent(formData);
var response = await client.SendAsync(request);
Console.WriteLine(response);
return content;
}
}
}
***Model***
public class LoginAdmin
{
public string username = "admin";
public string df_Password = "secret";
public string new_Password { get; set; }
}
Thank you.
Do you want to get token from response? If yes. Try this:
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:12345/Api");
var request = new HttpRequestMessage(HttpMethod.Post, "/token");
var keyValues = new List<KeyValuePair<string, string>>();
keyValues.Add(new KeyValuePair<string, string>("username", "yourusername"));
keyValues.Add(new KeyValuePair<string, string>("password", "yourpassword"));
request.Content = new FormUrlEncodedContent(keyValues);
var response = client.SendAsync(request).Result;
return response.Content.ReadAsStringAsync().Result;
Authorization is handled via the Authorization request header, which will include a token of some sort, prefixed by the scheme. What you're talking about here isn't really basic auth. With that, you literally pass the username and pass in the Authorization header with each request. What you're doing is just authenticating once to get an auth token, and then using that auth token to authorize further requests. In that scenario, you should really be posting the username and pass in the request body. Then, you'd do bearer auth with the token for the other requests, using the Authorization header. Still, to cover both bases:
Basic Auth
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
request.Headers.Add("Authorization", $"Basic {token}");
Bearer Auth
request.Headers.Add("Authorization", $"Bearer {token}");
// where `token` is what was returned from your auth endpoint
FWIW, List<KeyValuePair<string, string>> is just Dictionary<string, string>. It's better to use the real type. Then, you can just do formData.Add("new_password", "helloWorld123!") instead of formData.Add(new KeyValuePair<string, string>("new_password", "helloWorld123!"))

Call authorized Web API using WebClient

After hours of searching the internet I decided to ask you guys for a little help.
I've written an Web API with couple of simple get/post methods. I'm using Individual user accounts authentication method.
Using the HttpClient I've managed to successfully call every AUTHORIZED get and post method as well as the /token endpoint used for generating authorization token.
The problem is that I must call these methods inside .NET Framework 3.5 project. So I've tried using WebClient to do this because I read that the HttpClient is not supported in .NET Framework 3.5.
GetAPIToken() METHOD generates Bearer token and it works.
private static string GetAPIToken(string userName, string password, string apiBaseUri)
{
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var response = client.UploadString(apiBaseUri + "/Token", "POST", "grant_type=password&username=" + userName + "&password=" + password);
var jObject = JObject.Parse(response);
return jObject.GetValue("access_token").ToString();
}
}
This GET method works when I remove [Authorize] attribute from the Web API but I can't make it work when authorized.
//GET ODRAĐENI POSTUPCI
private static string GetOdradjeniPostupci(int Id, string token)
{
string apiBaseUri = "http://localhost:60511/";
string serviceUrl = apiBaseUri + "api/ZOdradjeniPostupci";
using (WebClient client = new WebClient())
{
client.Headers.Clear();
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", "Bearer " + token);
var response = client.DownloadString(serviceUrl + "/GetZOdradjeniPostupci?cZdrUst=" + Id.ToString());
return response;
}
}
I get error 401 unathorized no matter what I try. (Different combinations from the internet regarding Authorization header).
Hope you could give me any advice on how to solve this.
I would appreciate it a lot.
Thanks.

How to connect to Onedrive using MSAL?

I'm trying to connect to OneDrive using MSAL token but it's returning error="invalid_token", error_description="Auth error"
This is my code:
public static string[] Scopes = { "User.Read", "Files.Read", "Sites.Read.All" };
AuthenticationResult ar = await App.ClientApplication.AcquireTokenSilentAsync(Scopes);
WelcomeText.Text = $"Welcome {ar.User.Name}"; //Login OK here
//get data from API
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://api.onedrive.com/v1.0/drives");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ar.Token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
Anyone know what I'm doing wrong ?
The direct API endpoint (api.onedrive.com) doesn't support access tokens generated from MSAL, only tokens generated from MSA. If you are using MSAL, you should use the Microsoft Graph API (graph.microsoft.com) to access OneDrive files for both personal and business users.
You already got your answer long time back but I hope this link will be helpful for someone else in future.
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/onedrive

Asana Authorization error on Mono.NET framework

I'm trying to use the Asana restful API and I receive this error:
{"errors":[{"message":"Not Authorized"}]}
public static string GetProjects()
{
string url = "https://app.asana.com/api/1.0/projects/"; // Constants.BaseApiUrl + "projects";
var client = new RestClient(url);
System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
client.Authenticator = new HttpBasicAuthenticator(AsanaAPIKey.GetBase64(), "");
var req = new RestRequest(Method.GET);
RestResponse res =(RestResponse) client.Execute(req);
return res.Content;
}
public static bool CheckValidationResult(object sp,
X509Certificate cert,
X509Chain req,
System.Net.Security.SslPolicyErrors problem)
{
return true;
}
I've tried plain httpwebrequest/Httpwebresponse and it didn't work either so I tried the restsharp library and still the same problem.
Any ideas why this error is happening?
I don't know .NET but I see you're creating an HttpBasicAuthenticator and it looks like you're passing it a username/password pair. But you are passing it a base64-encoded version of the API key, which is wrong. The documentation on authentication states that when using an HTTP library you should pass the API key as the username, unchanged. You only need to manually base64-encode if you are constructing the full header manually.

Google+ api - Key from https://accounts.google.com/o/oauth2/token gives 401 errors

I'm having some trouble with Google+ API OAuth2 tokens.
Here is a simple program that gets an OAuth2 access token:
HttpClient httpclient = new HttpClient();
PostMethod postMethod = new PostMethod("https://accounts.google.com/o/oauth2/token");
NameValuePair[] data = {
new NameValuePair("client_id", "API KEY HERE"),
new NameValuePair("redirect_uri", "URL HERE"),
new NameValuePair("client_secret", "SECRET HERE"),
new NameValuePair("code", "CODE HERE"),
new NameValuePair("grant_type", "authorization_code")
};
postMethod.setRequestBody(data);
try {
int result = httpclient.executeMethod(postMethod);
assertEquals(result, 200);
System.out.println("Response body: ");
System.out.println(postMethod.getResponseBodyAsString());
} catch (IOException e) {
e.printStackTrace();
}
This successfully generates an OAuth2 token. Such as: ya29.AHES6ZTZgptKHyZ530MoYVDPaeXvjK5DWQzPqxoNNEL2C7gsQwGfmvfT8Q
Then I set up a simple test program that can test calling the /people API from that token:
#Test
public void testGoogleAPIAuthdRequest() throws Exception {
String feedUrl = "https://www.googleapis.com/plus/v1/people/me";
String apiKey = "MY API KEY";
String oauthCode = "OAUTH CODE FROM ABOVE";
String jsonStr = executeGoogleFeed(feedUrl, apiKey, oauthCode).getResponseBodyAsString("UTF-8");
}
public Response executeGoogleFeed(String feedURL, String apiKey, String oauthCode) throws Exception {
StringBuilder urlStr = new StringBuilder();
urlStr.append(feedURL);
urlStr.append("?key=");
urlStr.append(apiKey);
Map<String, String> hashMap = new HashMap<String, String>();
hashMap.put("Authorization", "Bearer " + oauthCode);
return HttpUtil.doHttpRequest(urlStr.toString(), MethodType.GET.toString(), null,
hashMap);
}
This gives me a 401 error. Permission denied.
When I go to https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=INSERT_ACCESS_TOKEN, the Token shows as valid.
Also, when I go to https://developers.google.com/+/api/latest/people/get and get the OAuth token from the OAuth2 sign-on feature... and I plug that OAuth token into my JUnit test... it works!
Anyone know why my call to https://accounts.google.com/o/oauth2/token cannot be used as the Bearer parameter in Google+'s api?
It sounds like the underlying problem is that you're not requesting the plus.me scope when you send the user to authenticate themselves and authorize your app. This is done in the step before what you've shown here, and is the component that returns the OAuth2 "code" that you're adding above. You may want to update your example to illustrate how you're getting the code and what scopes you're using to do this.
If you are setting the scope correctly, and you're using the code that is returned, it could be that you keep re-using the same code. The OAuth2 code returned from the first stage can only be used once, and must be used very quickly after it is issued. It is exchanged for an access_token which has a limited lifetime (which is what you're correctly trying to do), and a refresh_token which has an unlimited lifetime and is used to generate fresh access_tokens.
See https://developers.google.com/accounts/docs/OAuth2WebServer for full details about the multi-step process used to get, and then exchange, the OAuth2 code.