I am creating a simple web page, that make use of the Google Translation Service.
The page has a field, to receive the input from the user and a button to trigger the call to the Translation API. It returns the result translation to the user.
I've successfully done the flow above using Ajax requests, but the access token
is hard-coded into my method and I want to change that to a call that gets sent whenever the token expires (currently I have to request a new token using the Google CLI and replace it in my code).
I have a very basic knowledge of Oauth2.0 and I've read the Google Documentation but couldn't find a part of it that would tell me the endpoint to call to get an access token from the client-side.
Could someone point me in the right direction, please?
Here is my code:
HTML:
<form id="translate_form">
<input id="input" />
<button id="translate_button">Translate</button>
</form>
Javascript
$("#translate_form").submit(function () {
var text = $("#input").val()
sendTranslationRequest(text);
return false;
})
function sendTranslationRequest(inputText) {
var requestBody = {
q: inputText,
source: "en",
target: "fr",
format: 'text'
}
translationAjaxRequest(requestBody);
}
function translationAjaxRequest(requestBody) {
var access_token = [access_token]
$.ajax({
url: "https://translation.googleapis.com/language/translate/v2",
method: "POST",
contentType: "application/json",
beforeSend: function (request) {
request.setRequestHeader("Authorization", "Bearer " + access_token)
},
data: JSON.stringify(requestBody),
success: function (response) {
var translatedText = response.data.translations[0].translatedText
alert(translatedText)
},
error: function () {
console.log("An error occurred on the request:", response)
}
});
}
The relevant endpoints to get an access token and refresh it are:
https://accounts.google.com/o/oauth2/v2/auth
https://www.googleapis.com/oauth2/v4/token
However, you’ll need to perform several steps in order to get an access token and a refresh token. You may want to review this guide on Using OAuth2.0 for Web Server Applications. It will walk you through the prerequisites, obtaining an access token and refreshing your token.
Alternatively, you may use an API Key. Just be mindful of the recommendations on how to secure it, since a stolen API Key may be used to generate calls that would be charged directly to your billing account.
Related
I have a webapp that its backend is written in Python and renders some html for the frontend users.
What I would like to achieve is:
when a user makes a POST request to /token, the backend replies with a JSON document {"access_token": access_token, "token_type": "bearer"}; this is already in place
after the above takes place, every subsequent request / navigation to the webapp, should set a header named Authorization equal to Bearer <access_token> to every GET, POST, etc. request that it does; not important for the time being
can you advise and describe how to maintain a single variable client-side called access_token that its default value is null, but when doing POST to /token, then the variable access_token is initialised and never changes through navigation, unless the end user makes another POST request to /token again to reset the access_token to the new value ?
I am not familiar with jQuery or javascript much. Can you suggest how to initialise, set, reset a variable (and just print it, for example, using console.log) based on the background information above ?
You can store the token in local storage, or in cookies, either would work. Then, when you go to make an ajax call, you'll retrieve the value from whichever you used, and add it to the outgoing ajax request. How exactly you do that willl depend on what specific ajax implementation you use. For example google "add auth token to jquery.ajax" and you'll find the right syntax for that library
Something like this would work:
// do initial login and get token
var token = response.access_token;
// store it in local storage
localStorage.setItem('apiKey', token);
// ... navigate around and what not...
// later, when you need to make another call, get the token
var token = localStorage.getItem('apiKey');
$.ajax({
url: url,
method: "POST",
dataType: "json",
//.. other props as needed...
beforeSend: function (xhr) {
/* set the Authorization header with the token */
xhr.setRequestHeader("Authorization", "Bearer " + token);
},
success: function (data) {
// do something cool with data
},
error: function (jqXHR, textStatus, errorThrown) {
// handle errors ...
}
});
I am really struggling to get a successful response when doing a post request to the google recaptcha api. I am receiving the following response:
{
"success": false,
"error-codes": [
"invalid-input-response",
"invalid-input-secret"
]
}
I had a look at reCAPTCHA - error-codes: 'missing-input-response', 'missing-input-secret' when verifying user's response (missing details on POST) and followed the answer as closely as possible but with no success.
Here is my file below:
var request = require('request');
module.exports = {
verifyCaptcha: function(req, res) {
var secret = 'SECRET_KEY';
var response = JSON.stringify(req.body.response);
request({
url: 'https://www.google.com/recaptcha/api/siteverify',
method: 'POST',
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `secret=${secret}&response=${response}`,
}, function (err, response, body) {
if (err) {
res.status(500).send({
error: "Could not verify captcha"
});
} else {
res.status(200).send({
message: body
});
}
});
},
}
If anyone has a solution to this problem please let me know!
Due to the docs: https://developers.google.com/recaptcha/docs/verify
invalid-input-secret: The secret parameter is invalid or malformed.
Maybe you have mixed the site_key and the secret_key.
You need to add the user remote IP address.
var user_ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
request({
url: 'https://www.google.com/recaptcha/api/siteverify',
method: 'POST',
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `secret=${secret}&response=${response}&remoteip=${user_ip}`}...
Another thing I see that you are not using template literal, you should change the quotes to ` instead of '.
OR, You should use a ready-made module for reCaptcha, like this one:
https://www.npmjs.com/package/recaptcha
For reCAPTCHA Enterprise, check the official docs: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment.
In short, you need to use the library that Google provides:
const { RecaptchaEnterpriseServiceClient } =
require('#google-cloud/recaptcha-enterprise');
const client = new RecaptchaEnterpriseServiceClient();
const [ response ] = await client.createAssessment({...});
RecaptchaEnterpriseServiceClient requires a service account to be created beforehand as described here. The key for that account with the right roles set can then be read by the app. Check the arguments of the constructor to see the available options to pass the data if the file cannot be retrieved automatically.
var response = JSON.stringify(req.body.response);
The stringifying here is probably the cause of the invalid-input-response error.
If your body is something like {"g-recaptcha-response": "..."}, you need to pull out the response value and pass that directly in your post.
Regarding invalid-input-secret, if you have set up your key and secret through the classic interface at https://www.google.com/u/1/recaptcha/admin/create, then you shouldn't have a problem.However if you set up a key with recaptcha Enterprise on Google Cloud, then it requires that you do Oauth authentication to the Google Cloud API and then use the create.assessment endpoint to get back information on the validity of the user. As Yuuhn implied, the Google provided library makes interaction with recaptcha Enterprise easier, without a lot of documentation digging to find where your REST API calls need to go.
It's so simple:
OAuth protocol for authentication
list files from documentLibrary and checkout a file from the list
written in javascript
I've been struggling with this for few days with no such luck so far.
CHECKOUT OPTION 1 - Graph API:
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_checkout
Even though it's OneDrive API, it's should be running with SharePoint doc.libraries as well - RESt APIs section: "The REST API is shared between OneDrive, OneDrive for Business, SharePoint document libraries, and Office Groups, to allow... "
The result? check it out here: Sharepoint `Unsupported segment type` when checkin/chekout file
Good news the OAuth works like a charm - I got the client ID from https://apps.dev.microsoft.com/, authentication endpoint:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
https://login.microsoftonline.com/common/oauth2/v2.0/token
CHECKOUT OPTION 2 - Sharepoint Add-in
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
url: http://site url/_api/web/GetFileByServerRelativeUrl('/Folder Name/file name')/CheckOut(),
method: POST
headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
This one works perfectly, but in this case, OAuth is the issue ...
this link is promising:
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/authorization-code-oauth-flow-for-sharepoint-add-ins
however, in the process, there is the Microsoft Azure Access Control Service (ACS) involved, which is (according to this link https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-acs-migration) about to switch off.
Solution seems to be is a switch to Azure application (https://portal.azure.com -> Azure Active Directory -> App registrations). Anyway, access token using these settings is not compatible with access token required for the Sharepoint API, e.g.:
https://mindjet2.sharepoint.com/_api/contextinfo
throws exception
'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException'
What I'm doing wrong with the graph api? What is the right way to authenticate the Sharepoint API using OAuth?
In SharePoint add-in, we can use cross-domain library to achieve it.
Check the code below:
'use strict';
var hostweburl;
var appweburl;
// This code runs when the DOM is ready and creates a context object which is
// needed to use the SharePoint object model
$(document).ready(function () {
//Get the URI decoded URLs.
hostweburl =
decodeURIComponent(
getQueryStringParameter("SPHostUrl"));
appweburl =
decodeURIComponent(
getQueryStringParameter("SPAppWebUrl"));
// Resources are in URLs in the form:
// web_url/_layouts/15/resource
var scriptbase = hostweburl + "/_layouts/15/";
// Load the js file and continue to load the page with information about the list top level folders.
// SP.RequestExecutor.js to make cross-domain requests
// Load the js files and continue to the successHandler
$.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest);
});
// Function to prepare and issue the request to get
// SharePoint data
function execCrossDomainRequest() {
// executor: The RequestExecutor object
// Initialize the RequestExecutor with the app web URL.
var executor = new SP.RequestExecutor(appweburl);
var metatdata = "{ '__metadata': { 'type': 'SP.Data.TestListListItem' }, 'Title': 'changelistitemtitle'}";
// Issue the call against the app web.
// To get the title using REST we can hit the endpoint:
// appweburl/_api/web/lists/getbytitle('listname')/items
// The response formats the data in the JSON format.
// The functions successHandler and errorHandler attend the
// sucess and error events respectively.
executor.executeAsync({
url:appweburl + "/_api/SP.AppContextSite(#target)/web/GetFileByServerRelativeUrl('/Shared Documents/a.txt')/CheckOut()?#target='" +
hostweburl + "'",
method: "POST",
body: metatdata ,
headers: { "Accept": "application/json; odata=verbose", "content-type": "application/json; odata=verbose", "content-length": metatdata.length, "X-HTTP-Method": "MERGE", "IF-MATCH": "*" },
success: function (data) {
alert("success: " + JSON.stringify(data));
},
error: function (err) {
alert("error: " + JSON.stringify(err));
}
});
}
// This function prepares, loads, and then executes a SharePoint query to get
// the current users information
//Utilities
// Retrieve a query string value.
// For production purposes you may want to use
// a library to handle the query string.
function getQueryStringParameter(paramToRetrieve) {
var params =document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
Reference:https://www.c-sharpcorner.com/UploadFile/472cc1/check-out-files-in-sharepoint-library-2013-using-rest-api/
I'm working on a web page that lets you search for twitter users in your area. You enter a name in the search box and it returns users with that name within 50 miles of the city (the city is always the same).
I was having trouble authenticating, and I found oauth.io. I used that to authenticate and it seems to be working. But when I do a search, my request to Twitter returns as a 400 bad request error. I'm not sure what I'm doing wrong. I've looked at the oauth.io documentation but couldn't find anything.
Here is the part of the code that gets the value of what the user entered into the form field:
// Click function
$('.user-getter').submit(function(event) {
// prevent form refresh
event.preventDefault();
// zero out results if previous search has run
$('.user-results').html('');
// Get the values of what the person entered in search
var query = $(this).find("input[name='user_search']").val();
// Run function to send API request to Twitter
getUser(query);
}); // end click function
Here is the part of the code that calls the authorization and then sends the ajax request:
var getUser = function(query) {
OAuth.initialize('oMQua1CuWerqGKRwqVkzDx5uijo')
OAuth.popup('twitter').done(function(twitterData) {
$.ajax({
type: "GET",
url: "https://api.twitter.com/1.1/users/search.json?&geocode=42.94003620000001,-78.8677924,50mi&q=" + query,
dataType: "jsonp"
});
console.log( "Data Saved: " + twitterData ); // can see in inspector tab under Network
}); // end oAuth popup
};
Right now, I just want to see the result in console.log.
To make a request to Twitter API using OAuth.io you have to use the OAuth.io Javascript SDK instead of directly $.ajax (the OAuth.io Javascript SDK use the syntaxe of $.ajax behind the scene)
OAuth.initialize('oMQua1CuWerqGKRwqVkzDx5uijo')
OAuth.popup('twitter').done(function(twitterData) {
twitterData.get('/1.1/users/search.json', {
data: {
q: query
}
}).done(function(search) {
//result of the search here
console.log(search);
}).fail(function(error) {
//error management here
});
})
The SDK does all the hard things for you transparently: proxy the HTTP request, inject all the needed OAuth credentials (oauth_token, oauth_token_secret, signature, nonce, timestamp etc..)
Take a look to this jsfiddles: http://jsfiddle.net/uz76E/10/
I hope that helps,
I am writing a Web Api (using asp.net Web Api) and naturally want clients to authenticate to use the service.
I was hoping to write a Javascript plugin that would make use of the Api and then make it available to be simply dropped into other web sites.
Is there a secure way I can have the plugin authenticate?
I'm not sure how I could keep any information passed to the plugin confidential.
I also want the API to be used by native apps, so does that rule anything making use of cookies?
Thanks
Is there a secure way I can have the plugin authenticate?
You are going to have to either embed the username/password in your plugin OR have some fields to get that information from the user.
Consider some code if you choose to embed the username/password:
$.ajax({
url: 'api/foo',
type: 'GET',
dataType: 'json',
success: onSuccess,
error: onError,
beforeSend: setHeader
});
note the assignment of beforeSend to setHeader:
function setHeader(xhr) {
xhr.setRequestHeader('Authorization', 'Basic YXBpX3VzZXIxOjEyMzQxMjM0');
}
Note, you will have to pre-calculate the auth string using the method below
Now if you want to pull the username/password from the user you could do this:
function setHeader(xhr) {
xhr.setRequestHeader('Authorization', make_base_auth($("#username").val(), $("#password").val()));
}
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = Base64.encode(tok);
return "Basic " + hash;
}