I was trying to use Twilio's official Java library in my GWT application to send text messages.
Here is the Twilio code I used in my application:
public class TwilioSMS{
/** The Constant ACCOUNT_SID. */
public static final String ACCOUNT_SID = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
public static final String AUTH_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxx";
// Create a rest client
TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
/**
* The main method.
*
* #param args
* the arguments
* #throws TwilioRestException
* the twilio rest exception
*/
public String sendMessage(String _to, String _message) throws TwilioRestException
{
// Get the main account (The one we used to authenticate the client
Account mainAccount = client.getAccount();
// Send an sms
SmsFactory smsFactory = mainAccount.getSmsFactory();
Map<String, String> smsParams = new HashMap<String, String>();
smsParams.put("To", _to); // Replace with a valid phone number
smsParams.put("From", "(646) 755-7665"); // Replace with a valid phone // number in your account
smsParams.put("Body", _message);
smsFactory.create(smsParams);
// Make a raw request to the api.
TwilioRestResponse resp = client.request("/2010-04-01/Accounts", "GET",
null);
if (!resp.isError()) {
return resp.getResponseText();
}
else
{
return "Failed to send the message.";
}
}
}
When I ran the code in GAE, I got the following exception:
java.lang.NoClassDefFoundError: javax.net.ssl.KeyManagerFactory is a restricted class. Please see the Google App Engine developer's guide for more details.
I did realize that there is a gwt-twilio http://code.google.com/p/gwt-twilio/ but this is a wrapper for twilio client (which does not handle sending text message)
Any examples that send text messages using twilio in GAE+GWT are helpful!
Thanks
Kun
Twilio Java client library does not on GAE as it obviously uses some Java classes that are not present on GAE.
Since you can not use the Twilio client, your only option is to use GWT-RPC to call your method on server and this method further calls Twilio REST API.
I know this is an old one, but I'd like to share a bit more information if I can. As of January 2014, you can use the Twilio helper library for Java on App Engine if you choose. The Twilio Java library's underlying HTTP client implementation has been modified to run on App Engine.
Also, just to be clear, you should not attempt to use the Twilio helper library on the client side with GWT. The Twilio helper library will only work when the code is executed on the server.
If you want to send an SMS from an App Engine Java app, you will first need to sign up for a Twilio account. Once you have signed up for an account and have your Account SID and Auth Token (found on your dashboard), you can follow this guide in the Google App Engine documentation to set up and configure your environment to send a message.
If you run into any problems, please contact our support squad by e-mailing help#twilio.com.
Related
I need to form a POST to publish a Google PubSub message. I can't use the client libraries because they use gRPC which is incompatible with Google App Engine. I can form the critical POST request, but I'm not sure how to authenticate it using OAuth2.
This link shows what I'm doing, but it obscures the authentication part.
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/publish
(If GAE standard environment would support gRPC this would not matter.)
JSONObject obj = new JSONObject();
JSONArray attr = new JSONArray();
obj.put("script_name","foo_script.py");
obj.put("script_args","arg1");
attr.put(obj);
JSONObject jsontop = new JSONObject();
jsontop.put("messages",attr);
URL url = new URL("https://pubsub.googleapis.com/v1/projects/{my-URL}/topics/topic_run_script:publish");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
This code comes back "401 : UNAUTHENTICATED". How do I authenticate it?
App Engine has an API to fetch an access token that you can use to when calling Google services. For documentation and an example, see https://cloud.google.com/appengine/docs/standard/java/appidentity/#asserting_identity_to_google_apis
You might also be able to use the pubsub client library on GAE Std if you switch to the Java 8 environment. This doc implies that it should work.
I am providing a REST API via App Engine. I used Cloud Endpoints to generate it, although the client will not be mobile Android/iPhone but rather a known web server. Since I am familiar with this server (it is part of my application), I decided to use Service Account authorization in order to authorize the API calls (In addition, I will do IP validation, but that's beside the point).
I made all the necessary arrangement, created a Google developer project, generated a service account id (and email), with a p12 file, and added all the annotations needed on the server side (including a User object in the implementing function).
Now I want to implement a call to this API, and in order for it to work, I need to include a proper authorization header in my request.
When working with Google APIs, the client libraries generate some Credential object which you later need to pass in building some Service object, which represents a Google API you wish to call. For example, if you want to access Drive API in Java, you will do:
Drive drive = new Drive.Builder(Globals.httpTransport, Globals.jsonFactory, credential).build();
Where credential object is the object I previously build as follows:
credential = new GoogleCredential.Builder().setTransport(Globals.httpTransport)
.setJsonFactory(Globals.jsonFactory)
.setServiceAccountId(serviceAccountEmail)
.setServiceAccountScopes(scopes)
.setServiceAccountUser(serviceAccountUser)
.setServiceAccountPrivateKeyFromP12File(file(serviceAccountPrivateKeyP12File))
.build();
However, in my case, the client is not calling a Google API, but rather my App Engine REST API. How do I go about generating (or using the credential object I created to obtain) a proper Authorization header?
You can find some documentation in the readme.html file that is generated alongside the bindings, and here.
You can get the following account information in the console, "Apis & Auth", "Credentials". Here you need to paste "Email Address" of the service account. Your #Api annotation should include the account's "Client Id" in the "clientIds" parameter.
String accountEmail = "your-service-account#developer.gserviceaccount.com";
String keyFilePath = "your-key-file.p12";
This is the minimum authorization scope that is required for Cloud Endpoints API. It only allows the app to access the user's e-mail address. Your #Api annotation should list it in the "scopes" parameter.
String emailScope = "https://www.googleapis.com/auth/userinfo.email";
Then you need to create some support objects and the credential. GsonFactory can be replaced with JsonFactory if you prefer.
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory gsonFactory = new GsonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(gsonFactory)
.setServiceAccountId(accountEmail)
.setServiceAccountScopes(Collections.singleton(emailScope))
.setServiceAccountPrivateKeyFromP12File(new File(keyFilePath))
.build();
And finally create your API client. Replace YourApi with the client from the generated bindings. If you want to test against the dev AppServer, you can call .setRootUrl(yourDevServerUrl + "/_ah/api") on the builder.
YourApi client = new YourApi.Builder(httpTransport, gsonFactory, credential)
.setApplicationName("YourClientName")
.build();
I am trying to perform an external Http REST API callout using Apex Class from within my Salesforce Development Organization.
I was wondering if there is support for an equivalent HttpClient library like that of Apache Commons' HttpClient. Is there one?
From the documentation I realize that one way of doing it would be use the System.Http class to perform the request. Refer here for :Salesforce's System Classes and System.Http.
Example:
public class HttpCalloutSample {
// Pass in the endpoint to be used using the string url
public String getContent(String url) {
// Instantiate a new http object
Http h = new Http();
// Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod('GET');
// Send the request, and return a response
HttpResponse res = h.send(req);
return res.getBody();
}
}
The reason I am asking this question is because I remember running across a Apex Code Snippet from a tutorial that used such an API. I cant seem to find it now.
P.S: I understand the the Apex Code is a different language and Java libraries like the HttpClient do not run on the Salesforce platform. And there may not be direct language level way to integrate them both, unless there is a Apex Code binding to the library.
The System.HTTP class and friends is the only way to make HTTP requests from ApexCode. As you say apex is not java and you can't run random java libraries in apex.
The API is a backend to a mobile app. I don't need user authentication. I simply need a way to secure access to this API. Currently, my backend is exposed.
The documentation seems to only talk about user authentication and authorization, which is not what I need here. I just need to ensure only my mobile app can talk to this backend and no one else.
Yes, you can do that: use authentication to secure your endpoints without doing user authentication.
I have found that this way of doing it is not well documented, and I haven't actually done it myself, but I intend to so I paid attention when I saw it being discussed on some of the IO13 videos (I think that's where I saw it):
Here's my understanding of what's involved:
Create a Google API project (though this doesn't really involve their API's, other than authentication itself).
Create OATH client ID's that are tied to your app via its package name and the SHA1 fingerprint of the certificate that you will sign the app with.
You will add these client ID's to the list of acceptable ID's for your endpoints. You will add the User parameter to your endpoints, but it will be null since no user is specified.
#ApiMethod(
name = "sendInfo",
clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID },
audiences = { Config.WEB_CLIENT_ID }
// Yes, you specify a 'web' ID even if this isn't a Web client.
)
public void sendInfo(User user, Info greeting) {
There is some decent documentation about the above, here:
https://developers.google.com/appengine/docs/java/endpoints/auth
Your client app will specify these client ID's when formulating the endpoint service call. All the OATH details will get taken care of behind the scenes on your client device such that your client ID's are translated into authentication tokens.
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( ctx, Config.WEB_CLIENT_ID );
//credential.setSelectedAccountName( user ); // not specify a user
Myendpoint.Builder builder = new Myendpoint.Builder( transport, jsonFactory, credential );
This client code is just my best guess - sorry. If anyone else has a reference for exactly what the client code should look like then I too would be interested.
I'm sorry to say that Google doesn't provide a solution for your problem (which is my problem too).
You can use their API key mechanism (see https://developers.google.com/console/help/new/#usingkeys), but there is a huge hole in this strategy courtesy of Google's own API explorer (see https://developers.google.com/apis-explorer/#p/), which is a great development tool to test API's, but exposes all Cloud Endpoint API's, not just Google's services API's. This means anyone with the name of your project can browse and call your API at their leisure since the API explorer circumvents the API key security.
I found a workaround (based on bossylobster's great response to this post: Simple Access API (Developer Key) with Google Cloud Endpoint (Python) ), which is to pass a request field that is not part of the message request definition in your client API, and then read it in your API server. If you don't find the undocumented field, you raise an unauthorized exception. This will plug the hole created by the API explorer.
In iOS (which I'm using for my app), you add a property to each request class (the ones created by Google's API generator tool) like so:
#property (copy) NSString *hiddenProperty;
and set its value to a key that you choose. In your server code (python in my case) you check for its existence and barf if you don't see it or its not set to the value that your server and client will agree on:
mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
if mykey != 'my_supersecret_key':
raise endpoints.UnauthorizedException('No, you dont!')
Hope this puts you on the right track
The documentation is only for the client. What I need is documentation
on how to provide Service Account functionality on the server side.
This could mean a couple of different things, but I'd like to address what I think the question is asking. If you only want your service account to access your service, then you can just add the service account's clientId to your #Api/#ApiMethod annotations, build a GoogleCredential, and invoke your service as you normally would. Specifically...
In the google developer's console, create a new service account. This will create a .p12 file which is automatically downloaded. This is used by the client in the documentation you linked to. If you can't keep the .p12 secure, then this isn't much more secure than a password. I'm guessing that's why this isn't explicitly laid out in the Cloud Endpoints documentation.
You add the CLIENT ID displayed in the google developer's console to the clientIds in your #Api or #ApiMethod annotation
import com.google.appengine.api.users.User
#ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE },
clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" })
public void doIt(User user){ //by convention, add User parameter to existing params
// if no client id is passed or the oauth2 token doesn't
// match your clientId then user will be null and the dev server
// will print a warning message like this:
// WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed
//..
}
You build a client the same way you would with the unsecured version, the only difference being you create a GoogleCredential object to pass to your service's MyService.Builder.
HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish
JsonFactory jsonFactory = new JacksonFactory();
// assuming you put the .p12 for your service acccount
// (from the developer's console) on the classpath;
// when you deploy you'll have to figure out where you are really
// going to put this and load it in the appropriate manner
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12");
File p12file = new File(url.toURI());
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport);
credentialBuilder.setJsonFactory(jsonFactory);
//NOTE: use service account EMAIL (not client id)
credentialBuilder.setServiceAccountId("12345678901-12acg1ez8lf51spfl06lznd1dsasdfj#developer.gserviceaccount.com"); credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"));
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file);
GoogleCredential credential = credentialBuilder.build();
Now invoke your generated client the same way
you would the unsecured version, except the builder takes
our google credential from above as the last argument
MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");
final MyService service = builder.build();
// invoke service same as unsecured version
I have a simple web application hosted on tomcat-7 with single servlet. The aim of servlet is to create google channel and then request for a token on opened channel for a user. I have following configuration...
WEB-INF
-- lib
-- appengine-api-1.0-sdk-1.4.3.jar
-- classes
-- Gc.class
The source of Gc.java is...
import com.google.appengine.api.channel.*;
public class Gc extends HttpServlet {
protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("Creating channel...<br>");
ChannelService channelService = ChannelServiceFactory.getChannelService();
response.getWriter().write("Channel created!<br>");
response.getWriter().write("Getting token for user 'user1'...<br>");
String token = channelService.createChannel("user1");
response.getWriter().write("toekn => "+token);
}
}
But it gives me an following error...
type Exception report
*message* **The API package 'channel' or call 'CreateChannel()' was not found.**
*description* **The server encountered an internal error (The API package 'channel' or call 'CreateChannel()' was not found.) that prevented it from fulfilling this request.**
exception
com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'channel' or call 'CreateChannel()' was not found.
com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:98)
com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:50)
com.google.appengine.api.channel.ChannelServiceImpl.createChannel(ChannelServiceImpl.java:40)
webRtc.Gc.doGetOrPost(Gc.java:46)
webRtc.Gc.doGet(Gc.java:31)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
** Am I missing some libraries? If yes then which and where can I found those.**
Any help is really appreciated.
I got it!!!
The goal of my application is to create google channels and send messages on these channels.
I was under impression that, google channel API is an independent library and was tried to place relevant .jar in lib of my tomcat application.
But I was wrong. Google channel API libraries only works on Google AppEngine Server. And thus, any application needs to leverage these Google APIs must be hosted on Google AppEngine Server.
I am open to listen from experts, if I am wrong.