I'm connecting to a 3rd party web server from an HTTP client (Java or Dart - Android app) to download some resources (XML or IMG files) that belong to the current user on that server. This site requires login with Google Sing-In. I have everything set up in my Android app to login the user with Google, I obtained their authorization idToken. But how do actually use it in HTTP GET or POST methods to download the protected resources?
With BASIC authentication it's easy - just set HTTP 'Authorization' header correctly ("Basic " + user:password encoded as base64), call GET, and I download the desired resource. But I cannot find any information on how to do this with Google Sing-In. Do I send the idToken I received from Google in some headers? What other magic is needed?
Adding a Java code snippet, hope it helps:
// (Receive authCode via HTTPS POST)
if (request.getHeader('X-Requested-With') == null) {
// Without the `X-Requested-With` header, this request could be forged. Aborts.
}
// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.developers.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";
// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
REDIRECT_URI) // Specify the same redirect URI that you use with your web
// app. If you don't have a web version of your app, you can
// specify an empty string.
.execute();
String accessToken = tokenResponse.getAccessToken();
// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
.setApplicationName("Auth Code Exchange Demo")
.build();
File file = drive.files().get("appfolder").execute();
// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject(); // Use this value as a key to identify a user.
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
For detailed info, find all the required steps and references at: https://developers.google.com/identity/sign-in/web/server-side-flow#step_1_create_a_client_id_and_client_secret
Having built an app using PCL method in Xamarin and have had it working 100% using standard HTTP I now changed the remote test server to use SSL with self signed certs.
The app contacts a custom API for logging onto a server and querying for specific data.
I've changed the app to look at SSL now and initially got an error regarding Authentication not working or something but turned off SSL related errors for testing using:
ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
in my AppDelegate files FinishedLaunching method which got over that error.
I'm now getting a 404 / protocol error when trying to do my Login POST to the given URL.
I am using HttpWebRequest for my RESTful calls and this works fine if I change back to plain http.
Not sure why but some articles suggested using ModernHttpClient, which I did. I imported the component (also added the package using NuGet) to no avail.
Am I missing something else that I should be configuring in my code related to httpwebresponse when contacting the SSL server or is this component simply incapable of speaking to an SSL server?
My login function is as follows (Unrelated code removed/obfuscated):
public JsonUser postLogin(string csrfToken, string partnerId, string username, string password){
string userEndPoint = SingletonAppSettngs.Instance ().apiEndPoint;
userEndPoint = userEndPoint.Replace ("druid/", "");
var request = WebRequest.CreateHttp(string.Format(this.apiBaseUrl + userEndPoint + #"user/login.json"));
// Request header collection set up
request.ContentType = "application/json";
request.Headers.Add ("X-CSRF-Token", csrfToken);
// Add other configs
request.Method = "POST";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json_body_content = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}";
streamWriter.Write(json_body_content);
streamWriter.Flush();
streamWriter.Close();
}
try{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader (httpResponse.GetResponseStream ())) {
var content = reader.ReadToEnd ();
content = content.Replace ("[],", "null,");
content = content.Replace ("[]", "null");
if (content == null) {
throw new Exception ("request_post_login - content is NULL");
} else {
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.NullValueHandling = NullValueHandling.Ignore;
JsonUser deserializedUser = JsonConvert.DeserializeObject<JsonUser>(content, jss);
if(content.Contains ("Hire company admin user")){
deserializedUser.user.roles.__invalid_name__5 = "Hire company admin user";
deserializedUser.user.roles.__invalid_name__2 = "authenticated user";
}
return deserializedUser;
}
}
}catch(Exception httpEx){
Console.WriteLine ("httpEx Exception: " + httpEx.Message);
Console.WriteLine ("httpEx Inner Exception: " + httpEx.InnerException.Message);
JsonUser JsonUserError = new JsonUser ();
JsonUserError.ErrorMessage = "Error occured: " + httpEx.Message;
return JsonUserError;
}
}
When making a Web Request using ModernHttpClient, I generally follow the pattern below. Another great library created by Paul Betts is refit, and can be used to simplify rest calls.
using (var client = new HttpClient(new NativeMessageHandler(false, false)))
{
client.BaseAddress = new Uri(BaseUrl, UriKind.Absolute);
var result = await Refit.RestService.For<IRestApi>(client).GetData();
}
The second parameter for NativeMessageHandler should be set to true if using a customSSLVerification.
Here's a look at IRestApi
public interface IRestApi
{
[Get("/foo/bar")]
Task<Result> GetMovies();
}
Number of things I had to do to get this to work.
The Self Signed Cert had to allow TLS 1.2
As the API is Drupal based, HTTPS had to be enabled on the server and a module installed to manage the HTTP specific pages.
I am working on unity webgl build on our existing IOS running app. All the data about users are saving on Parse. I have implemented Rest API to communicate with Parse. Implemented Get and Post(without passing the method header) they are working fine but when i am trying to update the data using PUT :
string url = "https://api.parse.com/1/"
string ObjectID = "ERd99Q0kmd"
string CallLink = url + "classes/PlayerProfile/" + ObjectID ;
string jsonString = "{\"TotalCoins\":40}";
WWWForm form = new WWWForm();
var headers = form.headers;
headers["X-Parse-Application-Id"] = appID;
headers["X-Parse-REST-API-Key"] = restapikey;
headers["Content-Type"] = "application/json";
headers["Content-Length"] = jsonString.Length.ToString();
var encoding = new System.Text.UTF8Encoding();
WWW www = new WWW(CallLink,encoding.GetBytes(jsonString),headers);
yield return www;
if (www.error != null)
{
Debug.Log( "CallGet:Error:"+www.error);
}
else
{
Debug.Log("CallGet:Success:"+www.text);
}
It gives Bad Request error. I also tried the header "Method" it also give Bad Request but when i tried "X-HTTP-Method-Override" it works in unity editor but still it doesn't working in Browser and getting following Error :
Request header field X-HTTP-Method-Override is not allowed by
Access-Control-Allow-Headers in preflight response.
Please help me out how can i update the data.
I'm working on a C# VS2012 Framework 4.5 MVC application that is trying to become PCI compliant using Payflow Pro (https://pilot-payflowpro.paypal.com). We've been using PayflowPro for years, and this is what I have to use. From my reading it seems that I should use the Transparent Redirect so I'm not posting anything private to my webserver, though I don't know if I need that with how I'm hoping to handle this. I also have a few questions...
How I think this all works:
My understanding is that you need a securetoken (communication to Paypal, trip 1). Then you post the secure data (CC, exp, security code) including the securetoken (communication to Paypal, trip 2) and receive the authorization and transactionID of the sale.
How I'm hoping to do it:
I'm intending on having a form that will have all the info (user details, shipping details, and CC info), and when the user presses the purchase button, I'll use AJAX to process trip 1 to my server (no secure user info sent). Here I'll create the URL + params and send paypal my un/pw info to retrieve the token (all from my server). The response will be returned to the client and, if successful, I'll then directly communicate via AJAX to Paypal's Gateway server, this time sending the secure CC info + token (trip #2). Based on the response to trip #2, I'll let the user know what's up with their purchase. Trip 2 shouldn't need my Paypal UN/PW info as it could easily be see on the client, and I'm including the SecureToken which SHOULD identify the original transaction. From what I've explained I don't see a need for Transparent Redirect. Or am I missing something here?
Also, what Transaction Type do I want to use? Create an 'Authorization' for trip #1, then a 'Sale' for trip #2?
So here's the nitty gritty coding type stuff:
For my R&D testing I'm building my own name/value pair parameter string (see below) and communicating to the gateway server via WebRequest through their sandbox/test url (pilot-payflowpro.paypal.com). I do get a successful response and SECURETOKEN back. Initial request (shown below) for secure token is TRXTYPE = A (Authorization), no card info is sent. Do I want to authorize first?
Here are my parameters (might include shipto info as well, but it's not listed below):
USER=myAuthUserName
&VENDOR=myAuthUserName
&PARTNER=myPartner
&PWD=myPassword
&AMT=21.43
&BILLTOFIRSTNAME=FName
&BILLTOLASTNAME=LName
&BILLTOSTREET=123 Main Street
&BILLTOSTREET2=Apt 203B
&BILLTOCITY=MyCity
&BILLTOSTATE=CA
&BILLTOZIP=77777
&BILLTOPHONENUM=4444444444
&EMAIL=myemail#somedomain.com
&CURRENCY=USD
**&TRXTYPE=A**
&SILENTTRAN=TRUE
&CREATESECURETOKEN=Y
&SECURETOKENID=a99998afe2474b1b82c8214c0824df99
As I said, I get a successful response and move to the next step of sending the secure data (CC#, EXPDATE, security code). When I remove my UN/PW/VENDOR/Partner info from the params I get an error due to invalid user authentication. But, seeing I'm dynamically building this 2nd call I can't have my paypal un/pw there. What am I missing? Anyone offer assistance with this or the other questions from above?
Please let me know if I need any clarification to be added. Thanks in advance for your time!
After spending a bunch of time with a Paypal engineer I've successfully figured out a solution for the Paypal's Payflow Transparent Redirect without hosted pages (have own payment page). Again, here's the documentation which, per the engineer, is pretty confusing: Payflow API Documentation. Also, the code isn't optimized as it was just a R&D app, but as a whole, it is working for me. Just an example and explanation, and I'm sure there are better ways of doing individual steps. Hope this helps and allows you to bypass some of the roadblocks that have been slowing down your Paypal Payflow integration.
YES, it is PCI compliant in that no secure customer data will hit your own servers. Remember that PCI compliance is pretty complicated and involved but this is big part of it. Ok, so I'll explain what I did to make this work in a MVC C# environment. I'll explain the steps here, then include code below.
CLIENT: Client finishes adding items to the cart and presses BUY button. Javascript handles the button click, doesn't submit, and takes you to the next step.
CLIENT --> SERVER: AJAX function POSTS to server method to contact Paypal for the single-use secure token. This communication identifies YOU (the merchant) to paypal with your authentication, a unique transaction id (a guid), and non secure details about the transaction (total, billing info, shipping info, return URL details). This way, all your merchant personal acct info is secure (web server to Paypal).
SERVER --> CLIENT: From the transaction above you'll receive a parameter string that contains the secure token (among other stuff, see method with example). Using this piece of info, I dynamically create my url that I'll eventually need on the client for the transparent redirect part, and send the url string back to the client.
CLIENT: Using the url that was returned in step #3, I complete the URL by adding the needed credit card parameters using jQuery.
CLIENT --> PAYPAL: This is where I didn't understand what to do. While step #2 was a post, this step will be a REDIRECT. Sure, that seems appropriate seeing it's called 'transparent redirect', but that part just didn't make sense to me. So, once your entire URL is complete, you'll literally redirect the window to Paypal for processing your transaction.
PAYPAL --> SERVER: PayPal posts back to one of the URLs you included in step 2 (to a public method on one of my controllers), and I read the response object and parse the parameters.
Easy, right? Perhaps, but for me step 5 caused me big problems. I was using a POST and didn't understand why I kept getting errors on the response. It was an html page with something about an invalid merchant or authentication. Remember to redirect, not post for step #5.
CODE:
STEP 1: onclick attribute on button to call GetToken function.
STEP 2 and STEP 3:
client-side:
function GetToken() {
$.ajax({
url: '#Url.Action("GetToken", "MyController")',
type: 'POST',
cache: 'false',
contentType: 'application/json; charset=utf-8',
dataType: 'text',
success: function (data) {
// data is already formatted in parameter string
SendCCDetailsToPaypal(data);
},
//error:
//TODO Handle the BAD stuff
});}
Server Side:
I have separate methods used to build all the parameter values needed for the token request. First three build: authentication, transaction details, transparent redirect. I keep urls and payflow acct info in a web.config file. Last method, ProcessTokenTransaction, does all the heavy lifting to contact Paypal via WebRequest, and then parse it into the URL that will be sent back to the client. This method should be refactored for a cleaner delivery, but I'll leave that up to you. ParseResponse is a method that populates a simple model that I created, and returns that model.
URL for token (sandbox): https://pilot-payflowpro.paypal.com
THIS IS DIFFERENT THAN THE TOKEN URL!! Used in the PaypalTranactionAPI config value.
URL for transaction: (sandbox) https://pilot-payflowlink.paypal.com
private string PrepareApiAuthenticationParams()
{
var paypalUser = ConfigurationManager.AppSettings["PaypalUser"];
var paypalVendor = ConfigurationManager.AppSettings["PaypalVendor"];
var paypalPartner = ConfigurationManager.AppSettings["PaypalPartner"];
var paypalPw = ConfigurationManager.AppSettings["PaypalPwd"];
//var amount = (decimal)19.53;
var apiParams = #"USER=" + paypalUser
+ "&VENDOR=" + paypalVendor
+ "&PARTNER=" + paypalPartner
+ "&PWD=" + paypalPw
+ "&TENDER=C"
+ "&TRXTYPE=A"
+ "&VERBOSITY=HIGH";
// find more appropriate place for this param
//+ "&VERBOSITY=HIGH";
return apiParams;
}
private string PrepareTransactionParams(CustomerDetail detail)
{
var currencyType = "USD";
var transactionParams = #"&BILLTOFIRSTNAME=" + detail.FirstName
+ "&BILLTOLASTNAME=" + detail.LastName
+ "&BILLTOSTREET=" + detail.Address1
+ "&BILLTOSTREET2=" + detail.Address2
+ "&BILLTOCITY=" + detail.City
+ "&BILLTOSTATE=" + detail.State
//+ "&BILLTOCOUNTRY=" + detail.Country + // NEEDS 3 digit country code
+ "&BILLTOZIP=" + detail.Zip
+ "&BILLTOPHONENUM=" + detail.PhoneNum
+ "&EMAIL=" + detail.Email
+ "&CURRENCY=" + currencyType
+ "&AMT=" + GET_VALUE_FROM_DB
+ "&ERRORURL= " + HostUrl + "/Checkout/Error"
+ "&CANCELURL=" + HostUrl + "/Checkout/Cancel"
+ "&RETURNURL=" + HostUrl + "/Checkout/Success";
// ADD SHIPTO info for address validation
return transactionParams;
}
private string PrepareTransparentParams(string requestId, string transType)
{
var transparentParams = #"&TRXTYPE=" + transType +
"&SILENTTRAN=TRUE" +
"&CREATESECURETOKEN=Y" +
"&SECURETOKENID=" + requestId;
return transparentParams;
}
// Method to build parameter string, and create webrequest object
public string ProcessTokenTransaction()
{
var result = "RESULT=0"; // default failure response
var transactionType = "A";
var secureToken = string.Empty;
var requestId = Guid.NewGuid().ToString().Replace("-", string.Empty);
var baseUrl = ConfigurationManager.AppSettings["PaypalGatewayAPI"];
var apiAuthenticationParams = PrepareApiAuthenticationParams();
// Create url parameter name/value parameter string
var apiTransactionParams = PrepareTransactionParams(detail);
// PCI compliance, Create url parameter name/value parameter string specific to TRANSAPARENT PROCESSING
var transparentParams = PrepareTransparentParams(requestId, transactionType);
var url = baseUrl;
var parameters = apiAuthenticationParams + apiTransactionParams + transparentParams;
// base api url + required
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/name"; // Payflow?
request.Headers.Add("X-VPS-REQUEST-ID", requestId);
byte[] bytes = Encoding.UTF8.GetBytes(parameters);
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
try
{
// sample successful response
// RESULT=0&RESPMSG=Approved&SECURETOKEN=9pOyyUMAwRUWmmv9nMn7zhQ0h&SECURETOKENID=5e3c50a4c3d54ef8b412e358d24c8915
result = reader.ReadToEnd();
var token = ParseResponse(result, requestId, transactionType);
var transactionUrl = ConfigurationManager.AppSettings["PaypalTransactionAPI"];
secureToken = transactionUrl + "?SECURETOKEN=" + token.SecureToken + "&SECURETOKENID=" + requestId;
//ameValueCollection parsedParams = HttpUtility.ParseQueryString(result);
stream.Dispose();
reader.Dispose();
}
catch (WebException ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
finally { request.Abort(); }
return secureToken;
}
private TokenResponse ParseResponse(string response, string requestId, string transactionType)
{
var nameValues = HttpUtility.ParseQueryString(response);
int result = -999; // invalid result to guarantee failure
int.TryParse(nameValues.Get(TokenResponse.ResponseParameters.RESULT.ToString()), out result);
// retrieving response message
var responseMessage = nameValues.Get(TokenResponse.ResponseParameters.RESPMSG.ToString());
// retrieving token value, if any
var secureToken = nameValues.Get(TokenResponse.ResponseParameters.SECURETOKEN.ToString());
var reference = nameValues.Get(TokenResponse.ResponseParameters.PNREF.ToString());
var authCode = nameValues.Get(TokenResponse.ResponseParameters.AUTHCODE.ToString());
var cscMatch = nameValues.Get(TokenResponse.ResponseParameters.CSCMATCH.ToString());
// populating model with values
var tokenResponse = new TokenResponse
{
Result = result,
ResponseMessage = responseMessage,
SecureToken = secureToken,
TransactionIdentifierToken = requestId,
TransactionType = transactionType,
ReferenceCode = reference,
AuthorizationCode = authCode,
CSCMatch = cscMatch
};
return tokenResponse;
}
STEP 4 and STEP 5:
Back to Client Side:
Here I use the URL built from the previous steps and add the final needed params (secure credit card info) using jQuery and then REDIRECT to Paypal.
function SendCCDetailsToPaypal(secureParm) {
//alert('in SendCCDetailsToPaypal:' + secureParm);
var secureInfo = '&ACCT=' + $('#ccNumber').val() + '&EXPDATE=' + $("#expMonth").val() + $("#expYear").val() + "&CSC=" + $('#ccSecurityCode').val();
secureInfo = secureParm + secureInfo;
window.location.replace(secureInfo);
}
STEP 6:
Paypal will post back to one of the following methods: Cancel, Error, or Return (name the methods anything you want in the token request). Parse the Response and look at the variables returned from Paypal, particularly the RESULT and RESPMSG. Read the documentation for specifics as you can incorporate address validation and a bunch of other features. Based on the response, display what's appropriate.
server side:
public ActionResult Cancel()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
//return View("Return", result);
}
public ActionResult Error()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
return View("Return", result);
}
public ActionResult Return()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
return View("Return", result);
}
Hope this helps, and good luck! I'll answer clarification questions as I'm able. Thanks for checking this out, and remember to pay it forward.
I was able to use RichieMN's answer to get a working Transparent Redirect happening. However, the problem with doing a redirect with window.location.replace in the SendCCDetailsToPaypal function is that you're passing the data on a GET string.
This works on the PayFlow Gateway side, but when they send the customer's browser back to your ResponseURL, your Apache logs will show the whole payflowlink.paypal.com URL, including the GET string as the referrer in your Apache access logs! That GET string includes the Credit Card number and now you have just lost your PCI compliance!
To alleviate this problem, you can either put the SecureToken and SecureTokenID into your Credit Card entry form, and POST it directly to payflowlink.paypal.com, or you can rewrite the SendCCDetailsToPaypal function to build a form and submit it, like this:
function SendCCDetailsToPaypal() {
var parameters = {
"SECURETOKEN": secureToken,
"SECURETOKENID": secureTokenID,
"ACCT": $("#ccNumber").val(),
"EXPDATE": $("#expMonth").val() + $("#expYear").val(),
"CSC": $("#ccSecurityCode").val()
};
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", "https://pilot-payflowlink.paypal.com");
$.each(parameters, function(key, value) {
var field = $('<input></input>');
field.attr("type", "hidden");
field.attr("name", key);
field.attr("value", value);
form.append(field);
});
$(document.body).append(form);
form.submit();
}
Since that form transfers the data via POST, when your server gets the result POST back, the referrer does not contain any sensitive data, and your PCI compliance is maintained.
I am accessing Pinterest API for getting user's information by using this url but I can not find that how to generate an access token for Pinterest.
According to this blog post, it says that
Pinterest uses OAuth2 to authenticate users
Can you please tell me, from where I can generate OAuth access tokens for Pinterest?
First, register for an app and set up a redirect URI:
https://developers.pinterest.com/manage/
Then, find your client secret under Signature Tester:
https://developers.pinterest.com/tools/signature/
Bring the user to the OAuth dialog like this:
https://www.pinterest.com/oauth/?consumer_id=[client_id]&response_type=[code_or_token]&scope=[list_of_scopes]
If response type if token, it will be appended as a hash in the redirect URI.
If response type is code, see the post below for details on how to exchange code for token:
What's the auth code endpoint in Pinterest?
You need to register a client app under manager Apps option in Dropdown menu when you login
or
https://developers.pinterest.com/manage/
Register your app and you get AppID.
This follow the process in this link you have
http://wiki.gic.mx/pinterest-developers/
Hope this helps
**USING C#**
public string GetOAuthToken(string data)
{
string strResult = string.Empty;
try
{
string Clientid = WebConfigurationManager.AppSettings["Pinterest_Clientid"];
string ClientSecret = WebConfigurationManager.AppSettings["Pinterest_ClientSecret"];
string uri_token = WebConfigurationManager.AppSettings["Pinterest_Uri_Token"];
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri_token);
string parameters = "grant_type=authorization_code"
+ "&client_id="
+ Clientid
+ "&client_secret="
+ ClientSecret
+ "&code="
+ data;
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(parameters);
System.IO.Stream os = null;
req.ContentLength = bytes.Length;
os = req.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
System.Net.WebResponse webResponse = req.GetResponse();
System.IO.Stream stream = webResponse.GetResponseStream();
System.IO.StreamReader reader = new System.IO.StreamReader(stream);
string response = reader.ReadToEnd();
Newtonsoft.Json.Linq.JObject o = Newtonsoft.Json.Linq.JObject.Parse(response);
strResult = "SUCCESS:" + o["access_token"].ToString();
}
catch (Exception ex)
{
strResult = "ERROR:" + ex.Message.ToString();
}
return strResult;
}
Refer
Pinterest uses the User Flow or Oauth2
When you have an app you ant to use the app flow with an access token
So you need to create the flow yourself or use this tool online
https://frederik.today/codehelper/tools/oauth-access-token-pinterest
To make it yourself
Request Token
Exchange code for Acces Token
https://developers.pinterest.com/docs/api/v5/