Limit access to my endpoints to my Android app only - android

I'm new to the Google App Engine, and I'm trying to make my first engine and connect it to my Android app. I have walked through this tutorial in order to learn about it:
https://cloud.google.com/endpoints/docs/frameworks/legacy/v1/java/helloendpoints-android-studio
I got it to work fine. I can access my app engine from my android app, and get the wanted response. The problem is, I want to restrict the endpoints of my API to my app's users only.
This is my API method (from the tutorial), and as for now, everyone can access my api's explorer and execute methods in it, as long as they are logged in to any Google account.
I want the users to be able to execute this method from my app only.
This is my app engine java file:
package com.example.Barda.myapplication.backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.UnauthorizedException;
import com.google.appengine.api.users.User;
import javax.inject.Named;
/**
* An endpoint class we are exposing
*/
#Api(
name = "myApi",
version = "v1",
clientIds = {Constants.ANDROID_CLIENT_ID},
audiences="firebase-wiki-race.appspot.com",
namespace = #ApiNamespace(
ownerDomain = "backend.myapplication.Barda.example.com",
ownerName = "backend.myapplication.Barda.example.com",
packagePath = ""
)
)
public class MyEndpoint {
/**
* A simple endpoint method that takes a name and says Hi back
*/
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String name) throws UnauthorizedException {
// if (user == null) throw new UnauthorizedException("User is Not Valid");
MyBean response = new MyBean();
response.setData("Hi, " + name);
return response;
}
}
This is constants class:
package com.example.Barda.myapplication.backend;
/**
* Contains the client IDs and scopes for allowed clients consuming your API.
*/
public class Constants {
public static final String ANDROID_CLIENT_ID = "*********************.apps.googleusercontent.com";
}
I have generated using my app's SH-1 and package name the ANDROID_CLIENT_ID.
I have searched online a lot, and read blogs and threads, but I couldn't make it work. Is this a possible thing to do? What am I doing wrong?

You'll want to follow the documentation's guide on adding authorization to the API backend. In this process you define a list of clients that are authorized to use your Endpoint.
Once that's done you can follow the guide on making authenticated calls from Android.

Related

create spreadsheet programmatically in android studio

I want to create a spreadsheet programmatically in android studio. how can I do that?
I used OAuth for signing in the user and now wants to create the spreadsheet in his drive folder.
I found the below code but don't know how to use it...
Spreadsheet spreadsheet = new Spreadsheet()
.setProperties(new SpreadsheetProperties()
.setTitle(title));
spreadsheet = service.spreadsheets().create(spreadsheet)
.setFields("spreadsheetId")
.execute();
System.out.println("Spreadsheet ID: " + spreadsheet.getSpreadsheetId());
For creating a Google Sheet in a programmatic way you should try to use Sheet API. More specifcally you need to use the create method.
If you are using the Google libraries for Java you could just try to follow the example in the create endpoint:
/*
* BEFORE RUNNING:
* ---------------
* 1. If not already done, enable the Google Sheets API
* and check the quota for your project at
* https://console.developers.google.com/apis/api/sheets
* 2. Install the Java client library on Maven or Gradle. Check installation
* instructions at https://github.com/google/google-api-java-client.
* On other build systems, you can add the jar files to your project from
* https://developers.google.com/resources/api-libraries/download/sheets/v4/java
*/
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.Spreadsheet;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class SheetsExample {
public static void main(String args[]) throws IOException, GeneralSecurityException {
// TODO: Assign values to desired fields of `requestBody`:
Spreadsheet requestBody = new Spreadsheet();
Sheets sheetsService = createSheetsService();
Sheets.Spreadsheets.Create request = sheetsService.spreadsheets().create(requestBody);
Spreadsheet response = request.execute();
// TODO: Change code below to process the `response` object:
System.out.println(response);
}
public static Sheets createSheetsService() throws IOException, GeneralSecurityException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
// TODO: Change placeholder below to generate authentication credentials. See
// https://developers.google.com/sheets/quickstart/java#step_3_set_up_the_sample
//
// Authorize using one of the following scopes:
// "https://www.googleapis.com/auth/drive"
// "https://www.googleapis.com/auth/drive.file"
// "https://www.googleapis.com/auth/spreadsheets"
GoogleCredential credential = null;
return new Sheets.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("Google-SheetsSample/0.1")
.build();
}
}
This example is not handling credentials and you will need to change this in order to work
In case you need more information in the libraries read through the Java Quickstart to work from there, also look at the java create method. And of course you can just do an HTTP request if you have already managed all the OAuth part.

