Invalid grant in OAuth2 in GAE java appp - java

Hi i am trying to create a GAE/J app in which i have to retrieve access token from a given code
so here is my code for /oauth2callback servlet
public class OAuth2Callback extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String url = "https://accounts.google.com/o/oauth2/token";
// FetchOptions opt = FetchOptions.Builder.doNotValidateCertificate();
URL url1=new URL(url);
String param="grant_type=authorization_code&code="+req.getParameter("code")+"&client_id=anonymouns&client_secret=anonymous&redirect_uri=https://www.cloudspokestest.appspot.com/oauth2callback";
HttpURLConnection connection =
(HttpURLConnection)url1.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.getOutputStream().write( param.getBytes() );
InputStream str= connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(str));
String l="";
while((l=reader.readLine())!=null){
resp.getWriter().println(l);
}
}
}
but on the browser screen i am getting error invalid grant with response code 400.can any one please help how to remove this error.

You're getting this error most likely because the parameter values in your url are not url-encoded. The value of the redirect_uri, and possibly the value of code must be url-encoded.
You could use java.net.URLEncoder to encode the values.
Also never use getBytes() on a String, as it uses your platform's default character encoding to convert characters to bytes. Running the same code on another machine, or changing your machines configuration might give different output. Always use getBytes(charsetname) instead.

Related

Servlet equivalent in Python?

On client side , following android code would make the call to the local server :
String link = "http://localhost:8080/test/cgi-bin/test.py";
URL url = null;
try {
url = new URL(link);
HttpURLConnection client = (HttpURLConnection) url.openConnection();
JSONObject jo = new JSONObject();
jo.put("desc","xyz");
String data2 = jo.toString();
client.setRequestMethod("Post");
// client.setRequestProperty("key","value");
client.setDoOutput(true);
OutputStreamWriter outputPost = new OutputStreamWriter(client.getOutputStream());
outputPost.write(data2);
outputPost.flush();
outputPost.close();
Earlier I was using servlets to interact with DB as the code below :
Using HttpServlet class , i could get the request and its parameters :
public class ServletXYZ extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getParameter("method");
Is there any way in python which allows me to do the same (getting parameter values from request) ?
Thanks.
I've used CherryPy as a general purpose HTTP server framework. Ultimately to do the same as the servlet, there are many links - this one seems to be pretty much what you want.

Unable to authenticate with Google Tasks - Homework

This week I had a small program to develop, I needed to create a Web Application(using a Java Servlet on localhost), this Web App is required to do the following:
Obtain and show issues from public organizations from GitHub
Obtain authentication thru OpenID Connect(OAuth 2.0)
Create a Google Task on the default tasklist from an issue using REST
Note: I can only use HTTP, no jar libs
The first part was easy, just had to make the request to the GitHub API and parse the JSON, no problem here
The second part was somewhat easy, I had to create a new Client ID in Google Developer Console, where I'd set the callback and receive the code on it, I'll put it here just in case I'm doing something wrong with it:
Login.java
...
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("--New login request was received --");
resp.setStatus(302);
resp.setHeader("Location", GoogleStuff.AUTH_LINK);
}
...
callback.java
...
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Cookie c = new Cookie("googleCode", req.getParameter("code")); c.setMaxAge(60*60); //1 Hour
//Example code received from Google
//4/6POIUYwZA3tFCnX_2feRDGiPMQOU7At8HyfOzemMkOY.wtiPpsElo8wZoiIBeR5Q2m9sqEaFkwI
resp.addCookie(c);
resp.setStatus(302);
resp.setHeader("Location","searchOrg");
}
...
My problem comes on the third part, I get the response code 401(Not Authorized) from Google, I'm sure I'm doing something wrong, but I don't really know what is wrong. This is probably all wrong, so bear with it :p
Note: To get the API Key I used the Google Developer Console and created a key for Browsers
GoogleStuff.java
...
public static String AUTH_LINK = "https://accounts.google.com/o/oauth2/auth?"+
"scope=https://www.googleapis.com/auth/tasks&"+
"redirect_uri=http://localhost:5005/callback&"+
"response_type=code&" +
"client_id=" + FirstHttpServer.CLIENT_ID +
"&approval_prompt=force";
...
public static void addTask(Issue i, String googleCode){
try {
String postURL = "https://www.googleapis.com/tasks/v1/lists/%40default/tasks?key=" + MyServer.API_KEY;
URL url = new URL(postURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", googleCode);
BufferedWriter httpRequestBodyWriter = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
httpRequestBodyWriter.write(i.toJson());
httpRequestBodyWriter.close();
Scanner httpResponseScanner = new Scanner(connection.getInputStream());
while(httpResponseScanner.hasNextLine())
System.out.println(httpResponseScanner.nextLine());
httpResponseScanner.close();
} catch (IOException e) {
System.out.println(e.toString());
throw new RuntimeException();
}
I've been at it for a couple days, but with other projects also tightening my time, its becoming increasingly hard for me to find the problem with this, which is why I request your help :)
Thanks in advance
An API will indicate that an access token has expired when it returns a 401 status code.To obtain a new access token, make a request to the token endpoint and include the client_id, client_secret, refresh_token, and grant_type parameters.
You can find more information in this link.
Hope that helps!

Send and receive JSON to REST WebService in Jersey Java

I am new to Jersey Java REST WebService framework. I am trying to write a service method which consumes and produces JSON. My service code is below. It is simplest code, just for studying purpose.
#Path("/myresource")
public class MyResource {
#Path("/sendReceiveJson")
#GET
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String sendReceiveJson(String name)
{
System.out.println("Value in name: " + name);
return "{\"serviceName\": \"Mr.Server\"}";
}
}
And following is JerseyClient code.
public class Program {
public static void main(String[] args) throws Exception{
String urlString="http://localhost:8080/MyWebService/webresources/myresource/sendReceiveJson";
URL url=new URL(urlString);
URLConnection connection=url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("{\"clientName\": \"Mr.Client\"}");
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println(decodedString);
}
in.close();
}
}
But when i run service and then client, i am unable to send/receive JSON data. I get Exception at connection.getInputStream() which is
Server returned HTTP response code: 405 for URL: http://localhost:8080/hellointernet/webresources/myresource/sendReceiveJson
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1625)
Please guide me, what needs to correct, or whether i am in wrong direction.
Your resource method is annotated as #GET which means any input data would have to be query string parameters.
In this context #Consumes(MediaType.APPLICATION_JSON) doesn't make a lot of sense as only APPLICATION_FORM_URLENCODED is supported via GET.
When you client calls setDoOutput(true) it probably switches your HTTP call to a POST hence causing the 405 Method Not Allowed.
If you want to consume JSON you should change your #GET annotation with #POST instead. Your client call should then work if it's indeed a POST. You can specify it with the following method:
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
This API is pretty low level though, so I'd highly recommend you use Jersey's Client API instead. See https://jersey.java.net/documentation/1.17/client-api.html

