Hammock Facebook graph API query parameter - asp.net

I am using Hammock to get data from the Facebook graph API. When user logs into my web site I want to get all data from his Facebook profile since he last logged my web site. So when the user logs into my web site I update his login time and from his last login date to now, I take all his Facebook profile data. I am using Hammock to do this.
I want to give Hammock a creation date parameter but it doesn't work.
This works:
RestClient client = new RestClient { Authority = "https://graph.facebook.com/" };
RestRequest request = new RestRequest { Path = "/me/status " };
But this does not:
string query = "SELECT status_id, message FROM status WHERE status_id = me() and creationTime.......";
RestClient client = new RestClient { Authority = "https://graph.facebook.com/" };
RestRequest request = new RestRequest { Path = "/me?q=query" };
How can I give the creation time to the hammock request?
This code works for me:
RestClient client = new RestClient { Authority = "https://graph.facebook.com/" };
RestRequest request = new RestRequest { Path = "/me/statues" };
But it loads all user statuses. I want to give a datetime parameter; for example, if I want to get user statuses since 30.08.2012.

In your last example, you can add the since query string to your request:
... { Path = "/me/statuses?since=2012-08-30" };
For your second example, you're using the wrong URL to make a FQL query. Try this instead:
... { Path = "/fql?q=" + Server.UrlEncode(query) };

Related

WebRequest is forbidden on Sharepoint Online

I need to create web request to specific page in SharePoint Online using Access Token in order to get certain Header information, but I keep getting 403 and I'm not sure why. After toying with access requests some more, I managed to only get 403 using clientContext, and 401 using Postman.
I can get response from grah api in my app and with postman using access token, but the problem is I need to do a web request to get real web page headers like SpRequestDuration and SPIISLatency.
I've followed steps to create my Azure AD and application.
I request user login to get authentication code for my application
loginScopes = [
'User.Read.All',
'Directory.Read.All',
'Group.Read.All',
'Sites.Read.All',
'Reports.Read.All'
'offline_access',
'https://www.sharepoint.com/AllSites.FullControl'
];
const encodedScopes = encodeURIComponent(loginScopes.join(' '));
const encodedRedirectUri = encodeURIComponent(redirectUri);
let url = `https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?
response_type=code&
client_id=${clientId}
&redirect_uri=${encodedRedirectUri}
&scope=${encodedScopes}
&prompt=select_account`;
After this returns authentication code I create ConfidentialClientApplication with authority : 'https://login.microsoftonline.com/organizations' and with my application clientId, secret, redirect etc. With newly created ConfidentialClientApplication I acquire token silently with scope '{tenantUrl}/AllSites.FullControl'and another token with other scopes.
Now with access token I successfully create ClientContext, which retrieves data from sharepoint site and I can easily make a graph API request and everything will be fine. But the problem is with creating a WebRequest to a specific site (example. {tenantUrl}/SitePages/Forms/ByAuthor.aspx)
var manager = new AuthenticationManager();
var clientContext = manager.GetAzureADAccessTokenAuthenticatedContext(tenantUrl, accessToken);
clientContext.Load(clientContext.Site);
clientContext.Load(oWebsite.Lists);
clientContext.ExecuteQuery(); // Works fine
var request = clientContext.WebRequestExecutorFactory.CreateWebRequestExecutor(clientContext,{tenantUrl}/SitePages/Forms/ByAuthor.aspx).WebRequest;
request.Method = "GET";
//request.Headers.Add("Authorization", $"Bearer {accessToken}");
clientContext.ExecutingWebRequest += delegate (object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.WebRequest.Headers.Add("Authorization", "Bearer " + accessToken);
};
await request.GetResponseAsync(); // Throws 403
with sharepoint online
string siteUrl = ConfigurationManager.AppSettings["siteURL"];
SecureString passWord = new SecureString();
string pass = ConfigurationManager.AppSettings["userPassword"];
string user = ConfigurationManager.AppSettings["userName"];
foreach (char c in pass.ToCharArray()) passWord.AppendChar(c);
ClientContext clientContext = new ClientContext(siteUrl);
clientContext.Credentials = new SharePointOnlineCredentials(user, passWord);
return clientContext;
without
clientContext.ExecutingWebRequest

OneDrive for Business :"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'grant_type

