I would like to "authorize" via the .NET framework using my own API keys, secret and Refresh Token, and then pass the Access Token to JavaScript so I can upload a video directly to YouTube with a progress indicator.
I have working code via the .NET API that will accomplish the upload directly to my channel [without authorization], but you get no progress indication (and it can take quite some time) and the file must be uploaded to my server first, then to YouTube server.
Is a server side access code different from a client side access code? If not:
How can I obtain the access code server side? (get the string)
***How can I pass it to Google APIs via JavaScript? (not how to write <%= access code %> but where to pass it in?)
I am well aware of the security risk in exposing the access token, but these do expire right? (as a bonus, how can I shorten the expire time). This is also being done inside a password protected web page, and you don't get the 'client secret' or 'refresh token'
***update - I think I found where to pass in the token, in the MediaUploader object.
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: selectedFile,
token: token, // ***RIGHT HERE***
metadata: metadata,
params: params,
onError: function(data) {
Okay, so after weeks of smashing my way through the APIs, .NET, and JavaScript documentation I have built the following solution....
As per the YouTube V3 Developer documentation get your Keys all set up. (choose OAuth, Web Application, and enter URIs for both your Javascript and Redirect code)
Next use the OAuth Playground to obtain your Refresh Code
Once you have your client_id, client_secret, and refresh_token you are ready to rock!
This code makes a simple HTTP/REST call via the code behind to obtain an access_token which is good for 3600 seconds (the default). It then passes this string to the JavaScript code for use ****WARNING****
This does not use any of the .NET or JavaScript Libraries with the exception of one file, the cors_upload.js available on GitHub
Allas, the code
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ApisCallTest.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta charset="utf-8" />
<title>YouTube API Uploads via CORS</title>
<style>
#disclaimer {
font-size: 0.75em;
color: #aeaeae;
max-width: 350px;
}
.during-upload { display: none; }
label { display: block; }
input[type="text"],
textarea,
progress {
font-size: 16px;
width: 15em;
margin-bottom: 1em;
padding: 0.5em;
font-family: "Open Sans", sans-serif;
}
</style>
</head>
<body>
<div>
<input input type="file" id="file" class="button" accept="video/*" />
<button id="button">Upload Video</button>
</div>
<div class="during-upload">
<p><span id="percent-transferred"></span>% done (<span id="bytes-transferred"></span>/<span id="total-bytes"></span> bytes)</p>
<progress id="upload-progress" max="1" value="0"></progress>
</div>
<p id="disclaimer">By uploading a video, you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at http://www.youtube.com/t/terms</p>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="cors_upload.js"></script>
<script>
$('#button').on("click", goForUpload);
function goForUpload() {
if ($('#file').get(0).files[0]) {
$('#button').attr('disabled', true);
var uploadStartTime = 0;
var metadata = {
snippet: {
title: 'PUT YOU TITLE HERE',
description: 'THIS IS YOUR VIDEO DESCRIPTION',
categoryId: '22'
},
status: {
privacyStatus: 'unlisted'
}
};
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: $('#file').get(0).files[0],
token: '<%= access_token %>',
metadata: metadata,
params: {
part: Object.keys(metadata).join(',')
},
onError: function (data) {
var message = data;
// Assuming the error is raised by the YouTube API, data will be
// a JSON string with error.message set. That may not be the
// only time onError will be raised, though.
try {
var errorResponse = JSON.parse(data);
message = errorResponse.error.message;
} finally {
alert(message);
}
},
onProgress: function (data) {
var currentTime = Date.now();
var bytesUploaded = data.loaded;
var totalBytes = data.total;
// The times are in millis, so we need to divide by 1000 to get seconds.
var bytesPerSecond = bytesUploaded / ((currentTime - this.uploadStartTime) / 1000);
var estimatedSecondsRemaining = (totalBytes - bytesUploaded) / bytesPerSecond;
var percentageComplete = (bytesUploaded * 100) / totalBytes;
$('#upload-progress').attr({
value: bytesUploaded,
max: totalBytes
});
$('#percent-transferred').text(percentageComplete);
$('#bytes-transferred').text(bytesUploaded);
$('#total-bytes').text(totalBytes);
$('.during-upload').show();
},
onComplete: function (data) {
var uploadResponse = JSON.parse(data);
alert('all done, you can store this id: ' + uploadResponse.id)
}
});
uploadStartTime = Date.now();
uploader.upload();
}
}
</script>
</body>
</html>
and Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace ApisCallTest
{
public partial class WebForm1 : System.Web.UI.Page
{
private static readonly HttpClient client = new HttpClient();
public string access_token;
protected void Page_Load(object sender, EventArgs e)
{
var values = new Dictionary<string, string>
{
{ "client_id", "REPLACE_ME" },
{ "client_secret", "REPLACE_ME" },
{ "refresh_token", "REPLACE_ME" },
{ "grant_type", "refresh_token" }
};
var content = new FormUrlEncodedContent(values);
var response = client.PostAsync("https://www.googleapis.com/oauth2/v4/token", content);
string json = response.Result.Content.ReadAsStringAsync().Result;
dynamic obj = JObject.Parse(json);
access_token = obj.access_token;
}
}
}
The result... From a password protected web page I can have a user upload a video to MY channel, unlisted, and store the video ID to later embed that video back on my website.
as for the ****WARNING****, this is somewhat of a security concern as you are exposing (very directly) your PERSONAL access key to the "public". It only lasts for 1 hour, but gives whatever "scope" of access you are using to "anyone" It would be a good idea to try and obstuficate the key somewhat, and at the very least, don't do this on a publicly available page.
Related
I'm looking into taking payments through the Square connect API on a website, but I can't figure out how to allow the user to key in any payment amount they wish (like a PayPal pay me button). Is this possible to do, or can you only take payments in pre-set fixed amounts via Square?
It looks like in Square's examples the amount is being set in the backend code and there's no way to send the amount for the transaction through from the frontend.
I am following Square's walkthrough using Node here: https://developer.squareup.com/docs/payment-form/payment-form-walkthrough
Apologies if this has been asked before, but I couldn't find anything recent that addressed the issue.
If you want to send the amount from the frontend, you would need to submit it via a field in a form (like the nonce in the example you provided). Ie if you wanted the customer to fill out the amount you would have something like:
<form>
...
<input type="text" id="amount" name="amount">
...
</form>
as a field in your form, and then in your backend retrieve it from the amount name (which depends on what backend language you're using, but as an example PHP would be something like $_POST['amount'].
I ended up solving this by coding the fetch to /process-payment explicitly in the frontend .js code instead of having it in the form submit so it looks like this:
function submitPaymentRequest(event) {
let nonce = document.getElementById("card-nonce").value;
fetch("process-payment", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
nonce: nonce,
amount: document.querySelector('input[name="amount"]').value
})
})
.then(response => {
console.log(response);
response.json().then(data => {
console.log(data);
alert(JSON.stringify(data));
});
})
.catch(function(error) {
console.log("the error was", error);
});
}
I posted a full working example of this here.
Yes i face the same issue but i made the solution.
Firstly You make a hidden type field and give them some value e.g 100
**> <input type="hidden" id="amount" name="amount" value="1000" />**
add this line in below your form.Then go to payment-processing page,
**
> string am = Request.Form["amount"];
**
get that input value i am doing in c# so its a c# code.
then pass this am string type variable to Amountmoney section. like below.
var amountMoney = new Money.Builder()
**.Amount(Convert.ToInt64(am))**
.Currency("USD")
.Build();
Here is the full code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Square;
using Square.Models;
using Square.Exceptions;
using Square.Apis;
public partial class process_payment : System.Web.UI.Page
{
private SquareClient client;
public string ResultMessage
{
get;
set;
}
protected void Page_Load(object sender, EventArgs e)
{
client = new SquareClient.Builder()
.Environment(Square.Environment.Sandbox)
.AccessToken("YOUR ACCESS TOKEN")
.Build();
string nonce = Request.Form["nonce"];
string am = Request.Form["amount"];
IPaymentsApi PaymentsApi = client.PaymentsApi;
var amountMoney = new Money.Builder()
.Amount(Convert.ToInt64(am))
.Currency("USD")
.Build();
string idempotencyKey = NewIdempotencyKey();
var body = new CreatePaymentRequest.Builder(
sourceId: nonce,
idempotencyKey: idempotencyKey,
amountMoney: amountMoney)
.Build();
CreatePaymentRequest createPaymentRequest = new CreatePaymentRequest.Builder(nonce, idempotencyKey, amountMoney)
.Note("From Square Sample Csharp App")
.Build();
try
{
CreatePaymentResponse response = PaymentsApi.CreatePayment(createPaymentRequest);
this.ResultMessage = "Payment complete! " + response.Payment.Note;
}
catch (ApiException es)
{
this.ResultMessage = es.Message;
}
}
private static string NewIdempotencyKey()
{
return Guid.NewGuid().ToString();
}
}
So I have some graphs in Power BI which I want to share with my clients.
I'm making a custom page here on my server and trying to embed those graphs using Power BI Embedded setup.
I'm following this link https://learn.microsoft.com/en-us/power-bi/developer/get-azuread-access-token
However, how do I get an access token via javascript API?
Generate EmbedToken is basically a REST API call. you can use NodeJs or AJAX to issue this request and get your EmbedToken.
For AAD auth, I can maybe refer you to ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js
which can help with auth against AAD
I don't think that's possible in Javascript at the moment. I tried to create access tokens in Javascript not a long time ago but failed to find a way to do that.
I ended up doing a bit of server side code (something like this https://learn.microsoft.com/en-us/power-bi/developer/walkthrough-push-data-get-token) and printed the access code to a hidden div. Then I grabbed the token with Javascript and continued with Javascript from there (created the embed token and embedded the report itself).
It might be possible to do a sort of Javascript solution with a proxy, but that's out of my expertise (the proxy has the server side code).
The only pure Javascript solution I'm aware of is the Publish to web -solution (https://learn.microsoft.com/en-us/power-bi/service-publish-to-web), but it's got some limitations and security issues.
I have already embed the Power BI reports into my web application. And also, i have faced problems while embedding report into my application but finally i embed the reports. Below is the code that will help you to get the Access token.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.12/js/adal.min.js"></script>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: 'common', //COMMON OR YOUR TENANT ID
clientId: '49df1bc7-db68-4fb4-91c0-6d93f770d1a4', //This is your client ID
redirectUri: 'https://login.live.com/oauth20_desktop.srf', //This is your redirect URI
callback: userSignedIn,
popUp: true
};
var ADAL = new AuthenticationContext(config);
function signIn() {
ADAL.login();
}
function userSignedIn(err, token) {
console.log('userSignedIn called');
if (!err) {
showWelcomeMessage();
ADAL.acquireToken("https://analysis.windows.net/powerbi/api", function(error, token) {
// Handle ADAL Error
if (error || !token) {
printErrorMessage('ADAL Error Occurred: ' + error);
return;
}
// Get TodoList Data
$.ajax({
type: "GET",
url: "https://api.powerbi.com/v1.0/myorg/datasets",
headers: {
'Authorization': 'Bearer ' + token,
},
}).done(function(data) {
console.log(data);
// Update the UI
$loading.hide();
}).fail(function() {
printErrorMessage('Error getting todo list data')
}).always(function() {
// Register Handlers for Buttons in Data Table
registerDataClickHandlers();
});
});
} else {
console.error("error: " + err);
}
}
function getDataSets() {
var trythis = "Bearer " + token;
var request = new XMLHttpRequest();
request.open('GET', 'https://api.powerbi.com/v1.0/myorg/datasets'); request.setRequestHeader('Authorization', trythis);
request.onreadystatechange = function() {
if (this.readyState === 4) {
console.log('Status:', this.status);
console.log('Body:', this.responseText);
}
};
request.send();
}
function showWelcomeMessage() {
var user = ADAL.getCachedUser();
var divWelcome = document.getElementById('WelcomeMessage');
divWelcome.innerHTML = "Welcome " + user.profile.name;
}
</script>
</head>
<body>
<button id="SignIn" onclick="signIn()">Sign In</button>
<h4 id="WelcomeMessage"></h4>
</body>
</html>
For more information you can go through the link that i will provide here.
Link : https://community.powerbi.com/t5/Developer/get-Access-token-using-js/m-p/352093#M10472
I am working on a asp.net mvc 5 and I want to use web api in it and I use a jquery library and below code.but I didnot get proper answer .it returns always fail but I can see the output in the browser.please help me
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script src="js/jquery-1.12.4.js"></script>
<script>
function ftoken() {
$.ajax({
url: 'http://charter724.ir/webservice/get_city_a.php?id=367&key=EmlyCD8JOWX22cL8IuNBju5K5',
// data: { },
type: 'GET',
dataType: 'json',
success: function (data) {
alert('success')
// alert(data.data)
//if (country_id != "" && zone_code != "" && duration != "" && birthday != "") {
// fPrice(data.token);
//}
//$.each(data, function (idx, result) {
// alert(result.data);
//})
},
error: function (x, y, z) {
alert('fail')
//alert(x.responseText);
//alert(z);
}
});
}
</script>
</head>
<body>
<input type="submit" name="name" onclick="ftoken();" value="Click " />
</body>
</html>
I can see the output in the browser
You will not be able to make an AJAX call to this URL because of the Same Origin Policy(Yes you can copy and paste the URL in the browser and get a response, but you cannot access it from javascript).
Same origin policy states that AJAX calls will only be allowed if they are coming from the same domain, you are doing something like this:
making an AJAX call from http://localhost... to http://charter724... - this is not allowed
If you inspect the browser console you will see an error similar to the one below:
XMLHttpRequest cannot load http://charter724.ir/webservice/get_city_a.php?id=367&key=EmlyCD8JOWX22cL8IuNBju5K5. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:10585' is therefore not allowed access
The only way around this is for you to contact the company exposing the charter724 service and ask them to enable CORS(Cross Origin Resource Sharing) and allow all requests coming from your domain to access their service calls.
Alternatively you can access the service call using HttpClient and get the JSON response.If you really wanted to you could even expose your own set of services which talk to the external service and access your service calls from java script:
public async System.Threading.Tasks.Task<ActionResult> Index()
{
string url = "http://charter724.ir/webservice/get_city_a.php?id=367&key=EmlyCD8JOWX22cL8IuNBju5K5";
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
System.Net.Http.HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return View();
}
I know how to embed a feed which has a certain ID. I already did it. Now I'd like to implement the following functionality: If a user receives a private message, it will appear on an embedded feed. The best option in my opinion would be to embed the whole "chat window", but I didn't find a single code sample on the web. How can I do that?
You cannot really embed private messages like you can with feeds, because Yammer's REST APIs (incl. private messages) require authentication via OAuth 2.0. That means you have to create a Yammer API application which will ask your users to log in and allow you to access their messages. The overall concept of that described in their documentation here and here.
Yammer provides several SDKs you can use, one of them is the Javascript SDK. I pieced togehter a simple example of how you can ask users to log in and then it will display their private messages. Mind you, this is a very simple solution, I just tested it on a single one-to-one conversation.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" data-app-id="YOUR-APP-CLIENT-ID" src="https://c64.assets-yammer.com/assets/platform_js_sdk.js"></script>
</head>
<body>
<span id="yammer-login"></span>
<div id="messages"></div>
<script>
yam.connect.loginButton('#yammer-login', function (resp) {
if (resp.authResponse) {
document.getElementById('yammer-login').innerHTML = 'Welcome to Yammer!';
}
});
var msgdiv = document.querySelector("#messages");
yam.getLoginStatus(
function(response) {
if (response.authResponse) {
console.log("logged in");
var myId = response.authResponse.user_id;
yam.platform.request({
url: "messages/private.json",
method: "GET",
success: function (response) {
console.log("The request was successful.");
var usernames = {};
response.references.forEach(function(ref){
if(ref.type === "user") {
usernames[ref.id] = ref.full_name;
}
});
response.messages.forEach(function(message){
var msg = document.createElement("span");
msg.innerHTML = usernames[message.sender_id] + ": " + message.body.parsed + "<br/>";
msgdiv.appendChild(msg);
})
},
error: function (response) {
console.log("There was an error with the request.");
console.dir(private);
}
});
}
else {
console.log("not logged in")
}
}
);
</script>
</body>
</html>
The response from the messages/private.json API endpoint is a JSON file that you can go through. It includes information about the message and the users involved in the conversation.
I've tried to follow default Web API tutorial: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
Here's what I did:
1) I added Action Routing in my WebApiConfig:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
2) I added a link on my nav bar with client side javascript call:
<a onclick="RetrieveNext();" href="#">Retrieve next</a>
3) Here's my view:
<div class="row">
<div class="col-md-4">
<h2>Next barcode</h2>
<p id="barcode">
No available barcode
</p>
</div>
</div>
<script>
var uri = 'api/Barcode';
$(document).ready(function () {
});
function RetrieveNext() {
uri = 'api/Barcode/RetrieveNext';
$.getJSON(uri)
.done(function (data) {
$('#barcode').text(data);
})
.fail(function (jqXHR, textStatus, err) {
$('#barcode').text('Error: ' + err);
});
}
</script>
4) Here's my simple ApiController with 1 Action:
public class BarcodeController : ApiController
{
[HttpGet]
public IHttpActionResult RetrieveNext()
{
string barcode = "123456";
if (barcode == null)
{
return NotFound();
}
return Ok(barcode);
}
}
When I click my link I'm getting: Error: Not Found inside of my <p id="barcode">, which means JavaScript works, but Action wasn't called.
Here's Call details:
What I missed here? I put breakpoint in my Action and I can't reach this code...
How stupid is THAT??? I found what is the issue here: 404 error after adding Web API to an existing MVC Web Application
It's related to global.asax file. Even when you add WEB API to your project, visual studio opens readme.txt file for you with few tips how to add few lines of code to your global.asax file. THERE'S no single word about WHERE you should put your code (here it's really makes difference!)
So, copying from post I listed ablove:
While it doesn't work with:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register); //I AM THE 4th
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
It works with:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register); //I AM THE 2nd
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}