Unit testing Web API consumer module

My code is the consumer of an API (www.abc.com/public/news/apple.json). I get a json array in return which I then parse and populate in my own data structure. the code responsible for doing this is:
public Map<String,List<NewsItem>> populateNewsArray() throws Exception
{
url = domain + newsApiStr;
InputStream stream = getNews(url, true);
//jackson library object mapper
ObjectMapper mapper = new ObjectMapper();
//NewsApiObject class implements the structure of the json array returned.
List<NewsApiObject> mappedData = mapper.readValue(stream, NewsApiObject.class));
//populate the properties in a HashMap.
//return HashMap
}
public InputStream getNews(String request, boolean bulk) throws Exception
{
URL url = new URL(request);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "text/plain");
connection.setRequestProperty("charset", "utf-8");
connection.connect();
return connection.getInputStream();
}
As you can see I am not the controller of the api, only the consumer. It is said that in unit tests, one is not suppose to make http requests. In this scenario, how can I unit test the populateNewsArray() function to see if the object mapping was correct (without any exceptions) and a valid hashmap was returned?
You should extract getNews() into a separate interface, e.g. NewsReader (although the word Reader has a specific meaning in the JDK, I like the name...)
public interface NewsReader {
InputStream getNews(String request, boolean bulk) throws Exception
}
Then implement that interface with using HttpURLConnection as per your code and update your code to allow injection of that particular interface. Then, if you need to test how your code handles an InputStream, you can create a mock of NewsReader which returns a InputStream with well-known content.
Remember to aim for high cohesion: your class shouldn't be an HTTP client and a stream parser.
I would create a subclass and overwrite the method getNews(...). In the subclass you then may return an InputStream for your test.
Since you should not depenend on some external file in a unit test and in order to get a better testable design I'd also change the getNews(...) method to return some kind of value which can be further processed by the mapper.

Converting from java to c++, what is the equivalent curl command for setRequestProperty

I'm trying to convert a Java application to C++, I am using cURL for my requests.
Below is the java code; I'm wondering how to replicate the connection.setRequestProperty() method.
connection = (HttpURLConnection) url.openConnection();
connection.setInstanceFollowRedirects(false);
connection.setReadTimeout(10000);
String userId= =getUserId()
connection.setRequestProperty("UserID", userId);
Below is my current code that does not work.
struct curl_slist *headers=NULL;
curl_slist_append(headers, "UserID="2");
curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
curl_easy_setopt(curl, CURLOPT_URL,url.c_str());
curl_easy_setopt(curl,CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
curl_easy_setopt(curl, CURLOPT_CAINFO, certDataPath.c_str());
CURLcode c =curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, postRequestCallback);
Below is a the java servlet code that is failing (id is null or empty)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
...
...
String ud = request.getHeader("UserID");
}
What is the equiv command to setRequestProperty in cURL.
I'm sure I am missing something obvious.
Might be your header string format is off, how about:
curl_slist_append(headers, "UserID: 2");
ah, you need to assign the result, so
headers = curl_slist_append(headers, "UserID: 2");

Categories