I'm trying to integrate the OneDrive for Busines to a Web Form App.
For this I use the documentation given at this url
In web Form App I have two Pages:
First one is Login page which have a button for login
On login button click I create a GET Request to OneDrive for Business API using the following code:
HttpClient client = new HttpClient();
Redirecturi = Uri.EscapeDataString(Redirecturi);
string url = string.Format("https://login.windows.net/common/oauth2/authorize?response_type=code&client_id={0}&redirect_uri={1}", ClienId, Redirecturi);
var response = client.GetAsync(url);
var json = response.Result.Content.ReadAsStringAsync();
Label2.Text = json.Result;
When I click the login button it takes me to micorosoft login service and sends me back to callback.aspx page with access code (Redirect URI configured on azure)
I got the access code.
On the second page I redeem the access code and make a POST request to get the Authentication token.
Here is the code for the second page:
private string BaseUri="https://login.windows.net/common/oauth2/token";
public string Redirecturi = "http://localhost:51642/CallBack.aspx";
public string ResourcesId = "https://api.office.com/discovery/";
private string ClienId = "180c6ac4-5829-468e-.....-822405804862"; ///truncated//azure
private string ClientSecert = "G4TAQzD8d7C4...OE6m366afv8XKbTCcyXr4=";//truncated
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString[OAuthConstants.AccessToken]))
{
// There is a token available already. It should be the token flow. Ignore it.
return;
}
if (!string.IsNullOrEmpty(Request.QueryString[OAuthConstants.Code]))
{
string _accessCode = Request.QueryString[OAuthConstants.Code];
HttpClient client = new HttpClient();
// BaseUri = Uri.EscapeDataString(BaseUri);
Redirecturi = Uri.EscapeDataString(Redirecturi);
ResourcesId = Uri.EscapeDataString(ResourcesId);
string url = string.Format("{0}?client_id={1}&redirect_uri={2}&grant_type=authorization_code&client_secret={3}&code={4}&grant_type=authorization_code&resource={5}", BaseUri, ClienId, Redirecturi, ClientSecert, _accessCode, ResourcesId);
var response = client.PostAsync(url, null);
var json = response.Result.Content.ReadAsStringAsync();
Response.Write(json);
}
}
But instead of Response I am get the following error. Which say include the grant_type in url. I have already added (you can check in code).
I get same error the same error without including it.
Here is the error
{"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 2adb3a7f-ceb1-4978-97c4-3dc2d3cc3ad4\r\nCorrelation ID: 29fb11a0-c602-4891-9299-b0b538d75b5f\r\nTimestamp: 2015-07-15 09:58:42Z","error_codes":[90014],"timestamp":"2015-07-15 09:58:42Z","trace_id":"2adb3a7f-ceb1-4978-97c4-3dc2d3cc3ad4","correlation_id":"29fb11a0-c602-4891-9299-b0b538d75b5f","submit_url":null,"context":null}
Please help to know where or what is getting wrong.
Any kind of help will be appreciable
You're adding the parameters to the request querystring. You have to post the data in the request body.
var content = new StringContent(
"grant_type=authorization_code" +
"&client_id=" + ClienId +
"&redirect_uri=" + Redirecturi +
"&client_secret=" + ClientSecert +
"&code=" + _accessCode +
"&resource=" + ResourcesId,
Encoding.UTF8,
"application/x-www-form-urlencoded");
var response = httpClient.PostAsync(BaseUri, content);
var result = response.Result.Content.ReadAsStringAsync();
use FormUrlEncodedContent instead of StringContent (form data post)
var formContent = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", clientId },
{ "client_secret", clientSecret },
{ "code", authCode },
{ "redirect_uri", redirectUri },
{ "grant_type", "authorization_code" }
});
var response = await httpClient.PostAsync("https://login.microsoftonline.com/common/oauth2/token", formContent);
Sharing for future readers because this error is not specific to OneDrive only but can arise in other Microsoft tools
I was getting this error when working with Microsoft Bot Framework's Skype bot. In my case the bot file the appId and appSecret was wrongly set to clientId and clientSecret
Changing the same to appId and appSecret fixed the issue.

Asp.net Identity Email Verifcation Token Not Recognized

We are using Microsoft's Identity Framework v2.0 in a web forms application. All is working well. We decided we want to add email verification as part of the new account set up process. If we validate the token after it is created in the same page, we are successful. But if we try to validate the token in a different page, it fails. The process is very simple:
Admin creates a new account by providing user's email and name. (we do not support self registration).
User clicks link he gets in email to validate the email was received.
Here is the code to create the email verification token:
var manager = new UserManager();
var user = new ApplicationUser() { UserName = EmailAddress.Text, Email = EmailAddress.Text, FirstName = FirstName.Text, LastName = LastName.Text };
IdentityResult result = manager.Create(user);
var provider = new DpapiDataProtectionProvider();
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))
{
TokenLifespan = TimeSpan.FromHours(24)
};
var strToken = manager.GenerateEmailConfirmationToken(user.Id);
//IdentityResult validToken = manager.ConfirmEmail(user.Id, strToken);
strToken = HttpUtility.UrlEncode(strToken.ToString());
NOTE: If we uncomment the line beginning //IdentityResult validToken..., then it succeeds.
Here is the code on the VerifyEmail page:
string userid = Request.QueryString["id"].ToString();
string tokenReceived = Request.QueryString["token"].ToString();
//tokenReceived = HttpUtility.UrlDecode(tokenReceived);
ApplicationUser User = new ApplicationUser();
var manager = new UserManager();
User = manager.FindById(userid);
var provider = new DpapiDataProtectionProvider();
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))
{
TokenLifespan = TimeSpan.FromHours(24)
};
IdentityResult validToken = manager.ConfirmEmail(User.Id, tokenReceived);
The validToken line does not succeed in this file. I have validated that the strings User.Id and tokenReceived match EXACTLY in both file, so there is no URL corruption going on. (That is why I commented out the UrlDecode since it seems to be decoded by the browser automatically - when I try to decode, it is not 100% the same as the string before encoding).
So I am certain we are calling the same method (ConfirmEmail) and that the two parameters that are passed are exactly the same strings. I am also aware that a token can only be validated once, so I am not trying to re-use them after once validating them.
Any ideas would be welcome.
I think the problem in DpapiDataProtectionProvider - If you use the same instance of this class in creating and validating the token, it'll work fine.
Any reason you are not getting UserManager from Owin Context as per VC2013 template?