Cloud Endpoints generate entity key inside of Android/iOS client libs

Is there a way inside of Android Java to create an Entity Key?
For example, inside the Cloud Endpoints Java module code you can do this:
Key<User> userKey= Key.create(User.class, userId);
or with an Ancestor:
Key<Post> postKey= Key.create(userKey, Post.class, postId);
How can you do the above in the Android generated client library? I want to see if I can create a key in Android and pass it to an API method (probably as a websafeKey userKey.getString()).
BONUS: How can you do this with the objective-C Cloud Endpoints client library?
I doubt you want either the datastore nor objectify code in your Android App. That simply not where that belongs. So the way to go is to look at the source of the KeyFactory. In the method keyToString() we can see that most of the magic happens in the class KeyTranslator in method convertToPb().
Here's the code of convertToPb:
public static Reference convertToPb(Key key) {
Reference reference = new Reference();
reference.setApp(key.getAppId());
String nameSpace = key.getNamespace();
if (!nameSpace.isEmpty()) {
reference.setNameSpace(nameSpace);
}
Path path = reference.getMutablePath();
while (key != null) {
Element pathElement = new Element();
pathElement.setType(key.getKind());
if (key.getName() != null) {
pathElement.setName(key.getName());
} else if (key.getId() != Key.NOT_ASSIGNED) {
pathElement.setId(key.getId());
}
path.addElement(pathElement);
key = key.getParent();
}
Collections.reverse(path.mutableElements());
return reference;
}
And here's the code of keyToString()
public static String keyToString(Key key) {
if (!key.isComplete()) {
throw new IllegalArgumentException("Key is incomplete.");
} else {
Reference reference = KeyTranslator.convertToPb(key);
return base64Url().omitPadding().encode(reference.toByteArray());
}
}
Now what you want to do, is to replace the Key stuff in convertToPb with "normal" parameters (type, name/key, parent type, parent name/key) and thus rewrite the method to create a websafeKey without an actual Key object.
It would be much easier though if your app engine API simply accepted the ids and you'd recreate the key on the appengine side of things. My APIs are usually structured like
/user/<userId>/post/<postId>
if i assume an Entity that looks like this
#Entity public class Post {
#Parent Ref<User> user
#Id id; }
Regarding the bonus: What (the heck) is an Objectify Cloud Endpoint? I know Cloud Endpoints and Objectify, but i have not heard of a product that combines the two.

What does Device Id mean Azure Push Notifications in Xamarin Android? How to get it?

