I am trying to implement Android Management API in my project where the first step is to create an enterprise:
Post the Callbackurl and ProjectID to the Following URL
https://androidmanagement.googleapis.com/v1/signupUrls
I get the response name and url:
{
"name": "signupUrls/C265d41bc093bdd97",
"url": "https://play.google.com/work/adminsignup?token=someToken"
}
How can I Change this "url" parameter to my own. Do I require to upload my DPC to playstore?
I am out of guesses. please help
Thanks in advance.
The flow is this:
1) Create a Project in Google developer console, enable Android Management API, create credentials and get the project id. (I think you already done that).
2) Create a SignupUrl with signupUrls.create. (What you have done to get that JSON)
3) Keep the SignupUrl Name and redirect the user (or go) to the returned URL (inside the JSON posted).
3) Follow the procedure to create an enterprise.
This will start the creation of an enterprise to the signed Google Account.
4) At the end of the procedure you will be redirected to the callbackUrl specified inside signupUrls.create. Appended to the callbackUrl, as a GET query parameter, will be a token.
5) You must use the appended token to conclude the flow calling the API enterprises.create with these parameters:
The signup url name
The enterprise token returned as parameter
(optional) a request body with some enterprise parameters (logo, name, etc)
At the end of this coming and going between URLs and API calls, you will end with an Enterprise created on the Google Account and the enterprise ID in the form enterprise/<yourID> to interact with the API.
You can check all the Enterprise infos at the created Google Play for Work (or Managed Google Play) at http://play.google.com/work . Left menu "Administration Settings" at check your enterpriseId.
Related
Twitter login isn't working anymore on my android project and I have figured out that it's because I have restricted my API keys in Google cloud. By default, twitter login makes use of an https request https://<project_name>.firebaseapp.com/__/auth/handler....apiKey=...&providerId=twitter.com&sessionId etc where apiKey is the API key in my google-services.json. Given that I have restricted the API Key to my Android app package name, https requests for twitter login return an error. If I manually edit the url and put the Browser API key, it works fine but this is obviously not a practical solution for production.
Is there a way to tell AuthUI.IdpConfig.TwitterBuilder() to use a specific API Key so that I can pass the default Browser API key.
I have tried to manually edit google-services.json to add the Browser API Key and this fixes the Twitter Log in issue and breaks other calls to the server.
One work around is to have an extra key that your end users can have who you trust and check this via query params.
Const BrowserAPIKey = 'realKeyhere';
Create a unique key and save it as a constant in the function you call Twitter login.
Under the key variable call any URL and append a query param like so e.g. firebaseauth.com/twitter?key=123 and then pluck out the key by calling req.body.key so if you requested the API with a param called key. I.e. save this in another const e.g. const enteredKey = req.body.key. We expect 123 to be the resolved key if things are to work
Check if trusted clients got key right and release Browser API Key based on result:
If enteredKey = 123
// Call Twitter login api with real browser key
https://<project_name>.firebaseapp.com/__/auth/handler....apiKey=BrowserAPIKey...&providerId=twitter.com&sessionId
Assumptions:
This API accepts the browser key via a param called browserkey and spelt exactly that way
The BrowserAPIKey when in step 3 above contains the actual key that clients need to login with
I got in touch with Firebase support and this is expected behaviour if you restrict your API. In short, the API restriction for Android application is searching for package name and SHA-1 headers, the Twitter sign-in flow is based on a browser, so the headers are not sent, also there is no way to pass the headers through the browser.
The best approach would be using API restrictions (which APIs can my API be used for) rather than platform restrictions (which platforms can use this API key).
I implemented in-app billing in my mobile app. It uses auto renewing subscription. I want to check the subscription expiry date through the app. I found this link to check the subscription details : Purchases.subscriptions:get
The documentation shows that some authorization needed. I have tried but I am not able to get the result. I got client secret.json file but it does not contain client secret Id. So please help me to get the subscription expiry date.
My answer is late, but maybe it helps somebody else. See my answer here: Server side authorization with Google Play Developer API?
And these are the steps when you would do it manually:
1.) Create credentials in your OAuth2 configuration in Google API with the following link: https://developers.google.com/mobile/add?platform=android&cntapi=signin&cnturl=https:%2F%2Fdevelopers.google.com%2Fidentity%2Fsign-in%2Fandroid%2Fsign-in%3Fconfigured%3Dtrue&cntlbl=Continue%20Adding%20Sign-In
2.) Go to your Developer API console. If you have done the first step correct, the result should look like something like that:
3.) Go to Google Play Developer Console -> All Apps -> Settings -> API Access and link the project you defined in Developer API Console (step 2, black bar top left). (If you can't link your project in Google Play, because you didn't find some, you used different google accounts for Google Developer API and Google Play Developer Console.)
4.) Invoke the following link with your callback url:
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://www.yourdomain.com/oauth2callback&client_id=[WEBAPPLICATION_ID_FROM_ABOVE.apps.googleusercontent.com]
My /oauth2callback script is a simple php script. (This is not production safe. It's just for illustration):
oauth2callback.php
<?php
print_r($_REQUEST);
?>
5.) After you invoked the url from above, you will be asked for your google account and allowance to access the api. After you confirmed, you will be redirected to your callback url and get a result which looks like this:
4/vPv_eYX-az6YucwdpBzATpJEu8129gN9aYsUIMI3qgQ
6.)¹ Get an oauth2 access token and refresh token by invoking a POST request to https://accounts.google.com/o/oauth2/token with the following headers:
grant_type=authorization_code
code=4/vPv_eYX-az6YucwdpBzATpJEu8129gN9aYsUIMI3qgQ
client_id=[YOUR_WEBAPPLICATIONID.apps.googleusercontent.com]
client_secret=[YOUR CLIENT SECRET OF THIS WEBAPPLICATION ID]
redirect_uri=http://www.yourdomain.com/oauth2callback
(The client secret can be found when you click on the Web Client ID of the OAuth2 client IDs in the Developer Console from step 2)
The result will look like this:
{
"access_token": "ya29.GdsCBbnM584k3SUzoxDgIdaY26pEM_p_AdhkIkFq3tsai8U7x8DuFKq3WEF7KquxkdLO89KHpuUFdJOgkhpGbGyDfxkD32bK1ncnsu2IkA0e_5ZayOEr86u4A1IN",
"expires_in": 3600,
"refresh_token": "1/U5HF1m0nHQwZaF2-X35f_xyFaSOofdw3SEubnkkYUQ0",
"token_type": "Bearer"
}
7.) The access token is needed to invoke the Google Developer API requests, for example: https://www.googleapis.com/androidpublisher/v2/applications/[packageName]/purchases/subscriptions/subscriptionId/tokens/[purchaseToken]?access_token=ya29.GdsCBbnM584k3SUzoxDgIdaY26pEM_p_AdhkIkFq3tsai8U7x8DuFKq3WEF7KquxkdLO89KHpuUFdJOgkhpGbGyDfxkD32bK1ncnsu2IkA0e_5ZayOEr86u4A1IN
8.) The access token expires very quickly. With the refresh you can fetch new access tokens by using the following url and headers:
POST https://accounts.google.com/o/oauth2/token
grant_type=refresh_token
client_secret=[YOUR CLIENT SECRET]
refresh_token=1/U5HF1m0nHQwZaF2-X35f_xyFaSOofdw3SEubnkkYUQ0
client_id=[YOUR_WEBAPPLICATION_ID.apps.googleusercontent.com]
Result:
{
"access_token": "ya29.GlsCBZuN7hYJILi5VaVggIsCIb1_5feGvcjvQFmJRnPYXsnhsi_w3Md87tQwGd_WXmifo4s5739c3IU5INPmby8q64k0LdDFkO2JpNRG13K9sizvU1Sc-3cWzbf8",
"expires_in": 3600,
"token_type": "Bearer"
}
HINT (1): If you don't get a refresh token from the request of step 6, attach the following query params to your request: prompt=consent
I also struggled a bit with this, but at least I found what needs to be done.
Google provides an android library google-api-services-androidpublishe that can be used to access the Purchase.Subscription.Get API.
implementation 'com.google.apis:google-api-services-androidpublisher:v3-rev74-1.25.0'
Here is a Kotlin code example:
import com.google.api.client.http.apache.ApacheHttpTransport
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.androidpublisher.AndroidPublisher
...
fun retrieveSubscriptionInfo(sku: String) {
val packageName = ""
val sku = ""
val purchasedSubscriptionToken = ""
val apacheHttpTransport = ApacheHttpTransport()
val jacksonJsonFactory = JacksonFactory.getDefaultInstance()
val AndroidPublisher.Builder(apbacheHttpTransport, jacksonJsonFactory, null).build()
val request = publisher.Purchases().subscriptions().get(packageName, sku, purchasedSubscriptionToken);
return request.execute()
}
Note that before the above code is executed you must first Authorize the AndroidPublisher. You would have to request the users permission in order to be able to query the Purchase.Subscription.Get
Hope that this is helpful.
Google's documentation here is horrible, no clear examples of implementation. I finally found the answer after a LOT of Googling thanks to #Sabeeh's answer here and lots of other snippets spread out online.
1. First step is to add the dependencies:
implementation "com.google.apis:google-api-services-androidpublisher:v3-rev142-1.25.0" // Update based on latest release
implementation "com.google.auth:google-auth-library-oauth2-http:1.12.1" // Update based on latest release
2. Follow these steps to link the Google Play Console with Google Play Developer API (choose the "Use a service account", not "Use OAuth clients" and follow until "Additional information").
3. Download the services JSON file from your Google Cloud service account (click on the account that you set up in the previous step). You can find/create this file under the "Manage Keys" action or the "Keys" tab. Add the exported JSON file in your assets folder in Android
4. Then you can call the Google Play Developer API to query subscriptions like this (important to call from a Thread, didn't work from the UI thread, not sure why):
new Thread(() -> {
InputStream inputStream = context.getAssets().open("service_account_google_play.json"); // JSON file from step 3
GoogleCredentials credentials = GoogleCredentials.fromStream(inputStream)
.createScoped(AndroidPublisherScopes.ANDROIDPUBLISHER);
AndroidPublisher androidPublisher = new AndroidPublisher(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
new HttpCredentialsAdapter(credentials)
);
SubscriptionPurchase purchase = androidPublisher.purchases().subscriptions().get(
context.getPackageName(), subscriptionId, purchaseToken
).execute();
// Do with the purchase object what you want here
}).start();
At the risk of being overly descriptive, the subscriptionId is the ID of your subscription in the Play Console (e.g. subscription_monthly or whatever you called it), and the purchaseToken is the token you get from the Purchase token after querying the BillingClient (querying subscriptions is explained in detail here).
Let me know if anything is unclear or doesn't work yet. This took me 6 hours to figure out and I'm happy to save others that pain.
I am an Android developer building my first Google App Engine (java) back-end for my apps. I don't want anybody else to access this API other than my app. (I plan to use App engine for verifying InApp purchases in my Android app). My data is not relevant to users so,
I don't want users to be able to access my API even if they are logged in with their Google accounts (on web or Android devices).
I followed the steps mentioned in - "Specifying authorized clients in the API backend"
(https://developers.google.com/appengine/docs/java/endpoints/auth)
like generating client IDs and add them in #Api (clientIds and audiences)
except "Add a User parameter" - since I don't need user authentication.
Then I deployed App engine and I am still able to access the API through API explorer (https://your_app_id.appspot.com/_ah/api/explorer)
(I haven't added API_EXPLORER client ID)
I tested with the APK that was built with the endpoint libs before adding client IDs and can still access the API.
Is adding a "User parameter" to all endpoint APIs a must? to achieve my purpose (restrict API to only my Android apps).
Can I pass null as userAccount name from Android client and ignore user parameter value on server (since it will be null)? Will this ensure that the API is accessible only from my android apps (since the client ID is generated for my package name and SHA1 of the APK?)
Should I use something like a service account for this purpose?
The documentation says for Android, both Android and Web client IDs must be added and audience must be the same as web client ID. Does this open access to any other web client? can I skip mentioning web client ID and still achieve my purpose?
Appreciate your time and help.
...... updating with my further investigation ...
I did the following:
Added User parameter to APIs on backend - but did not check for null value. API can still be accessed without passing any credentials (from Android debug APK and API explorer)
Then, I tried
mCredential = GoogleAccountCredential.usingAudience(this, "server:client_id:" + WEB_CLIENT_ID);
mCredential.setSelectedAccountName(null);
and passed this credential to API builder (as suggested in some other posts)
Caused FATAL EXCEPTION. So, we can't pass null account name.
I could call the API using API explorer without OAuth. But when I enabled OAuth, it gave error saying this client ID is not allowed! ( I haven't yet added com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID in client_ids{})
Then I added code to throw OAuthRequestException on the backend if the user is null. This resulted in API explorer getting errors without OAuth. It works with OAuth enabled after adding API_EXPLORER_CLIENT_ID to client_ids)
Added code to pass valid user account name(email) from my Android app. Then, I am able to access API only with my release APK. Even the debug APK gets exceptions! - which is what I expected..So, I assume no other Android apps will be able to access this API.
So, not checking for null user on back-end API is a bad idea (as suggested in other posts). It is as good as not mentioning any client_ids and not having User param.
Only question I have at this moment is: If some one can figure out the WEB_CLIENT_ID from the APK, will they be able to use it to build a web client to access my API (I haven't mentioned client secret anywhere in the code. So I am thinking this is not possible).
I did search Google groups and Stackoverflow, but still it is not clear.
(Authenticate my “app” to Google cloud endpoints not a “user”)
Authenticate my "app" to Google Cloud Endpoints not a "user"
(How do I protect my API that was built using Google Cloud Endpoints?)
How do I protect my API that was built using Google Cloud Endpoints?
(Restrict access to google cloud endpoints to Android app)
Restrict access to google cloud endpoints to Android app
I had a similar issue, not between Android and App Engine, but between a separate server and App Engine. The way I handled it was to add a signature hash field as a parameter to each API call. If the request had an improper signature, it would be denied.
For example, suppose your API end-point is example.com/api/do_thing?param1=foo. I would hash the entire url, along with a secret key, and then append the result of the hash to the request: example.com/api/do_thing?param1=foo&hash=[some long hex value].
Then, on the server side, I would first remove the hash from the url request, then run the hash on everything that was remaining. Finally, you check whether the calculated hash matches the one that was sent with the request and if they don't, you can deny the request.
It is very important however that your secret key remain secret. You have to be careful with this on Android because someone could attempt to decompile your APK.
Facing the same problem than you ! Authenticate Android End point without Google User Account is just impossible !
So here is my way to resolv this problem, without any user interaction (Maybe not the right but that works, and you've got strong authentication (SHA1 + Google Account)):
HERE IS MY ANDROID CODE
Get and Build Valid Credential
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
Use this credential for secure calls
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
HERE IS MY API BACKEND CODE:
API Annotation
#Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
Method code:
public Collection<Campagne> getCampagnes(#Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
For the moment, it only works on Android (I don't know how we gonna do on IOS..)..
Hope It will help you !
Google provides ways to do this for Android, web and iOS
The steps involves:
Specifying a client Id for apps you want to allow to make requests to your API
Adding a User parameter to all exposed methods to be protected by authorization.
Generating the client library again for any Android clients
Redeploying your backend API.
Updating the regenerated jar file to your Android project for your Android client.
These steps are laid out in clear detail on Google's Using Auth with Endpoints and also on this blog
Facing the same problem, here are the result of my research :
Added Android cliend id with SHA1 fingerprint in Google console
Use of it in the API annotation
BUT :
If i dont add user parameter to methods : the check about android app client id does not work
If I add the USER parameter but do not ask the user to choose its google account to create the credential ... also it does not work ...
Conclusion : It seems to be mandatory to connect a user account for the check about the app client id to be executed ... I really do not understand why because no link exist between the 2 processes
Access this site
Choose your project, go to credentials section
Create a new api key
Create a new android key
Click on "Edit allowed android applications" and enter your SHA1 key; your android package name
Let me know if this solves the issues.
I'm trying to implement one-time code sign in flow in my system.
Application contains of two parts:
1)Android application which requests Google+ for one-time authorization code
2)Rails server that receives one-time code from android application in request header and tries to exchange code for access_token and id_token from Google+
The problem is that everything works well if I get one-time code using JavaScript sign-in button in browser, but doesn't work when one-time code is obtained by Android application and then sent to my server.
I'm getting always
"error" : "redirect_uri_mismatch"
My server settings are following:
{ "web":
{ "client_id": "MY_REGISTERED_WEB_APP_CLIENT_ID",
"client_secret": "MY_CLIENT_SECRET",
"redirect_uris": ["postmessage"],
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token"
}
}
Now, how I'm requesting one-time code from Android app:
I use the same MY_REGISTERED_WEB_APP_CLIENT_ID as on my server for requesting one-time code. I don't know, maybe I have to use on Android another client id, that corresponds to my Android application? But all found documentation and articles are pointing to registered
Web app client_id.
Or maybe my rails server should be configured not for web, but for installed type of registered in Google Console apps?
Now regarding redirect_uris.
I've tried to set several redirect_uris in Google Console:
empty field
http://localhost:5000
https://localhost:5000
http://my.deployment.url/auth2callback
Web origins in Google console are set to
- http://my.deployment.url
- http://localhost:5000
Can't figure out what I'm doing wrong.
Actually I don't understand why I need to set this redirect_uris values, since I don't want to have callbacks from Google, I just want to get access_token and use it for accessing Google+.
This is happening because the redirect_uri your android app is using to create the initial login flow is different from the redirect_uri the server is using when it tries to excange the code for an access_token. The redirect_uri the user returns to and the redirect_uri used in the token exchange must match.
The proper redirect_uri in this case is "urn:ietf:wg:oauth:2.0:oob"
I just need the correct format of the request - https://www.googleapis.com/customsearch/v1?
key=INSERT-YOUR-KEY&cx=013036536707430787589:_pqjad5hr1a&q=flowers&alt=json.
My app will simply make a request with the search phrase and get a callback in JSON. I already connect Google Custom Search to my account, fill in the payment details and get all the keys.
I use the key for Android apps (with certificates), but get the response "Access Not Configured" after call the request in the browser.
How to create a query string to request the API? How can I get the parameter cx?
This is a bug of Google. The problem was solved only completely removing default project and create a new one.