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

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.

Related

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

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

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!"))

No Session handle to Renew Token in Xero-Partner-App

Error from Xero :
Token does not match an expected REQUEST token
The issue seems to be related to the comment from the Xero help site?
This error will also occur if the session handle is not used in the
access token renewal process.
I have confirmed I do not get this on the return object of the following :
public async Task<AccessTokenDto> Authorise(string oauth_token, string oauth_verifier, string org)
{
var xeroacessToken =
_authenticator.RetrieveAndStoreAccessToken(_user.Name,
oauth_token, oauth_verifier, org);
}
I am not sure how I get the session handle and then how to use this in my service call to renew the token? As per the example I was expecting this on my token.
oauth_session_handle=ODJHMGEZNGVKMGM1NDA1NZG3ZWIWNJ
"Session Handle used to renew the access token"
Code that works the first time with the token that has been retrieved from the database:
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
var api = new RA.Xero.Partner.Core(tokenStore, XeroUser(UserId)), _hostingEnvironment)
{
UserAgent = "My Partner App " + input.ConsumerKey,
};
I tried to see if using the Partner Authentication directly would work :
var tokenStore = new MemoryTokenStore();
tokenStore.Add(xerotoken);
Settings ApplicationSettings = new Settings();
X509Certificate2 certificate = RA.Xero.Partner.Core.Certificate(_hostingEnvironment);
var partnerAuthentication = new RA.Xero.Public.PartnerAuthenticator(
ApplicationSettings.Uri,
ApplicationSettings.AuthorizeUri,
ApplicationSettings.CallBackUri,
tokenStore,
certificate
);
var consumer = new Consumer(ApplicationSettings.Key,
ApplicationSettings.Secret);
var token = partnerAuthentication.GetToken(consumer,
XeroUser(UserId));
I have checked the keys are the partner keys in my app and any hints or sample code would be great.

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.

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.