We are using Azure Mobile Services to Push notifications to a Xamarin Android and a Xamarin iOS and a Windows Universal App. The Windows Universal App has plenty of documentation around what we need, although we haven’t had a chance to implement it yet. However, both Xamarin Android and iOS are missing all documentation around Push Notifications. If you go to http://azure.microsoft.com/en-us/documentation/services/mobile-services/ and select Xamarin Android or Xamarin iOS and .NET Backend there are zero links for documentation around these APIs. After digging around a ton yesterday I found this: http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-xamarin-android-get-started-push/ and http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-xamarin-ios-get-started-push/ both which were last updated in September of last year. The documentation was promised to be updated over 5 months ago.
When I use the Xamarin Component from Microsoft for Azure Mobile Services: http://components.xamarin.com/view/azure-mobile-services/ I am able to get the MobileServiceClient up and running, but not the Push notifications.
The API:
Push pushManager = MobileService.GetPush();
string deviceId = "what is this???";
//Option 1:
pushManager.RegisterNativeAsync(deviceId);
//Option 2:
GcmRegistration googleNotificationRegistration = new GcmRegistration(deviceId);
pushManager.RegisterAsync(googleNotificationRegistration);
Documentation I’m using:
Push.RegisterAsync:
https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.mobileservices.push.registerasync.aspx
GcmRegistration: I can’t find any documentation for this class
Registration (Base class for GcmRegistration):
https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.mobileservices.registration.aspx
Note: the parameter for Registration is not named deviceId it is named channelUri
Push.RegisterNativeAsync:
https://msdn.microsoft.com/en-us/library/dn643553.aspx
Note: the parameter of RegisterNativeAsync is not named deviceId it is named channelUri
My question is simple:
What is deviceId supposed to be? And how do I get it?
All the documentation above is for Winodws Universal Apps not for Xamarin Apps on Mono.
In the writing up of this question I have found articles about "Get Started with Notification Hubs":
Xamarin iOS - http://azure.microsoft.com/en-us/documentation/articles/partner-xamarin-notification-hubs-ios-get-started/
Xamarin Android - http://azure.microsoft.com/en-us/documentation/articles/partner-xamarin-notification-hubs-android-get-started/
Are these the example I should be using? They look old and the Android one mentions nothing about Azure Mobile Services. Should I not even be using the Azure Mobile Services Xamarin Component for Android?
tl;dr
deviceId should be just the GCMRegistrationId.
I looked into the source code of the implementations of the component DLLs and also Android SDKs.
Firstly, let's take a look to your option 1 and option 2 behind the scene. Basically both eventually do the same job of creating a GcmRegistration and passing it the internal RegistrationManager.
public Task RegisterAsync (Registration registration)
{
if (registration == null) {
throw new ArgumentNullException ("registration");
}
if (string.IsNullOrWhiteSpace (registration.PushHandle)) {
throw new ArgumentNullException ("registration.deviceId");
}
return this.RegistrationManager.RegisterAsync (registration);
}
public Task RegisterNativeAsync (string deviceId, IEnumerable<string> tags)
{
if (string.IsNullOrWhiteSpace (deviceId)) {
throw new ArgumentNullException ("deviceId");
}
GcmRegistration registration = new GcmRegistration (deviceId, tags);
return this.RegistrationManager.RegisterAsync (registration);
}
Then, one of the API calls that I can find involving the Registration.PushHandle (which is the deviceId you passed) is as below
public async Task<IEnumerable<Registration>> ListRegistrationsAsync (string deviceId)
{
MobileServiceHttpResponse mobileServiceHttpResponse = await this.client.HttpClient.RequestAsync (HttpMethod.Get, string.Format ("/push/registrations?deviceId={0}&platform={1}", new object[] {
Uri.EscapeUriString (deviceId),
Uri.EscapeUriString (Platform.Instance.PushUtility.GetPlatform ())
}), this.client.CurrentUser, null, true, null, MobileServiceFeatures.None);
return JsonConvert.DeserializeObject<IEnumerable<Registration>> (mobileServiceHttpResponse.Content, new JsonConverter[] {
new RegistrationConverter ()
});
}
I have then switched to Android Mobile Services SDK to look for similar code to find some hints. Sadly, it is found called pnsHandle in android but still no hints what it is.
/**
* Registers the client for native notifications with the specified tags
* #param pnsHandle PNS specific identifier
* #param tags Tags to use in the registration
* #return The created registration
* #throws Exception
*/
public Registration register(String pnsHandle, String... tags) throws Exception {
if (isNullOrWhiteSpace(pnsHandle)) {
throw new IllegalArgumentException("pnsHandle");
}
Registration registration = PnsSpecificRegistrationFactory.getInstance().createNativeRegistration(mNotificationHubPath);
registration.setPNSHandle(pnsHandle);
registration.setName(Registration.DEFAULT_REGISTRATION_NAME);
registration.addTags(tags);
return registerInternal(registration);
}
Finally, I guess the below example code from http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-android-get-started-push/#update-app should be calling the same API which now explain everything, i.e. deviceId is just the GCMRegistrationId.
#Override
public void onRegistered(Context context, final String gcmRegistrationId) {
super.onRegistered(context, gcmRegistrationId);
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
try {
ToDoActivity.mClient.getPush().register(gcmRegistrationId, null);
return null;
}
catch(Exception e) {
// handle error
}
return null;
}
}.execute();
}

Change eBay search from US to UK

