i am getting the same issue as described in this post
. we have used almost exactly the same code. i have tried both with Client ID and Email address of the google service account in below mehotd
setServiceAccountId(GOOGLE_SERVICE_CLIENT_EMAIL) OR
setServiceAccountId(GOOGLE_CLIENT_ID)
error changes with the change in a/c id. if i use client id, error is
400 Bad Request { "error" : "invalid_grant" }
and if i use service email id, error is
401 Unauthorized {
"code" : 401, "errors" : [ {
"domain" : "androidpublisher",
"message" : "This developer account does not own the application.",
"reason" : "developerDoesNotOwnApplication" } ], "message" : "This developer account does not own the application." }
any idea?
There appears to be some evidence that Google Play API does not currently work with Service Accounts (madness). There is another thread on the issue here. You can read about the Google Service Accounts here. You can read about authentication for Android Google Play API here.
Once you have done the dance on the Google API Console to get a refresh_token you can get an access token like this:
private String getAccessToken()
{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
try
{
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
nameValuePairs.add(new BasicNameValuePair("client_id", "YOUR_CLIENT_ID);
nameValuePairs.add(new BasicNameValuePair("client_secret", "YOUR_CLIENT_SECRET"));
nameValuePairs.add(new BasicNameValuePair("refresh_token", "YOUR_REFRESH_TOKEN"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
return json.getString("access_token");
}
catch (IOException e) { e.printStackTrace(); }
catch (JSONException e) { e.printStackTrace(); }
return null;
}
Related
Okay, here's the thing, my colleagues have registered our backend app to Firebase Console. I'm using code bellow to send any notification to the FCM and consequently to the end user on iOS, but I'm failing to do so!
#RequestMapping(value = "/admin/invoice/message", method = RequestMethod.GET)
#ResponseBody
public void getMessage() {
try {
org.springframework.core.io.Resource resource = new ClassPathResource("name_of_the_json_file_below.json");
InputStream dbAsStream = resource.getInputStream(); // when spring boot project running as a jar
FirebaseOptions options = new FirebaseOptions.Builder().setCredentials(GoogleCredentials.fromStream(dbAsStream))
.setDatabaseUrl("https://project_id_property.firebaseio.com").build();
#SuppressWarnings("unused")
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if (firebaseApps != null && !firebaseApps.isEmpty()) {
for (FirebaseApp app : firebaseApps) {
if (app.getName().equals(FirebaseApp.DEFAULT_APP_NAME)) {
firebaseApp = app;
}
}
} else {
firebaseApp = FirebaseApp.initializeApp(options);
}
Notification notification = new Notification("title", "body");
Message message = Message.builder().setNotification(notification).putData("title", "title").putData("body", "body")
.putData("type", "type").putData("sound", "default").putData("priority", "high").setToken("valid_push_token").build();
if (firebaseApp != null) System.out.println("aaa"); //aaa
String responseMessage = FirebaseMessaging.getInstance().send(message);
System.out.println(responseMessage); //this prints -> projects/project_id/messages/0:1607085339665987%fbe62b14fbe62b14
return;
}catch (Exception e) {
e.printStackTrace();
}
return;
}
Within resource folder inside Spring Boot project there is a json file, presumably gotten at the time of registering out app with FCM.
This file looks like this:
{
"type": "service_account",
"project_id": "project_id",
"private_key_id": "some string with private key id",
"private_key": "some long string with private key",
"client_email": "firebase-adminsdk-k202i#project_id.iam.gserviceaccount.com",
"client_id": "some client id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-9cgqi%40project_id_string_property.iam.gserviceaccount.com"
}
As soon as some user from iOS mobile app login in, User table gets updated with new valid push token which is part of simple login request. That push token is gotten before the actual login request is sent to our backend app. Namely, request from user's mobile app is made to FCM and a new push token is pulled. This is usual scenario I guess.
For testing I just call local service (Swagger) localhost8080:appName/admin/invoice/message.
The mobile app is not getting any notification!
The problem is that all other services with very huge requests bodies, and bunch of check-ups are able to send notifications. Unfortunately, I cannot invoke them, bunch of cases and conditions need to overlap in some way to be able to reach the lines of code above for sending push notifications!
How to send notifications locally to an end User, assuming all configuration is correct?
This is the function that is both sending sound to iOS and Android.
private Message getMessage(String token, String title, String body, String type, Map<String, String> data) throws FirebaseMessagingException {
AndroidNotification androidNofi = AndroidNotification.builder()
.setSound("default")
.build();
Aps aps = Aps.builder()
.setSound("default")
.build();
ApnsConfig apnsConfig = ApnsConfig.builder()
.setAps(aps)
.build();
AndroidConfig androidConfig = AndroidConfig.builder()
.setNotification(androidNofi)
.build();
Notification notification = new Notification(title, body);
Builder builder = Message.builder()
.setNotification(notification)
.setApnsConfig(apnsConfig)
.setAndroidConfig(androidConfig)
.putData("title", title)
.putData("body", body)
.putData("type", type)
.putData("priority", "high")
.setToken(token);
if (data != null) builder.putAllData(data);
Message message = builder.build();
return message;
}
I am using oauth2/token to authenticate my application and get the access_token. Bellow is the java code which is working fine.
private String getToken() throws Exception {
String access_token = "";
String url = "https://login.windows.net/MyApplication_ID_here/oauth2/token";
HttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("grant_type", "client_credentials"));
urlParameters.add(new BasicNameValuePair("client_id", "MyApplication_ID_here"));
urlParameters.add(new BasicNameValuePair("client_secret", "MyApplication_secret_here"));
urlParameters.add(new BasicNameValuePair("resource", "https://graph.microsoft.com"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
System.out.println("Sending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + post.getEntity());
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
String responseAsString = EntityUtils.toString(response.getEntity());
System.out.println(responseAsString);
try {
access_token = responseAsString.split(",")[6].split("\"")[3]; // get the access_token from response
} catch (Exception e) {
e.printStackTrace();
return null;
}
return access_token;
}
Response :
{"token_type":"Bearer","expires_in":"3599","ext_expires_in":"0","expires_on":"1493011626","not_before":"1493007726","resource":"https://graph.microsoft.com","access_token":"eyJ0e..."}
then I am using access_token to load the memberOf value which is not working and gives me the Access Token missing or malformed error. Bellow is the java code
private void getMemberOf()
{
HttpClient httpclient = HttpClients.createDefault();
try
{
URIBuilder builder = new URIBuilder("https://graph.windows.net/MyApplication_ID_here/users/test#testABC.onmicrosoft.com/memberOf?api-version=1.6");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
request.addHeader("Authorization", "Bearer " + access_token);
request.addHeader("Content-Type", "application/json");
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
}
catch (Exception e)
{
e.getMessage();
}
}
Response :
Response Code : 401
{"odata.error":{"code":"Authentication_MissingOrMalformed","message":{"lang":"en","value":"Access Token missing or malformed."},"date":"2017-04-24T04:39:38","requestId":"c5aa2abe-9b37-4611-8db1-107e3ec08c14","values":null}}
Can someone please tell me which part of the above request is wrong? Am I not setting access_token correctly?
According to your code , your access token is for resource "https://graph.microsoft.com"(Microsoft Graph API) ,But the access token is used for "https://graph.windows.net"(AAD Graph API) :
URIBuilder builder = new URIBuilder("https://graph.windows.net/MyApplication_ID_here/users/test#testABC.onmicrosoft.com/memberOf?api-version=1.6");
If you want to call Azure AD graph api , you need to get access token for Azure AD Graph API .
I got this issue while performing the CRUD operation on Azure AD B2C service via AD Graph API for user management.
The idea is to get the access token for the resource "graph.windows.net" instead I was using my tenant App Id URI as it was suggested here.
*might help people who faced the same issue and landed up here
We are trying to use Exact Online API. It is using Apache OAuth 2.0 framework. For that we followed the below document.
https://developers.exactonline.com/#OAuth_Tutorial.html%3FTocPath%3DAuthentication%7C_____2
I successfully able to get the authorization code but failing to get the access_token with exception like below.
OAuthProblemException{error='invalid_request', description='Missing parameters: access_token', uri='null', state='null', scope='null', redirectUri='null', responseStatus=0, parameters={}}
My code is like this.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
String code = oar.getCode();
OAuthClientRequest oAuthrequest = OAuthClientRequest
.tokenLocation("https://start.exactonline.co.uk/api/oauth2/token")
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId("my client id")
.setClientSecret("my client secret")
.setRedirectURI("http://localhost:8080/SampleServlet/AuthServlet")
.setCode(code)
.buildBodyMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, "POST",GitHubTokenResponse.class);
out.println("Access Token = " + oAuthResponse.getAccessToken());
} catch (OAuthSystemException ex) {
Logger.getLogger(AuthServlet.class.getName()).log(Level.SEVERE, null, ex);
} catch (OAuthProblemException ex) {
Logger.getLogger(AuthServlet.class.getName()).log(Level.SEVERE, null, ex);
} finally {
out.close();
}
}
Can some one please help me to sort this out.
Finally i resolved this issue with a simple change. The problem is with the line
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, "POST",GitHubTokenResponse.class);
Instead of this we have to use either of the below lines to get the access token properly.
OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, OAuth.HttpMethod.POST);
(Or)
OAuthAccessTokenResponse oAuthResponse =oAuthClient.accessToken(oAuthrequest,OAuth.HttpMethod.POST);
The google api project for my app contains a simple android key with two applications allowed. one is the com.examples.youtubeapidemo, the other is my app. If I take the com.examples.youtubeapidemo in and out of the key it fails as expected. The other app always returns this response:
11-06 08:06:52.321 32579-528/com.wfs.android.youtubesearchtest E/com.wfs.android.youtubesearchtest﹕ 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "Access Not Configured. Please use Google Developers Console to activate the API for your project.",
"reason" : "accessNotConfigured"
} ],
"message" : "Access Not Configured. Please use Google Developers Console to activate the API for your project."
}
my code is this:
[in an async task]
{
YouTube.Builder builder = new YouTube.Builder(
new NetHttpTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request)
throws IOException {
}
})
.setApplicationName((String.valueOf(R.string.app_name)));
return builder.build();
}
and this:
{
// ...
YouTube youTube = createYouTubeService();
YouTube.Search.List search = null;
try {
search = youTube.search().list("id,snippet");
} catch (IOException e) {
Log.e(TAG, e.getMessage());
return null;
}
search.setKey(Developerkey.DEVELOPER_KEY);
search.setQ(q[0]);
search.setType("video");
search.setFields("items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)");
search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED);
SearchListResponse searchListResponse = null;
try {
searchListResponse = search.execute();
}
The exception is thrown in searchListResponse = search.execute();
I have tested the key, is there anything I may have missed in the code?
I also tested with a browser key and the com.examples.youtubeapidemo works with either one. My app still has the same issue; So all the posts about using a browser key instead did not work for me.
Ok this is old but I figured this out for my case and I thought it might help others. I went to oauth and it seemed to resolve.
the real issue is that if you use an unrestricted key [and maybe, depepending on the api enabled] have a billing account linked; the api should work. If it works unrestricted, you are on the right track.
Once you restrict it to android it will fail again with that key until you sign your app. The easiest way i found was the use a signing config for the variants under android in the gradle file.
signingConfigs {
debug {
storeFile file("/users/xxxxxxxxxx/Android/keystores/google_demos/debugandroid.jks")
storePassword "xxxxxxxxxx"
keyAlias "com.example.xxxxxxxxxx"
keyPassword "xxxxxxxx"
}
}
I am trying to connect to the survey monekey API with this code, which is not working. It says "Invalid API key" even though I got the API from the API console.
public void fetch() {
String url = "https://api.surveymonkey.net/v2/surveys/get_survey_list?api_key=" + apiKey;
System.out.println("request being sent");
System.out.println(url);
JSONObject obj = new JSONObject();
try {
// byte[] postDataBytes = obj.toJSONString().getBytes("UTF-8");
URL ourl = new URL(url.toString());
HttpURLConnection conn = (HttpURLConnection) ourl.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "bearer " + accessToken);
conn.setRequestProperty("Content-Type", "application/json");
conn.getRequestProperty(obj.toString().getBytes("UTF-8").toString());
int k = conn.getResponseCode();
System.out.println("The response code received is " + k);
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
output = br.readLine();
System.out.println(output);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Here's the error:
request being sent
https://api.surveymonkey.net/v2/surveys/get_survey_list?api_key=---API-KEY----
The response code received is 200
Output from Server ....
{"status":3,"errmsg":"Expected object or value"}
I just got this url from the API console.
Ensure you are using the API key associated with your developer account registered at http://developer.surveymonkey.com, not the sample API key the console uses to let you try requests. The sample api key is not meant to be used with apps, only on the API console.
That particular error is generated when an empty string is sent for the POST data. The API expects an empty object at minimum ("{}"). If the issue pointed out by Miles above was just a typo (using 'getRequestProperty' instead of 'setRequestProperty',) check if toString on an empty JSONObject is returning "" or "{}".