I am a salesforce developer, our company are planning to extend the service for global users, so we decided to use google translate to improve our customers' experience.
I have read the google api document, however, we met an issue when requesting GCP access token, the tutorial google provided in document which supports different languages, like java, c#, python etc. Since we are suing apex (a type of salesforce platform script), we weren't able to use your library to get GCP token.
Instead, we also checked "OAuth 2.0 for Server Accounts", unfortunately, neither worked from me.
Is there any suggestions?
I got token by below code, and the error I met was caused by special characters encode.
public with sharing class SwitchLanguageByGoogleAPIController {
private static final String ENDPOINT = '**';
private static final String TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token';
private static final String SCOPE = 'https://www.googleapis.com/auth/cloud-platform';
private static final String PROJECT_ID = '**';
private static final String GLOSSARY_ID = '88';
private static final String LOCATION_ID = 'us-central1';
private static final String CLIENT_SECRET = '**';
private static final String PRIVATE_KEY = '**';
private static final String CLIENT_EMAIL = '**';
public static void translateByGlossary() {
Token token = getToken();
HttpRequest request = new HttpRequest();
request.setHeader('Content-Type', 'text/plain');
request.setEndpoint(ENDPOINT + PROJECT_ID + '/locations/' + LOCATION_ID + ':translateText?access_token=' + token.access_token);
request.setMethod('POST');
String contents = 'Personal Information, Middle Name e, first First Name';
String sourceLanguageCode = 'en';
String targetLanguageCode = 'zh';
request.setBody('{"sourceLanguageCode":"' + sourceLanguageCode + '","targetLanguageCode":"' + targetLanguageCode + '","contents":"'+ contents +'","glossaryConfig":{"glossary":"projects/' + PROJECT_ID +'/locations/' + LOCATION_ID + '/glossaries/' + GLOSSARY_ID + '"}}');
HTTP http = new HTTP();
HttpResponse reponse = http.send(request);
System.debug(reponse.getBody());
}
private static Token getToken() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
//Making the call out
req.setEndpoint(TOKEN_ENDPOINT);
req.setMethod('POST');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
string URLEncodedGrantType = encodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer','UTF-8');
string jwtSigned = generateJWT();
req.setBody('grant_type='+URLEncodedGrantType+'&assertion='+jwtSigned);
res = http.send(req);
system.debug('Response : '+res.getBody());
return (Token)JSON.deserialize(res.getBody(), Token.Class);
}
private static String generateJWT() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
String JWTHeader = '{"typ":"JWT","alg":"RS256"}';
String Base64EncodedJWTHeader = EncodingUtil.base64Encode(Blob.valueOf(JWTHeader));
long issued_at = datetime.now().getTime()/1000;
long expires_at = datetime.now().addHours(1).getTime()/1000;
JWTClaimSet claimSet = new JWTClaimSet();
claimSet.iss = CLIENT_EMAIL;
claimSet.scope = SCOPE;
claimSet.aud = TOKEN_ENDPOINT;
claimSet.iat = issued_at;
claimSet.exp = expires_at;
String strClaimSetJSON = JSON.Serialize(claimSet);
String Base64EncodedClaimset = EncodingUtil.base64Encode(Blob.valueOf(strClaimSetJSON));
system.debug('Base64 Encoded Claimset::'+Base64EncodedClaimset);
Base64EncodedClaimset = PerformPostBase64Encode(Base64EncodedClaimset);
system.debug('persorm post Claimset::'+Base64EncodedClaimset);
string Base64EncodedString = Base64EncodedJWTHeader + '.' + Base64EncodedClaimset;
String algorithmName = 'RSA-SHA256';
Blob privateKey = EncodingUtil.base64Decode(PRIVATE_KEY);
Blob input = Blob.valueOf(Base64EncodedString);
Blob Blobsign = Crypto.sign(algorithmName, input , privateKey);
String base64EncodedSignature = EncodingUtil.base64Encode(Blobsign);
base64EncodedSignature = PerformPostBase64Encode(base64EncodedSignature);
system.debug('Base 64 encoded signature ::'+base64EncodedSignature );
system.debug('Encoded assertion : ' + Base64EncodedString+'.'+base64EncodedSignature);
string URLEncodedUTF8Assertion = encodingUtil.urlEncode(Base64EncodedString+'.'+base64EncodedSignature,'UTF-8');
return URLEncodedUTF8Assertion;
}
public static String PerformPostBase64Encode(String s)
{
s = s.Replace('+', '-');
s = s.Replace('/', '_');
s = s.Split('=')[0];
return s;
}
public class JWTClaimSet
{
public string iss {get;set;}
public string scope {get;set;}
public string aud {get;set;}
public Long exp {get;set;}
public Long iat {get;set;}
}
private class Token{
private String access_token;
private String token_type;
private String expires_in;
}
}
Related
I have an app that allows users to log in via facebook, once user enters their credentials - My api request saves the user onto the database and auto-generates a user token(This is unique to each user). In order to display user specific details once user logs in - the token needs to be referenced. I am trying to get this token to the PCL project but it returns null just for the token. When I tried passing another string like name, it passes the correct value. Any help will be much appreciated.Thanks
FacebookRender in droid:
public class FacebookRender : PageRenderer
{
public FacebookRender()
{
CustomerService customerService = new CustomerService();
String error;
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "",
scope: "",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
try
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me?fields=email,first_name,last_name,gender,picture"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["first_name"].ToString().Replace("\"", "");
var surname = obj["last_name"].ToString().Replace("\"", "");
var gender = obj["gender"].ToString().Replace("\"", "");
//var email = obj["email"].ToString().Replace("\"", "");
Customer.Customers cust = new Customer.Customers();
cust.Credentials = new Customer.Credentials();
cust.Name = name;
cust.Surname = surname;
cust.Email = "";
cust.MobilePhone = "";
cust.DOB = DateTime.Now;
cust.Number = "";
cust.City = "";
cust.Region = "";
cust.Country = "";
cust.DeviceToken = "sample";
cust.Credentials.SecretKey = "";
await customerService.AddCustomer(cust);
App.SaveToken(cust.Credentials.Token); - **//This is where I am passing the token**
App.NavigateToProfile(string.Format(name + surname));
}
else
{
App.NavigateToProfile("Invalid Login");
}
}
catch(Exception ex)
{
error = ex.Message;
}
};
activity.StartActivity(auth.GetUI(activity));
}
App.cs
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
public static void NavigateToProfile(string message)
{
App.Current.MainPage = (new Profile(message));
}
static string _Token;
public static string Token
{
get { return _Token; }
}
public static void SaveToken(string token)
{
_Token = token;
}
AboutPage.cs - I am passing the token in a label just to see if it's passing
public partial class About : ContentPage
{
private Label _lbltoken;
public About()
{
//InitializeComponent();
Appearing += (object s, EventArgs a) => {
_lbltoken.Text = App.Token;
};
string tk = App.Token;
_lbltoken = new Label()
{
FontSize = 20,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Text = tk,
};
var stack = new StackLayout
{
VerticalOptions = LayoutOptions.StartAndExpand,
Children = { _lbltoken },
};
Content = stack;
}
}
You can use the MessagingCenter.
Messages may be sent as a result like a button click, a system event or some other incident. Subscribers might be listening in order to change the appearance of the user interface, save data or trigger some other operation.
More Info
I don't really now if its good idea use static fields in App class. Xamarin access all fields with service locator, App.Current.[property] I will suggest you try to change these fields to public
string _Token;
public string Token
{
get { return _Token; }
}
public void SaveToken(string token)
{
_Token = token;
}
and use it with App.Current.SaveToken(token) or App.Current.Token
I am having trouble fetching result from my amazon elastic search cluster using the amazon java SDK and an IAm user credential. Now the issue is that when the PATH string is equal to "/" then I am able to fetch the result correctly but when I try with a different path for e.g "/private-search" then I get a 403 forbidden error. Even when for the path that has public access I am getting a 403 forbidden error for this IAm user but it works if I remove "signer.sign(requestToSign, credentials);" line in performSigningSteps method(for public resource only).
My policy in AWS gives this IAM user access to everything in my elastic search service. And also what can I do to avoid hard-coding the access key and secret key in source code?
private static final String SERVICE_NAME = "es";
private static final String REGION = "region-name";
private static final String HOST = "host-name";
private static final String ENDPOINT_ROOT = "http://" + HOST;
private static final String PATH = "/private-search";
private static final String ENDPOINT = ENDPOINT_ROOT + PATH;
private static String accessKey = "IAmUserAccesskey"
private static String secretKey = "IAmUserSecretkey"
public static void main(String[] args) {
// Generate the request
Request<?> request = generateRequest();
// Perform Signature Version 4 signing
performSigningSteps(request);
// Send the request to the server
sendRequest(request);
}
private static Request<?> generateRequest() {
Request<?> request = new DefaultRequest<Void>(SERVICE_NAME);
request.setContent(new ByteArrayInputStream("".getBytes()));
request.setEndpoint(URI.create(ENDPOINT));
request.setHttpMethod(HttpMethodName.GET);
return request;
}
private static void performSigningSteps(Request<?> requestToSign) {
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(requestToSign.getServiceName());
signer.setRegionName(REGION);
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
signer.sign(requestToSign, credentials);
}
private static void sendRequest(Request<?> request) {
ExecutionContext context = new ExecutionContext();
ClientConfiguration clientConfiguration = new ClientConfiguration();
AmazonHttpClient client = new AmazonHttpClient(clientConfiguration);
MyHttpResponseHandler<Void> responseHandler = new MyHttpResponseHandler<Void>();
MyErrorHandler errorHandler = new MyErrorHandler();
Void response = client.execute(request, responseHandler, errorHandler, context);
}
public static class MyHttpResponseHandler<T> implements HttpResponseHandler<AmazonWebServiceResponse<T>> {
#Override
public AmazonWebServiceResponse<T> handle(com.amazonaws.http.HttpResponse response) throws Exception {
InputStream responseStream = response.getContent();
String responseString = convertStreamToString(responseStream);
System.out.println(responseString);
AmazonWebServiceResponse<T> awsResponse = new AmazonWebServiceResponse<T>();
return awsResponse;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static class MyErrorHandler implements HttpResponseHandler<AmazonServiceException> {
#Override
public AmazonServiceException handle(com.amazonaws.http.HttpResponse response) throws Exception {
System.out.println("In exception handler!");
AmazonServiceException ase = new AmazonServiceException("exception.");
ase.setStatusCode(response.getStatusCode());
ase.setErrorCode(response.getStatusText());
return ase;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static String convertStreamToString(InputStream is) throws IOException {
// To convert the InputStream to String we use the
// Reader.read(char[] buffer) method. We iterate until the
// Reader return -1 which means there's no more data to
// read. We use the StringWriter class to produce the string.
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
}
finally {
is.close();
}
return writer.toString();
}
return "";
}
I have an Email Web Service - working ok - and now I need to add attachment.
1.How do I write the #FormParam in my post method to receive byte[] ?
2.How do I write my bean the addParam to add the file?
My bean is like this:
public String sendEmail() throws IOException{
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest req = (HttpServletRequest) context.getExternalContext().getRequest();
String ip = req.getRemoteAddr();
String conteudo = "é ô ç $ & / { [";
List<byte[]> att = new ArrayList<byte[]>();
String request = "myURI";
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(request);
method.getParams().setContentCharset("utf-8");
method.addParameter("conteudo", conteudo);
method.addParameter("ip", ip);
return "sendEmail ok";
}
My POST Method is like this:
#POST
#Path("/sendEmail")
#Consumes({"application/json","application/x-www-form-urlencoded",})
public String sEmail(#FormParam("conteudo") String conteudo, #FormParam("ip") String ip)throws MessagingException {
String de = "de#mail.com.br";
String para = "para#rmail.com.br";
String cc = "";
String cco = "";
String titulo = "Email test";
String conteudo = "conteudo";
try {
Email email = new SimpleEmail();
email.setHostName("smtp....");
email.setSmtpPort(25);
email.setStartTLSEnabled(true);
email.setFrom(de);
email.addTo(para);
email.setSubject(titulo);
email.setMsg(conteudo);
if (!cc.equals("")){
email.addCc(cc);
}
if (!cco.equals("")){
email.addBcc(cco);
}
email.send();
} catch (EmailException e) {
Logger.getLogger(Mail.class.getName()).log(Level.SEVERE, null, e.getMessage());
}
I use JavaMail 1.4.
I encoded to base64, then I put all the files into a String separated with ;
In the web service first I split the String and then I decoded from base64.
I am trying to grasp how Play framework handles its web service calls.
This is Foursquare's directions (after 1 and 2):
Your server will make a request for
https://foursquare.com/oauth2/access_token
?client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&grant_type=authorization_code
&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
&code=CODE
The response will be JSON
{ access_token: ACCESS_TOKEN }
And this is my code:
public static Result index() {
String base = "http://foursquare.com/oauth2/authenticate";
String clientId = "?client_id=***";
String responseType = "&response_type=code";
String redirectUri = "&redirect_uri=http://localhost:9000/code";
return redirect(base + clientId + responseType + redirectUri);
}
public static Result code() {
String base = "http://foursquare.com/oauth2/access_token";
String clientId = "?client_id=***";
String clientsecret = "&client_secret=***";
String grantType = "&grant_type=authorization_code";
String redirectUri = "&redirect_uri=http://localhost:9000/json";
String code = "&code=" + request().getQueryString("code");
return redirect(base + clientId + clientsecret + grantType
+ redirectUri + code);
}
There are two things I am curios about:
1) I am redirected to a page with the access token displayed on screen:
URL: https://foursquare.com/oauth2/access_token?client_id=***&client_secret=***&grant_type=authorization_code&redirect_uri=http://localhost:9000/json&code=***
With this displayed:
{"access_token":"***"}
I would have expected to be redirected to http://localhost:9000/json as that was the redirect uri...
2) How do I grab the access token? I have tried using the asynchronous web service calls vis http://www.playframework.com/documentation/2.2.x/JavaWS but I cannot make them work.
My attempt:
String feedUrl = base + clientId + clientsecret + grantType
+ redirectUri + code;
final Promise<Result> resultPromise = WS.url(feedUrl).get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok("Feed title:" + response.asJson().findPath("access_token").asText());
}
}
);
return resultPromise;
This gives me an exception: [ConnectException: Connection refused: no further information: foursquare.com/107.23.103.139:80 to http://foursquare.com/oauth2/access_token]
All help is appreciated greatly!
This is the class that I made to get the foursquare access_token and submit a new search to foursquare:
public class Application extends Controller {
static final String HOST_AUTHENTICATE = "foursquare.com/oauth2/authenticate";
static final String HOST_ACCESS_TOKEN = "https://www.foursquare.com/oauth2/access_token";
static final String CLIENT_ID = "***";
static final String REDIRECT_URI = "http://localhost:9000/code";
static final String CLIENT_SECRET = "***";
static final String GRANT_TYPE = "authorization_code";
static final String RESPONSE_TYPE = "code";
static final String FOURSQUARE_API_FRIENDS = "https://api.foursquare.com/v2/users/self/friends";
public static Result index() {
String uri = new URIBuilder().setScheme("https").setHost(HOST_AUTHENTICATE)
.setParameter("client_id", CLIENT_ID).setParameter("response_type", RESPONSE_TYPE)
.setParameter("redirect_uri", REDIRECT_URI).toString();
return redirect(uri);
}
public static Promise<Result> code() {
WSRequestHolder authenticate = WS.url(HOST_ACCESS_TOKEN).setQueryParameter("client_id", CLIENT_ID)
.setQueryParameter("client_secret", CLIENT_SECRET).setQueryParameter("grant_type", GRANT_TYPE)
.setQueryParameter("redirect_uri", REDIRECT_URI)
.setQueryParameter("code", request().getQueryString("code").toString());
final Promise<Result> resultPromise = authenticate.get().flatMap(new Function<WS.Response, Promise<Result>>() {
public Promise<Result> apply(WS.Response response) {
JsonNode json = response.asJson();
return WS.url(FOURSQUARE_API_FRIENDS).setQueryParameter("oauth_token", json.findPath("access_token").asText())
.setQueryParameter("v", "20131108").get().map(new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asJson());
}
});
}
});
return resultPromise;
}
}
I've roughly followed this example but it doesnt solve my Sitecore-related redirect problem.
sitecore web form for marketers form post to external url
I've confirmed that my form POST works properly by using a 3rd party POST test tool. The problem I'm having is that in Sitecore they use a successMode to determine what the user wants todo if the submit is a success. If the user selects successmode/message, the form redirects back to a thank you message. If the user selects successmode/redirect, the success method pipeline looks for the success page value in the form and then a redirect happens to that URL. The problem with the redirect is that it loses my POST data.
Can anyone provide a Sitecore example of how they executed a form POST, and then redirect to the target external URL without losing POST values?
Did you use the successmode settings in the form?
I'm debating whether to overrride the successmode redirect pipeline, add conditions and test but I'm open to a solution that could include jquery.
Here's is my code:
using Sitecore.Data;
using Sitecore.Form.Core.Client.Data.Submit;
using Sitecore.Form.Core.Controls.Data;
using Sitecore.Form.Submit;
using System.Web;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Text;
using Sitecore.Forms.Core.Data;
using Sitecore.Form.Core.Configuration;
using Sitecore.Forms.Core.Crm;
using System;
using System.IO;
using System.Net;
using Sitecore.Diagnostics;
using System.Text;
namespace XXXWffmExternals
{
public class Redirect : ISaveAction
{
UrlString url = new UrlString("https://XXX.XXX/default.asp");
public virtual void Execute(ID formid, AdaptedResultList fields, params object[] data)
{
String strResult = "";
strResult = setPost(url.ToString(), fields);
}
public String setPost(string url, AdaptedResultList fieldListForPOST)
{
String resultReturn = "";
AdaptedControlResult firstname = fieldListForPOST.GetEntry(this.First_Name, "First_Name");
AdaptedControlResult lastname = fieldListForPOST.GetEntry(this.Last_Name, "Last_Name");
AdaptedControlResult billingaddress = fieldListForPOST.GetEntry(this.Billing_Address, "Billing_Address");
AdaptedControlResult billingcity = fieldListForPOST.GetEntry(this.Billing_City, "Billing_City");
AdaptedControlResult billingstate = fieldListForPOST.GetEntry(this.Billing_State, "Billing_State");
AdaptedControlResult billingzip = fieldListForPOST.GetEntry(this.Billing_Zip, "Billing_Zip");
AdaptedControlResult billingphone = fieldListForPOST.GetEntry(this.Billing_Phone, "Billing_Phone");
AdaptedControlResult email = fieldListForPOST.GetEntry(this.Email, "Email");
AdaptedControlResult amount = fieldListForPOST.GetEntry(this.Amount, "Amount");
AdaptedControlResult desc = fieldListForPOST.GetEntry(this.Description, "Description");
AdaptedControlResult login = fieldListForPOST.GetEntry(this.Login, "Login");
AdaptedControlResult acct = fieldListForPOST.GetEntry(this.Account, "Account");
AdaptedControlResult fund = fieldListForPOST.GetEntry(this.Fund, "Fund");
AdaptedControlResult org = fieldListForPOST.GetEntry(this.Org, "Org");
AdaptedControlResult source_code = fieldListForPOST.GetEntry(this.Source_Code, "Source_Code");
String post =
"First_Name=" + firstname.Value +
"&Last_Name=" + lastname.Value +
"&Billing_Address=" + billingaddress.Value +
"&Billing_City=" + billingcity.Value +
"&Billing_State=" + billingstate.Value +
"&Billing_Zip=" + billingzip.Value +
"&Billing_Phone=" + billingphone.Value +
"&Email=" + email.Value +
"&Amount=" + amount.Value +
"&Description=" + desc.Value +
"&Login=" + login.Value +
"&Account=" + acct.Value +
"&Fund=" + fund.Value +
"&Org=" + org.Value +
"&Invoice_Num=" + "DVXXXX";
resultReturn = sendPost(url.ToString(), post);
return resultReturn;
}
public String sendPost(string url, string post)
{
String result = "";
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
// Set credentials to use for this request.
objRequest.Credentials = CredentialCache.DefaultCredentials;
// Convert POST data to a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(post);
// Set the ContentLength property of the WebRequest.
objRequest.ContentLength = byteArray.Length;
// Set the ContentType property of the WebRequest.
objRequest.ContentType = "application/x-www-form-urlencoded";
// Get the request stream.
Stream dataStream = objRequest.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = objRequest.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream ();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader (dataStream);
// Read the content.
result = reader.ReadToEnd ();
// Clean up the streams.
reader.Close ();
dataStream.Close ();
response.Close ();
return result;
}
public string First_Name { get; set; }
public string Last_Name { get; set; }
public string Billing_Address { get; set; }
public string Billing_City { get; set; }
public string Billing_State { get; set; }
public string Billing_Zip { get; set; }
public string Billing_Phone { get; set; }
public string Email { get; set; }
public string Amount { get; set; }
public string Description { get; set; }
public string Login { get; set; }
public string Account { get; set; }
public string Fund { get; set; }
public string Org { get; set; }
public string Invoice_Num { get; set; }
public string Source_Code { get; set; }
}
}
Why do you want to use WFFM for the form if you don't want to invoke any of the WFFM functionality? The point of WFFM is to allow marking people to create their own forms without any Developer input. You're having to edit all the post data in your code which pretty much eliminates the ability for anyone to edit the form without developer input. I'd say, if you're going to go through the process of writing all the code to submit your code by hand, you can use a Sitecore item to create the form and then use your own code for processing. Skip WFFM. It's a lot more work to do things as you suggested than to just manually create a form.
If you really need any WFFM end functionality, you can easily call them... it's still way easier than trying to override WFFM base functionality to inject your own functionality.