I have a Facebook Page Tab app and I'm trying to find out where visitors to the page tab are coming from. I've read on http://developers.facebook.com/docs/authentication/signed_request/ that you can get these from app_data in the signed request but whenever I try getting the signed request app_data isn't there.
I used FB.getLoginStatus to get the signed request when inside the tab on Facebook, but
When I debug the signed request with http://developers.facebook.com/tools/echo I get the error "Bad Signature"
Your signed_request was probably not signed with our app_id of xxxxx Here is the payload:
{
"algorithm": "HMAC-SHA256",
"code": "xxxx",
"issued_at": xxxx,
"user_id": "xxxx2"
}
I'm using the C# SDK with Javascript
You can decode the signed request with the code in this topic:
Decode Signed Request Without Authentication
if (Request.Params["signed_request"] != null)
{
string payload = Request.Params["signed_request"].Split('.')[1];
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var o = JObject.Parse(json);
var lPid = Convert.ToString(o.SelectToken("page.id")).Replace("\"", "");
var lLiked = Convert.ToString(o.SelectToken("page.liked")).Replace("\"", "");
var lUserId= Convert.ToString(o.SelectToken("user_id")).Replace("\"", "");
}
It should be easy to get the app_data by adding
var lAppData = Convert.ToString(o.SelectToken("app_data")).Replace("\"", "");
To the have the app_data for your tab app you need to add it to the redirect url when acquiring permissions. You redirect url should something like:
http://facebook.com/YOUR_PAGE?sk=app_YOUR_APP_ID&app_data=add,whatever,parameters,you,want,here
I can only guess that the reason you got this error is because you just pasted your signed request in the address bar instead of the one used by the echo tool. The error is because your signed request is signed by your app_id and you're trying to use it with echo which has another app_id. But that's just a guess :)
My primary language is PHP but hope I was able to help :)
Related
I generated SAS url with below code
var blobBuilder = new BlobSasBuilder()
{
ExpiresOn = DateTimeOffset.UtcNow.AddDays(2),
Protocol = SasProtocol.Https,
StartsOn = DateTimeOffset.UtcNow.AddDays(-2),
BlobContainerName = _containerName
};
var blockBlob = _blobContainer.GetBlobClient(fileName);
blobBuilder.SetPermissions(BlobAccountSasPermissions.Read);
var isBlobExist = blockBlob.Exists();
if (isBlobExist)
{
var uriData = blockBlob.GenerateSasUri(blobBuilder);
if (uriData != null)
{
path = uriData.AbsoluteUri;
}
}
Generated URI is working most of the time for mobile users but sometimes it returns this error message when trying to download file
server returned http 403 server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature
I am not sure what wrong am I doing here because it works most of the time but doesn't work sometime.
I am also wondering if this is the case when someone try to override the file and other user is trying to read it. Please suggest
【Problem】
The app was implemented by reference to below URL, can no longer sign-in with SSO.
URL: https://blogs.msdn.microsoft.com/omarv/2012/11/15/developing-windows-8-store-apps-for-sharepoint-online-with-sso-single-sign-on/
【The code that was copied from above URL】
const string msoHrdUrl = “https://login.microsoftonline.com/GetUserRealm.srf“;
private async Task<Uri> GetAdfsAuthUrl()
{
// make a post request with the user’s login name to
// MSO HRD (Home Realm Discovery) service so it can find
// out the url of the federation service (corporate ADFS)
// responsible for authenticating the user
byte[] response = await HttpUtility.SendHttpRequest(
new Uri(msoHrdUrl),
HttpMethod.Post,
new MemoryStream(Encoding.UTF8.GetBytes(String.Format(“handler = 1 & login ={ 0 }”, this.username))),
// pass in the login name in the body of the form
“application/x-www-form-urlencoded“,
null);
StreamReader sr = newStreamReader(new MemoryStream(response));
Dictionary<String, IJsonValue> dict = new Dictionary<string, IJsonValue>();
HttpUtility.ParseJson(JsonObject.Parse(Encoding.UTF8.GetString(response, 0, response.Length)), dict);
// the corporate STS url is in the AuthURL element of the response body
Uri corpAdfsProxyUrl = dict.ContainsKey(“AuthURL“) ? new Uri(dict[“AuthURL“].GetString()) : null;
return corpAdfsProxyUrl;
}
【Current Situation】
Send POST Request to “https://login.microsoftonline.com/GetUserRealm.srf“, but I got response with error below.
Error: "AADSTS90100: Invalid request. The Accept request parameter value 'application/x-www-form-urlencoded' is invalid."
When I changed method POST to GET and set json to Accept, I can get some values that I want and AuthURL("https://ADFS.CONTOSO.COM/adfs/ls/?username=USER%40CONTOSO.COM&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=" ), but following behavior is different than before.
Ex) I cannot find value of “wresult” from Response that accessed to "https://ADFS.CONTOSO.COM/adfs/ls/auth/integrated/?username=USER%40CONTOSO.COM&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx="
【My Question】
I am not sure when this problem was occurred.
Does somebody have some information about this problem like this authentication function has changed?
The last time it went well is January in this year.
I m using amazon sdk for .net
i have uploaded a file in folder of my bucket , now i want to get the url of that file using this code
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
request.BucketName = "my-new-bucket2";
request.Key = "Images/Tulips.jpg";
request.Expires = DateTime.Now.AddHours(1);
request.Protocol = Protocol.HTTP;
string url = s3.GetPreSignedURL(request);
but this is returning url with key , exipration date and signature but infact i want to get the url without them , there is no other method to get the url
**Things i tried **
i search and found that i have to change permission of my file
i have change the permission of file while uploading
request.CannedACL = S3CannedACL.PublicRead;
but still its returning the same url
http://my-new-bucket2.s3-us-west-2.amazonaws.com/Images/Tulips.jpg?AWSAccessKeyId=xxxxxxxxxxxx&Expires=1432715743&Signature=xxxxxxxxxxx%3D
it work when i remove keyid ,expire and signature
but how can i get url with out it , or do i have to do it manually
This is by design. If you know the bucket name and the key then you have everything you need to construct the URL. As an example, here bucketname is yourbucketname and the key is this/is/your/key.jpg.
https://yourbucketname.s3.amazonaws.com/this/is/your/key.jpg
Hope that helps!
I just browsed their documentation and was not able to find a method to return an absolute url. However, I really believe there is one that I could not see. For now, you can solve your problem by extracting an absolute url from the result you have:
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
request.BucketName = "my-new-bucket2";
request.Key = "Images/Tulips.jpg";
request.Expires = DateTime.Now.AddHours(1);
request.Protocol = Protocol.HTTP;
string url = s3.GetPreSignedURL(request);
index = url.IndexOf("?");
if (index > 0)
string absUrl = url.Substring(0, index);
Hope it helps :)
I am creating an ASP.NET C# app that uploads videos to a YouTube Channel.
*I have already read through (to the best of my ability) the documentation at
The YouTube API Documentation
I have been able to successfully implement two examples of uploading a video to the YouTube channel using the sample code provided.
For example, using direct method (only the important code attached):
<!-- eja: import the google libraries -->
<%# Import Namespace="Google.GData.Client" %>
<%# Import Namespace="Google.GData.Extensions" %>
<%# Import Namespace="Google.GData.YouTube" %>
<%# Import Namespace="System.Net" %>
<!-- some more code -->
<%
// specify where to go to once authenticated
Uri targetUri = new Uri(Request.Url, "VideoManager.aspx");
// hide the link to authenticate for now.
GotoAuthSubLink.Visible = false;
// GotoAuthSubLink.Visible = true;
// look for a session var storing the auth token. if it's not empty
if (Session["token"] != null)
{
// go to the VideoManager link
Response.Redirect(targetUri.ToString());
}
else if (Request.QueryString["token"] != null)
{
// if we have the auth key in the URL, grab it from there instead
String token = Request.QueryString["token"];
// set the session equal to AuthSubUtil's calling the exchangeForSessionToken method
// returns the token and convert it to a string
Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
Response.Redirect(targetUri.ToString(), true);
}
else
{
//no auth token, display the link and create the token by loading the google
// auth page
String authLink = AuthSubUtil.getRequestUrl(Request.Url.ToString(), "http://gdata.youtube.com", false, true);
GotoAuthSubLink.Text = "Login to your Google Account";
GotoAuthSubLink.Visible = true;
GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl(Request.Url.ToString(),"http://gdata.youtube.com",false,true);
}
<asp:HyperLink ID="GotoAuthSubLink" runat="server"/>
That's page one...it loads the google authentication screen. (see link to attached image ,it's safe, I just set up a new account here on stackOverflow and can't upload images yet).
Then it leads to a page with the upload mechanism...The uploading works I am not worried about that, but here is the snippet of code FYI.
// create an instance ot the YouTubeService class. passing the application name and my DEV KEY
YouTubeService service = new YouTubeService(authFactory.ApplicationName, **API_KEY**);
// retrieve the current session token as a string if any
authFactory.Token = HttpContext.Current.Session["token"] as string;
// incorporate the information into our service
service.RequestFactory = authFactory;
try
{
// a YouTubeEntry object is single entity within a videoFeed object. It generally contains info
// about the video. when uploading, we will assign the values that we received to the feed.
YouTubeEntry entry = new YouTubeEntry();
// aggregate all the initial descriptor information
entry.Media = new Google.GData.YouTube.MediaGroup();
entry.Media.Description = new MediaDescription(this.Description.Text);
entry.Media.Title = new MediaTitle(this.Title.Text);
entry.Media.Keywords = new MediaKeywords(this.Keyword.Text);
// process entry.Media.Categories to assign the category
MediaCategory category = new MediaCategory(this.Category.SelectedValue);
category.Attributes["scheme"] = YouTubeService.DefaultCategory;
entry.Media.Categories.Add(category);
// prepare the token used for uploading
FormUploadToken token = service.FormUpload(entry);
HttpContext.Current.Session["form_upload_url"] = token.Url;
HttpContext.Current.Session["form_upload_token"] = token.Token;
// construct the URL
string page = "http://" + Request.ServerVariables["SERVER_NAME"];
if (Request.ServerVariables["SERVER_PORT"] != "80")
{
page += ":" + Request.ServerVariables["SERVER_PORT"];
}
page += Request.ServerVariables["URL"];
HttpContext.Current.Session["form_upload_redirect"] = page;
Response.Redirect("UploadVideo.aspx");
The page UploadVideo.aspx is the actual upload form, and it works, so I am not concerned about that.
The alternate method is not the recommended method, as it's synchronous in nature, but it DOES avoid that login screen as it allows us to pass credentials to authenticate (it works as a web app)...again principal code attached below.
<%
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory(ServiceNames.YouTube, "TesterApp");
// Response.Write("serviceNames.youtube=" + ServiceNames.YouTube + "<br />");
YouTubeRequestSettings s = new YouTubeRequestSettings(authFactory.ApplicationName, **your API KEY**,**Your email account as a username**,**your password**);
YouTubeRequest request = new YouTubeRequest(s);
Video newVideo = new Video();
newVideo.Title = "test at 4:40";
newVideo.Tags.Add(new MediaCategory("Games", YouTubeNameTable.CategorySchema));
newVideo.Keywords = "cars, funny";
newVideo.Description = "My description";
newVideo.YouTubeEntry.Private = false;
// newVideo.Tags.Add(new MediaCategory("mydevtag, anotherdevtag", YouTubeNameTable.DeveloperTagSchema));
// newVideo.YouTubeEntry.Location = new GeoRssWhere(37, -122);
// alternatively, you could just specify a descriptive string
newVideo.YouTubeEntry.setYouTubeExtension("location", "Somewhere,Someplace");
newVideo.YouTubeEntry.MediaSource = new MediaFileSource("C:\\IMG_1672.MOV",
"video/quicktime");
Video createdVideo = request.Upload(newVideo);
Response.Write("This will print out once the file is uploaded...indicates that the code is <i>synchronous</i>. The cursor spins around until done. go get a coffee then check the YouTube Channel");
%>
So basically the question that I am asking is - Is there a method that will upload a video to a YouTube Channel in ASP.NET C# code a) for a web application b) that I can pass credentials through the code to c) bypass the Google authentication screen seen above and d) without using OAuth and openID and a cert etc?
The App is for only a short campaign (November only) and I am happy to use the deprecated authSubUtil and a dev key and do not need to worry about oAuth 2.x or open ID (since authsubutil will deprecate in 2015 anyway).
Any Help is appreciated.
thanks
Edward
You would be best placed to use the ClientLogin authentication, where you can store a users username & password for their account and then use DirectUpload.
Direct Upload: https://developers.google.com/youtube/2.0/developers_guide_dotnet#Direct_Upload
ClientLogin: https://developers.google.com/youtube/2.0/developers_guide_protocol_clientlogin#ClientLogin_Authentication
Note client login is being deprecated, and they want you to use OAuth, however if you do it quickly you should be okay!
I'm developing a desktop application in C#.
After visiting https://www.facebook.com/dialog/oauth?client_id=123 the user logs in and the user access token is attached to the redirect uri. Its no problem, when the loginpage is displayed in a webbrowser control in my form, so i can extract the token from the url.
But this is not the way i want to get the token. My question is, is there a way to obtain the freshly created token via an Graph API call?
Because i want to display the login page in the user's standard browser and not in this embedded webbrowser. All my efforts to get the user access token have been resulted in getting the app access token, which is useless in this case.
Any hints are appreciated.
// This is very raw, And Note it is a MVC3 solution, but it is in C# and I hope it helps.
// It is basically a C# version of the PHP example on FB for 'Server Side Flow'
// I have been at it for a while and had to go through some pain
// Please note the bug I read about that states the redirect_uri must be the same for both //requests
// Also read that someone had an issue if the redirect_uri did not end in '/'
// Post back if you hae any ?s as I am just starting this project and am going to try and //incorporate the C# FaceBook SDK
public class AccountController : Controller
{
// LoginWithFaceBook
// First Contact with FB - oauth?client_id ... redirect_uri = /Account/FacebookLinker
// according to a bug files on FB redirect_uri MUST BE SAME FOR both trips ( to get the 'code' then exchange the code for 'access_token'
public ActionResult ConnectFaceBookAccount()
{
string APP_ID = HttpContext.Application["FacebookAppId"].ToString();
string redirect_uri = HttpContext.Application["FacebookOAuthRedirect"].ToString();
string state = HttpContext.Application["state_guid"].ToString();
// in this View I simply link to this URL
ViewBag.FaceBookOAuthUrl = "https://www.facebook.com/dialog/oauth?client_id=" + APP_ID + "&redirect_uri="+redirect_uri+"&state=" + state+"&display=popup";
return View();
}
// Account/FacebookLinker
// redirect_uri for both getting 'code' and exchanging for 'access_token'
public ActionResult FacebookLinker()
{
if (!Request.IsAuthenticated)
{
Response.Redirect("/Account/LogOn");
}
// Per FB DOC, Make sure 'state' var returned is same one you sent to reduce chance of Cross Site Forgery
if (Request.QueryString["state"].ToString() == HttpContext.Application["state_guid"].ToString())
{
try
{
string FBcode = Request.QueryString["code"].ToString();
string APP_ID = HttpContext.Application["FacebookAppId"].ToString();
string APP_SECRET = HttpContext.Application["FacebookAppSecret"].ToString();
string redirect_uri = HttpContext.Application["FacebookOAuthRedirect"].ToString();
string FBAccessUrl = "https://graph.facebook.com/oauth/access_token?client_id=" + APP_ID + "&redirect_uri=" + redirect_uri + "&client_secret=" + APP_SECRET + "&code=" + FBcode;
string accessToken = null;
// Send the request to exchange the code for access_token
var accessTokenRequest = System.Net.HttpWebRequest.Create(FBAccessUrl);
HttpWebResponse response = (HttpWebResponse) accessTokenRequest.GetResponse();
// handle response from FB
// this will not be a url with params like the first request to get the 'code'
Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);
using(StreamReader sr = new StreamReader(response.GetResponseStream(),rEncoding))
{
// parse the response to get the value of the 'access_token'
accessToken = HttpUtility.ParseQueryString(sr.ReadToEnd()).Get("access_token");
}
//TODO
// Add to the accessToken for the Logged in User.Identity to a FBUSERS Model
// WHen someone Logs in Check to see if they are also in FB
// ON Login Page add option to login with FaceBook
return View();
}
catch (Exception exp)
{
// try to get token failed
}
}
else
{
// state var form FB did not match state var sent
}
return View();
}
I think this is achievable via URL protocol handlers;
Create a custom URL protocol handler (MSDN: Registering an Application to a URL Protocol)
Create a facebook page that passes user access token to your url handler (ex. myfbapp://accesstoken/{token})
Set oauth redirect_uri to your facebook page
Parse access token in your application