Google OAuth 2.0 Access Token Request Error - java

I have a small Google App Engine project on GitHub what I "finished" several months ago.
It worked until now (Last use was 2-3 months ago), but it seems the Google changed something and I don't find what the real problem is and how I can solve it.
The problem is in this file (line 59):
File
Code:
public class TokenManager {
static private final String TOKEN_URL = "https://www.googleapis.com/oauth2/v3/token";
static private final String ENC = "UTF-8";
private String _refreshToken;
private String _clientId;
private String _clientSecret;
private final Gson _gson = new Gson();
private TokenData _tokenData = new TokenData();
...
private void refreshAccessToken() throws Exception {
String payload = "client_secret=$client_secret&grant_type=refresh_token&refresh_token=$refresh_token&client_id=$client_id";
payload = payload.replace("$client_secret", URLEncoder.encode(_clientSecret, ENC));
payload = payload.replace("$refresh_token", URLEncoder.encode(_refreshToken, ENC));
payload = payload.replace("$client_id", URLEncoder.encode(_clientId, ENC));
HTTPRequest request = new HTTPRequest(new URL(TOKEN_URL), HTTPMethod.POST);
request.setPayload(payload.getBytes(ENC));
String stringData = new String(URLFetchServiceFactory.getURLFetchService().fetch(request).getContent(), ENC);
_tokenData = _gson.fromJson(stringData, TokenData.class);
}
}
The problem is around the access token request. (I use offline refresh token.)
The response is this:
{
"error": "invalid_grant",
"error_description": "Bad Request",
"error_uri": ""
}
I have tried to modify the TOKEN_URL to "https://www.googleapis.com/oauth2/v4/token"
I have tried to generate new refresh token.
I have tried create new OAuth Client ID.
All attempts had same problem.
Have anyone any idea what is wrong?
Thanks for help!

I found the problem.
Probably my previous refresh token was expired. I tried to generating
a new but I misunderstood the process and I considered "code"
parameter as refresh token.
https://developers.google.com/identity/protocols/OAuth2WebServer#offline

Related

Telegram API methods - 404 error | java