Testing a Web App Protected by Passive Federated Auth

My team has an ASP.NET MVC-based website and WebAPI that is protected by passive federated authentication. It all works properly. The problem we're having is that we need to test the website and the web API after an automated deployment. How can we authenticate and get the FEDAUTH cookie to the website from automated test code, assuming that the test code is run by a user authorized to access the website?
You can have your Web API support active authentication. It requires some work to change the configuration and authentication handler, but it will make your web API easily accessible from a program client as well. If you just want to get a FEDAUTH cookie in your automated test code, the following code sample can work. It mimics a browser to post the user token to the website and get a cookie back.
// The code needs the STS server and the website url
var stsUrl = "https://your_STS";
var serviceUrl = "https://your_Service";
// Use Windows Credential to get the token
var binding = new WSHttpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
var factory = new WSTrustChannelFactory(binding, stsUrl) { TrustVersion = TrustVersion.WSTrust13 };
// Override current login user credential if needed:
// factory.Credentials.Windows.ClientCredential = userCredential;
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference(serviceUrl)
};
RequestSecurityTokenResponse rstr;
var token = factory.CreateChannel().Issue(rst, out rstr);
var fedSerializer = new System.IdentityModel.Services.WSFederationSerializer();
var rstrContent = fedSerializer.GetResponseAsString(rstr, new WSTrustSerializationContext());
// After this the security token is acquired and saved in rstrContent
var client = new HttpClient();
// Initiate a request to the service, which will be redirected to STS. Read WS fed fields from redirected URL.
var response = client.GetAsync(serviceUrl).Result;
response.EnsureSuccessStatusCode();
var redirectQuery = response.RequestMessage.RequestUri.Query;
var queryParams = System.Web.HttpUtility.ParseQueryString(redirectQuery);
// construct a authentication form
var formData = new Dictionary<string, string>
{
{"wa", queryParams["wa"]},
{"wresult", rstrContent},
{"wctx", queryParams["wctx"] },
};
// post the authentication form to the website.
response = client.PostAsync(serviceUrl, new FormUrlEncodedContent(formData)).Result;
response.EnsureSuccessStatusCode();
// After this, the auth cookie is set in this HttpClient that you can use to access your service

Using Hammock to Call Recurly REST API with BasicAuthCredentials

I'm trying to call the Recurly REST API using the Hammock C# library for .NET. The API calls require an Authorization header on the HttpRequest, and the authentication scheme is Basic authentication with the Base64 encoded API key in the username portion of the header. I thought that I could create a new Hammock BasicAuthCredentials object with the encoded key in the Username property of the object, then assign the object to the Credentials property of either the RestClient or RestRequest objects. However, this does not seem to generate an Authorization header on the outbound HttpRequest.
If I add the Authorization header manually using the AddHeader method on one of those objects, the API call succeeds. If I use the Credentials property with the BasicAuthCredentials object, I get an Access Denied error from Recurly.
This seems pretty basic, so I know I'm doing something wrong. So, in Hammock, is the Credentials property on either the RestClient or RestRequest object supposed to create an Authorization header on the Http request?
Thanks for any help from a super Hammock user!
The code that fails:
class Program
{
public static void Main(string[] args)
{
string encodedAPIKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("APIKeyHere"));
BasicAuthCredentials credentials = new BasicAuthCredentials
{
Username = encodedAPIKey
};
RestClient client = new RestClient
{
Authority = "https://api.recurly.com",
VersionPath = "v2"
};
client.AddHeader("Accept", "application/xml");
RestRequest request = new RestRequest
{
Credentials = credentials,
Path = "plans"
};
RestResponse response = client.Request(request);
Console.WriteLine(response.Content);
Console.ReadLine();
}
}
The code that succeeds:
class Program
{
public static void Main(string[] args)
{
string encodedAPIKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("APIKeyHere"));
RestClient client = new RestClient
{
Authority = "https://api.recurly.com",
VersionPath = "v2"
};
client.AddHeader("Accept", "application/xml");
client.AddHeader("Authorization", "Basic " + encodedAPIKey);
RestRequest request = new RestRequest
{
Path = "plans"
};
RestResponse response = client.Request(request);
Console.WriteLine(response.Content);
Console.ReadLine();
}
}
After getting no answers to my question, I did a search for alternative Rest libraries for .NET and found RestSharp. I was able to get it working with Recurly using its built-in Basic Authorization implementation on the first try, so I will be implementing using RestSharp. The code looks very similar, so the migration should be an easy one.

Resources