I am trying to change the search site that my eBay Android app searches in. At the moment, it searches the US site, but I would like it to search the UK site.
Here's my findingServiceClient class that I'm trying to make search the UK site, with the country code 3(UK, source).
As far as I can see I have set my code up to search the UK site, but it still seems to search the US.
any help would be appreciated, thanks.
public class FindingServiceClient {
// production
public static String eBayFindingServiceURLString = "http://svcs.ebay.com/services/search/FindingService/v1";
// sandbox
//public static String eBayFindingServiceURLString = "https://svcs.sandbox.ebay.com/services/search/FindingService/v1";
public static String eBayAppId = "ebay_app_id";
private static volatile FindingServicePortType_SOAPClient client = null;
public static String targetSiteid = "3";
public static FindingServicePortType_SOAPClient getSharedClient() {
if (client == null) {
synchronized(FindingServiceClient.class) {
if (client == null) {
client = new FindingServicePortType_SOAPClient();
client.setEndpointUrl(eBayFindingServiceURLString);
client.setSoapVersion(SOAPVersion.SOAP12); // ebay finding service supports SOAP 1.2
client.setContentType("application/soap+xml");
client.getAsyncHttpClient().addHeader("X-EBAY-API-SITE-ID", targetSiteid);
client.getAsyncHttpClient().addHeader("Accept", "application/soap+xml");
client.getAsyncHttpClient().addHeader("X-EBAY-SOA-SECURITY-APPNAME", eBayAppId);
client.getAsyncHttpClient().addHeader("X-EBAY-SOA-MESSAGE-PROTOCOL", "SOAP12");
client.getAsyncHttpClient().addHeader("X-EBAY-SOA-REQUEST-DATA-FORMAT", "SOAP");
}
}
}
return client;
}
}
The site that is searched is specified in the HTTP header X-EBAY-SOA-GLOBAL-ID. The value of this header is not a unique integer, such as 3, but a unique string, such as EBAY-US. To search the UK site you need to make the two below changes to your code and remove any reference to X-EBAY-API-SITE-ID.
public static String targetSiteid = "EBAY-GB";
client.getAsyncHttpClient().addHeader("X-EBAY-SOA-GLOBAL-ID", targetSiteid);
The eBay docs provide a complete list of HTTP headers and a table of site IDs mapped to global IDs.

Reading information from CIFS / SMB with an Android application

I've been attempting to develop an android application that can pull information from a CIFS / SMB protocol. I've tried JCIFS and keep getting errors with my eclipse application not being able to read the package (even after I've Javadoc'd it), and my last resort was to get help. Therefore, can anyone offer incite / information on how to do this?
I've tried this : Copy all files from server to Android Device
I've tried this : http://jcifs.samba.org/
I've tried this: http://learn-it-stuff.blogspot.com/2012/01/adding-jcifs-api-to-our-android-java.html
Maybe there is a couple things I'm not understanding at the moment that could be fleshed out.
My snippet of the code I'm using (copy and pasted directly from the third link for the most part) :
public void login(String address2, String username2, String password2)
throws Exception {
setDomain(UniAddress.getByName(address2));
setAuthentication(new NtlmPasswordAuthentication(address2, username2,
password2));
SmbSession.logon(getDomain(), authentication);
}
public UniAddress getDomain() {
return domain;
}
/**
* #param domain
* the domain to set
*/
public void setDomain(UniAddress domain) {
this.domain = domain;
}
/**
* #return the authentication
*/
public NtlmPasswordAuthentication getAuthentication() {
return authentication;
}
/**
* #param authentication
* the authentication to set
*/
public void setAuthentication(NtlmPasswordAuthentication authentication) {
this.authentication = authentication;
}
and then from here I'm calling the login(); with a address, username, and password. When I do this the application crashes and gives me an error of "NoClassDefFoundError" at the line: setDomain(UniAddress....), specifically from the UniAddress class.
Could anyone help me with this?
Noticing that you have followed the procedure from:
http://learn-it-stuff.blogspot.com/2012/01/adding-jcifs-api-to-our-android-java.html
in importing jcifs.jar for UniAddress and other jcifs apis,
but for it to work :
jcifs.jar must be present in <Project Name>/libs folder

Categories

Resources