Created a bot and group. Added bot to the group(as admin) and starting trying posts. Through Url, it's smooth and successful. Started off exploring Telegram API(JAVA). Tests were on getUpdate and sendMessage methods.
I have generated TOKEN from telegram webapp(https://web.telegram.org).
Code snippet to getUpdates: yes, I have included bot ahead of the token.
TelegramBot bot = new TelegramBot("BOT_TOKEN");
GetUpdates getUpdates = new GetUpdates().limit(100).offset(0).timeout(0);
GetUpdatesResponse gur = bot.execute(getUpdates);
List<Update> list = gur.updates();
for(Update update : list) {
System.out.println(update.message());
}
Resonse is null.
code for sendMessage:
SendMessage request = new SendMessage(chatId, text)
.parseMode(ParseMode.HTML)
.disableWebPagePreview(true)
.disableNotification(true)
.replyToMessageId(1)
.replyMarkup(new ForceReply());
// sync
SendResponse sendResponse = bot.execute(request);
boolean ok = sendResponse.isOk();
Message message = sendResponse.message();
System.out.println(ok);
System.out.println(message);
Response is false and null.
I'm referring https://github.com/pengrad/java-telegram-bot-api#send-message
Help me understand the mistake. Thanks.
You need 109780439:AAJqs_w-4 format token, for instance:
TelegramBot bot = new TelegramBot("109780439:AAJqs_w-4");
This token can be obtained from #BotFather.

How do I send nested json POST request in java using jersey?

I am using a document converter api called cloudconvert. They don't have an official java library, but a third party java option. I needed a little customization so I cloned the github project and added it to my project. I am sending cloudconvert a .epub file and getting a .pdf file in return. If I use the default settings it works without issue and properly converts my .epub to a .pdf. Here is the code that makes it happen.
Here is what triggers the conversion:
// Create service object
CloudConvertService service = new CloudConvertService("api-key");
// Create conversion process
ConvertProcess process = service.startProcess(convertFrom, convertTo);
// Perform conversion
//convertFromFile is a File object with a .epub extension
process.startConversion(convertFromFile);
// Wait for result
ProcessStatus status;
waitLoop:
while (true) {
status = process.getStatus();
switch (status.step) {
case FINISHED:
break waitLoop;
case ERROR:
throw new RuntimeException(status.message);
}
// Be gentle
Thread.sleep(200);
}
//Download result
service.download(status.output.url, convertToFile);
//lean up
process.delete();
startConversion() calls:
public void startConversion(File file) throws ParseException, FileNotFoundException, IOException {
if (!file.exists()) {
throw new FileNotFoundException("File not found: " + file);
}
startConversion(new FileDataBodyPart("file", file));
}
Which calls this to actually send the POST request using jersey:
private void startConversion(BodyPart bodyPart) {
if (args == null) {
throw new IllegalStateException("No conversion arguments set.");
}
MultiPart multipart = new FormDataMultiPart()
.field("input", "upload")
.field("outputformat", args.outputformat)
.bodyPart(bodyPart);
//root is a class level WebTarget object
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
Up to this point everything is working. My problem is that the when the conversion happens the .pdf that returns has very small margins. cloudconvert provides a way to change those margins. You can send in an optional json param converteroptions and set the margins manually. I have tested this out using postman and it works without issue, I was able to get a properly formatted margin document. So know this is possible. Here is the POSTMAN info I used:
#POST : https://host123d1qo.cloudconvert.com/process/WDK9Yq0z1xso6ETgvpVQ
Headers: 'Content-Type' : 'application/json'
Body:
{
"input": "base64",
"file": "0AwAAIhMAAAAA", //base64 file string that is much longer than this
"outputformat": "pdf",
"converteroptions": {
"margin_bottom": 75,
"margin_top": 75,
"margin_right": 50,
"margin_left": 50
}
}
Here are my attempts at getting the POST request formatted properly, I'm just not very experienced with jersey and the couple of answers I did find on stackoverflow didn't work for me.
Attempt 1, I tried adding the json string as a Multipart.field. It didn't give me any errors and still returned a converted .pdf file, but the margins didn't get changed so I must not be sending it back right.
private void startConversion(BodyPart bodyPart) {
String jsonString = "{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}";
MultiPart multipart = new FormDataMultiPart()
.field("input", "upload")
.field("outputformat", args.outputformat)
.field("converteroptions", jsonString)
.bodyPart(bodyPart);
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
Attempt 2, when I had it working in POSTMAN it was using the 'input' type as 'base64' so I tried changing it to that but it this time it doesn't return anything at all, no request errors, just a timeout error at the 5 minute mark.
//I pass in a File object rather than the bodypart object.
private void startConversion(File file) {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
String jsonString = "{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}";
MultiPart multipart = new FormDataMultiPart()
.field("input", "base64")
.field("outputformat", args.outputformat)
.field("file", encoded64)
.field("converteroptions", jsonString);
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
Attempt 3, after some googling on how to properly send jersey json post requests I changed the format. This time it returned a 400 bad request error.
private void startConversionPDF(File file) throws IOException {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
String jsonString = "{\"input\":\"base64\",\"file\":\"" + encoded64 + "\",\"outputformat\":\"pdf\",\"converteroptions\":{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}}";
root.request(MediaType.APPLICATION_JSON).post(Entity.json(jsonString));
}
Attempt 4, Someone said you don't need to manually use a jsonString you should use serializable java beans. So I created the corresponding classes and made the request like shown below. Same 400 bad request error.
#XmlRootElement
public class PDFConvert implements Serializable {
private String input;
private String file;
private String outputformat;
private ConverterOptions converteroptions;
//with the a default constructor and getters/setters for all
}
#XmlRootElement
public class ConverterOptions implements Serializable {
private int margin_bottom;
private int margin_top;
private int margin_left;
private int margin_right;
//with the a default constructor and getters/setters for all
}
private void startConversionPDF(File file) throws IOException {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
PDFConvert data = new PDFConvert();
data.setInput("base64");
data.setFile(encoded64);
data.setOutputformat("pdf");
ConverterOptions converteroptions = new ConverterOptions();
converteroptions.setMargin_top(75);
converteroptions.setMargin_bottom(75);
converteroptions.setMargin_left(50);
converteroptions.setMargin_right(50);
data.setConverteroptions(converteroptions);
root.request(MediaType.APPLICATION_JSON).post(Entity.json(data));
}
I know this is quite the wall of text, but I wanted to show all the different things I tried so that I wouldn't waste anyone's time. Thank you for any help or ideas you might have to make this work. I really want to make it work with jersey because I have several other conversions I do that work perfectly, they just don't need any converteroptions. Also I know its possible because it works when manually running the process through POSTMAN.
Cloudconvert api documentation for starting a conversion
Github repo with the recommended 3rd party java library I am using/modifying
I finally figured it out. Hours of trial and error. Here is the code that did it:
private void startConversionPDF(File file) throws IOException {
if (args == null) {
throw new IllegalStateException("No conversion arguments set.");
}
PDFConvert data = new PDFConvert();
data.setInput("upload");
data.setOutputformat("pdf");
ConverterOptions converteroptions = new ConverterOptions();
converteroptions.setMargin_top(60);
converteroptions.setMargin_bottom(60);
converteroptions.setMargin_left(30);
converteroptions.setMargin_right(30);
data.setConverteroptions(converteroptions);
MultiPart multipart = new FormDataMultiPart()
.bodyPart(new FormDataBodyPart("json", data, MediaType.APPLICATION_JSON_TYPE))
.bodyPart(new FileDataBodyPart("file", file));
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}

Authy Authentication is throwing UnknownHostException

I'm trying to implement 2 phase authentication for my application using authy authentication.
While trying to verify the token generated in authy mobile app m getting UnknownHostException.
package tes.resource;
import com.authy.*;
import com.authy.api.*;
public class SampleAuthenticator {
AuthyApiClient client=null;
public void init(){
String apiKey = "API_KEY";
String apiUrl = "http://api.authy.com";
boolean debugMode = true;
client = new AuthyApiClient(apiKey, apiUrl, debugMode);
}
public void register(String userid,String phone){
Users user=client.getUsers();
user.createUser(userid,phone, "57");
}
public boolean verify(){
Tokens tokens = client.getTokens();
Token verification = tokens.verify(27319980, "7983610");
return verification.isOk();
}
public static void main(String[] args){
SampleAuthenticator objSampleAuthenticator=new SampleAuthenticator();
objSampleAuthenticator.init();
System.out.println(objSampleAuthenticator.verify());
}
}
I have created a application to test whether authy is verifying the user based on the random token generated in authy app.
Any help is appreciated.
Authy developer evangelist here.
First I would recommend you change your Authy API key, since you seem to have leaked it in this question.
Secondly, the Authy API URL requires HTTPS. My guess is that you need to change
String apiUrl = "http://api.authy.com";
to an HTTPS url:
String apiUrl = "https://api.authy.com";
Let me know if that helps.

YouTube API v3 Not Displaying Exceptions

I just started using YouTube API for Java and I'm having a tough time trying to figure out why things don't work since exception/stack trace is no where to be found. What I'm trying to do is to get list of videos uploaded by current user.
GoogleTokenResponse tokenFromExchange = new GoogleTokenResponse();
tokenFromExchange.setAccessToken(accessToken);
GoogleCredential credential = new GoogleCredential.Builder().setJsonFactory(JSON_FACTORY).setTransport(TRANSPORT).build();
credential.setFromTokenResponse(tokenFromExchange);
YouTube.Channels.List channelRequest = youtube.channels().list("contentDetails");
channelRequest.setMine(true);
channelRequest.setFields("items/contentDetails,nextPageToken,pageInfo");
ChannelListResponse channelResult = channelRequest.execute();
I don't see anything wrong with this code and also tried removing multiple things, but still not able to get it to work. Please let me know if you have run into a similar issue. The version of client library I'm using is v3-rev110-1.18.0-rc.
YouTube API has some working code and you can use it.
public static YouTubeService service;
public static String USER_FEED = "http://gdata.youtube.com/feeds/api/users/";
public static String CLIENT_ID = "...";
public static String DEVELOPER_KEY = "...";
public static int getVideoCountOf(String uploader) {
try {
service = new YouTubeService(CLIENT_ID, DEVELOPER_KEY);
String uploader = "UCK-H1e0S8jg-8qoqQ5N8jvw"; // sample user
String feedUrl = USER_FEED + uploader + "/uploads";
VideoFeed videoFeed = service.getFeed(new URL(feedUrl), VideoFeed.class);
return videoFeed.getTotalResults();
} catch (Exception ex) {
Logger.getLogger(YouTubeCore.class.getName()).log(Level.SEVERE, null, ex);
}
return 0;
}
This simple give you the number of videos a user has. You can read through videoFeed using printEntireVideoFeed prepared on their api page.

Render page to string in Wicket 1.5

I'm working on upgrading our existing Wicket webapp to 1.5 and have hit a snag in our renderPage function that we use to render our HTML emails.
Previously we used the code referenced/listed in this StackOverflow question and this (currently broken but maybe fixed later) link but that code no longer works as a lot of those classes don't exist in 1.5.
I also found this email thread but it is light on the details and I don't know how to create the WebPage from my pageClass and parameters.
http://apache-wicket.1842946.n4.nabble.com/Render-WebPage-to-String-in-Wicket-1-5-td3622130.html
Here is my code:
// Renders a page under a temporary request cycle in order to get the rendered markup
public static String renderPage(Class<? extends Page> pageClass, PageParameters pageParameters)
{
//get the servlet context
WebApplication application = (WebApplication) WebApplication.get();
ServletContext context = application.getServletContext();
//fake a request/response cycle
MockHttpSession servletSession = new MockHttpSession(context);
servletSession.setTemporary(true);
MockHttpServletRequest servletRequest = new MockHttpServletRequest(application, servletSession, context);
MockHttpServletResponse servletResponse = new MockHttpServletResponse(servletRequest);
//initialize request and response
servletRequest.initialize();
servletResponse.initialize();
WebRequest webRequest = new ServletWebRequest(servletRequest);
BufferedWebResponse webResponse = new BufferedWebResponse(servletResponse);
webResponse.setAjax(true);
WebRequestCycle requestCycle = new WebRequestCycle(application, webRequest, webResponse);
requestCycle.setRequestTarget(new BookmarkablePageRequestTarget(pageClass, pageParameters));
try
{
requestCycle.getProcessor().respond(requestCycle);
if (requestCycle.wasHandled() == false)
{
requestCycle.setRequestTarget(new WebErrorCodeResponseTarget(HttpServletResponse.SC_NOT_FOUND));
}
}
finally
{
requestCycle.detach();
requestCycle.getResponse().close();
}
return webResponse.toString();
}
Specifically, the code breaks because the WebRequestCycle and BookmarkablePageRequestTarget classes no longer exist. I feel like I should be able to use the StringResponse class some how but I'm missing the link that would help me trigger a render on that response.
Any help would be appreciated. Thanks.
My Final Solution
Using the example that I was directed to by the answer below I ended up with the following code. I'm pasting it here as well so that if that link disappears or is changed with a future version of Wicket then people from the future will still be able to get the answer they need.
I ended up passing in a PageProvider because in some cases I needed to pass in an instantiated Page and in others a pageClass + parameters.
public static String renderPage(final PageProvider pageProvider)
{
final RenderPageRequestHandler handler = new RenderPageRequestHandler(pageProvider, RedirectPolicy.NEVER_REDIRECT);
final PageRenderer pageRenderer = Application.get().getPageRendererProvider().get(handler);
RequestCycle requestCycle = RequestCycle.get();
final Response oldResponse = requestCycle.getResponse();
BufferedWebResponse tempResponse = new BufferedWebResponse(null);
try
{
requestCycle.setResponse(tempResponse);
pageRenderer.respond(requestCycle);
}
finally
{
requestCycle.setResponse(oldResponse);
}
return tempResponse.getText().toString();
}
Check the source code of http://www.wicket-library.com/wicket-examples/mailtemplate/ example.

Categories