Problem with dotnetopenauth client.ProcessUserAuthorization() - asp.net

I downloaded DotNetOpenAuth-3.5.0.10259 and tried to run the samples, specifically the OAuthClient sample and I managed to get it to work with facebook (VS2010). I can see "Welcome, [my name]" after allowing access in facebook.
The problem comes in when I try to use it in another project. I get a "No overload for method 'ProcessUserAuthorization' takes '0' arguments" and "No overload for method 'RequestUserAuthorization' takes '0' arguments".
Its basically the same code, which I find very weird since it works on the included sample but won't compile in the other project.
What did I miss?
protected void Page_Load(object sender, EventArgs e)
{
IAuthorizationState authorization = client.ProcessUserAuthorization();
if (authorization == null)
{
// Kick off authorization request
client.RequestUserAuthorization();
}
private static readonly FacebookClient client = new FacebookClient
{
ClientIdentifier = ConfigurationManager.AppSettings["facebookAppID"],
ClientSecret = ConfigurationManager.AppSettings["facebookAppSecret"],
};
The FacebookClient class came from the DotNetOpenAuth.ApplicationBlock project in the samples included in the 3.5.0.10259 download.

The only thing I can guess is that there is missing overload definitions within the libraries. I experienced the same issue you are describing, but in my case I couldn't get the samples to compile at all.
The trick though, is to simply pass in a NULL for the request parameter, which seems to work:
IAuthorizationState authorization = client.ProcessUserAuthorization(null);
Also note that you may run into the same missing overload issue with the "RequestUserAuthorization" method. Likewise, you can also pass in null values for each of the three parameters if you don't want to send them along:
client.RequestUserAuthorization(null, null, null);
Good luck!

Related

Handling cookies based on route in a single request lifecycle in ASP.NET MVC?

I'm writing a route that will allow the user to set a cookie with the version of some JSON object that the application will use to set client-side configurations. It is a fairly large JSON object that we don't want to store in a cookie alone. We want to store ONLY the version to be looked up and set from some map up in the cloud on every request since multiple versions of the client are running around and we want those to be separated on a per request basis.
Currently, I know the problem is due to my lack of understanding of the single request lifecycle of ASP.NET MVC as I'm sure the following code proves. I do know that the Application_BeginRequest Action is probably happening BEFORE the route is handled (correct me if I'm wrong here), but I am not sure where it SHOULD be happening so that the cookie is populated BEFORE it is retrieved. I also don't believe that Application_EndRequest would be better due to the same, but opposite issue.
Any and all suggestions that lead to my understanding of the lifecycle and an appropriate Action to handle that kind of cookie value getting will be welcomed!
// Working controller (cookie does get set, this is confirmed)
using System;
using System.Web;
using System.Web.Mvc;
using SMM.Web.Infrastructure.Filters;
namespace SMM.Web.Controllers
{
[NoCache]
public class SetCookieController : ApplicationController
{
private HttpCookie CreateVersionCookie(int versionId)
{
HttpCookie versionCookie = new HttpCookie("version_id");
versionCookie.Value = versionId.ToString();
return versionCookie;
}
public ActionResult SetCookie(int versionId)
{
Response.Cookies.Add(CreateVersionCookie(versionId));
return Redirect("/");
}
}
}
// In Global.asax.cs (this does not work to get the cookie)
private void LoadSomeJsonFromACookie()
{
HttpCookie someJsonThingCookie = HttpContext.Current.Request.Cookies["version_id"];
string jsonVersion = (string)staticVersionCookie.Value;
string json = FunctionToGetSomeJsonThingByVersion(jsonVersion); // This returns a stringified JSON object based on the jsonVersion supplied
dynamic someJsonThing = JsonConvert.DeserializeObject<dynamic>(json);
HttpContext.Current.Items["someJsonThing"] = someJsonThing;
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
RedirectToHttps();
// some other redirects happen here
LoadSomeJsonFromACookie();
}
Application_BeginRequest is the right place. Since in the code, you can see I'm firing a redirect back to root /, it will set the cookie before it ever needs the cookie.

MVVM Light 5 - Navigation Service passing wrong parameter

I have upgraded to MVVM Light 5 and I changed my navigation methods from:
Messenger.Default.Send(new NavigateToPageMessage() { PageName = "UserDetailsPage", Parameter = id });
To the following:
_navigationService.NavigateTo(ViewModelLocator.UserDetailsPageKey, id);
The parameter I am passing does not seem to make it's way to the OnNavigatedTo event of the view anymore, the parameter is completely different, am I missing something?
EDIT:
This new method seems to give me the parameter I need:
GlobalNavigation.GetAndRemoveParameter(NavigationContext)
Although now, when the app is tombstoned, I lose that parameter entirely. Before, when the app was restored I would still have that parameter in the NavigatedTo args, this allowed me to re-hit the server with that ID and get fresh data. Why have I lost this capability
use this
protected override void OnNavigatedTo(NavigationEventArgs e)
{
GalaSoft.MvvmLight.Views.NavigationService navigationService = new GalaSoft.MvvmLight.Views.NavigationService();
var param = navigationService.GetAndRemoveParameter(this.NavigationContext);
base.OnNavigatedTo(e);
}

WCF call via MSMQ erratic

The code is trivial so rather than explain, here's the relevant portion:
protected void Page_Load(object sender, EventArgs e)
{
if ((Request.HttpMethod == "POST") && (Request.ContentType == "text/xml"))
{
string filename = string.Format("{0:yyyyMMddHHmmss}.xml", DateTime.UtcNow);
var path = Path.Combine(Request.MapPath("Chapters"), Request.Headers["X-MAC"]);
Directory.CreateDirectory(path);
string xml;
using (ChapterWriterClient client = new ChapterWriterClient())
using (StreamReader sr = new StreamReader(Request.InputStream))
{
xml = sr.ReadToEnd();
client.Write(xml);
System.Diagnostics.Trace.TraceInformation(xml);
}
Request.SaveAs(Path.Combine(path, filename), false);
}
There's more but the rest of it works as expected.
Here's the problem: the call client.Write(string xml) is erratic in whether it succeeds.
Some known facts:
No error is ever reported to the debugger or the event log
Sometimes the XML makes it into the message queue and sometimes it doesn't
Request.SaveAs(string filepath, bool includeHeaders) call always succeeds and the resultant file always contains the expected XML. This has several important implications:
The call to WCF is being executed.
Because the string xml had the expected value immediately after the failed WCF call, and assignment to this variable occurs only prior to the WCF call, it must have had the correct value at the time of the call.
There is some variation in message size so I'm checking the service config in that regard but past experience tells me to expect an exception thrown when the payload is too big.
Any clues would be appreciated.
Also, as you can probably see the whole point of the exercise is a somewhat naiive attempt to use an HTTP POST to put some XML into a message on MSMQ. I'd be perfectly happy with a "Don't do it like that, do it like this you ignorant savage" type answer.

What is an anonymous username supposed to look like in a ProviderInfo object?

Per Microsoft's ProfileInfo definition http://msdn.microsoft.com/en-us/library/system.web.profile.profileinfo.aspx, an unauthenticated profileinfo object has a username; naturally this must be keyed off of to persist/ reference profile information in a given session (I am assuming it is session-based). I'm guessing this is some guid or something, but I don't see where this is defined, created, tracked, etc. Can someone point me in the right direction?
Well... The question interested me so I've decided to do some research.
A bit of digging in documentation lead me first to Implementing a Profile Provider MSDN article, where I've found the following:
GetPropertyValues method
Takes as input a SettingsContext and a SettingsPropertyCollection
object.
The SettingsContext provides information about the user. You can use
the information as a primary key to retrieve profile property
information for the user. Use the SettingsContext object to get the
user name and whether the user is authenticated or anonymous.
...
So, the determination of whether user is authenticated or not is generally done on higher level. Anyway, I took a look at code of Microsoft's default SqlProfileProvider implementation (namely, GetPropertyValues method implementation) and found out that it calls method private void GetPropertyValuesFromDatabase(string userName, SettingsPropertyValueCollection svc) which actually has the following code:
HttpContext context = HttpContext.Current;
...
string sName = null;
if (context != null)
sName = (context.Request.IsAuthenticated ? context.User.Identity.Name : context.Request.AnonymousID);
So, if we have a non-authenticated request then a user id is taken from HttpContext.Current.Request.AnonymousID property. Searching through MSDN for this property has revealed the following page: HttpRequest.AnonymousID property (System.Web). Although it still does not describe exact algorithm of generating this ID, but it provides information on how you can override this default algorithm if you want. All you need is to overload public void AnonymousIdentification_Creating(Object sender, AnonymousIdentificationEventArgs e) method in your web application. Also this page provides some information on how AnonymousID is persisted between calls (by default it's stored in .ASPXANONYMOUS cookie).
Example code:
void Application_Start(Object sender, EventArgs e)
{
// Initialize user count property
Application["UserCount"] = 0;
}
public void AnonymousIdentification_Creating(Object sender, AnonymousIdentificationEventArgs e)
{
// Change the anonymous id
e.AnonymousID = "mysite.com_Anonymous_User_" + DateTime.Now.Ticks;
// Increment count of unique anonymous users
Application["UserCount"] = Int32.Parse(Application["UserCount"].ToString()) + 1;
}
Summary: I have not been able to answer your original question on HOW this ID is created by default but I think that last code snippet will be enough for you to override this with any algorithm you want.

The Application_PreRequestHandlerExecute event doesn't fire for PageMethods. What can I use instead?

This article explains that the PreRequestHandlerExecute event does not fire for PageMethod calls for whatever reason. However, I'm trying to use that event to populate the Principal object with the user's permissions so they can be checked within any web request (PageMethod call or not). I'm caching the permissions in the Session, so I need an event that fires whenever a PageMethod is called, and I need to have access to the Session. This way I can populate the Principal object with the security permissions cached in the session, and User.IsInRole() calls will work as expected. What event can I use?
You should implement an authorization module that will be run with every request that goes up to the server. This way you are able to authorize your principal for any request that come up to the server (page request, method, etc.)
public class AuthorizationModule : IHttpModule, IRequiresSessionState
{
//not going to implement it fully, might not compile
public void Init( HttpApplication context )
{
//you'll prolly want to hook up to the acquire request state event, but read up to make sure this is the one you want on the msdn
context.AcquireRequestState += AuthorizeRequest;
}
public void AuthorizeRequest( HttpContextBase httpContext )
{
// do you work in here
// you can redirect them wherever if they don't have permssion, log them out, etc
}
}
}
After you've crated the module, you'll need to hook it up in the web.config. Your type should include the namespace if it has one.
<httpModules>
<add name="AuthorizationModule" type="AuthorizationModule"/>
</httpModules>
I hope this helps.
You can use the Application_OnPostAuthenticateRequest as shown below (assuming you are using Forms Authentication. Else, pls replace the code with your Authentication mechanism):
public void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
{
IPrincipal usr = HttpContext.Current.User;
if (usr.Identity.IsAuthenticated && usr.Identity.AuthenticationType == "Forms")
{
var fIdent = (FormsIdentity)usr.Identity;
var ci = new CustomIdentity(fIdent.Ticket);
var p = new CustomPrincipal(ci);
HttpContext.Current.User = p;
Thread.CurrentPrincipal = p;
}
}
Page Methods are static, and bypass the normal Page lifecycle, its objects and its events. The best you can do is pass authentication information as parameters to the Page Method itself.
From my point of view, you can:
1.- Use a common method you can call from every page method server code that have access to Session variables. Please refer to:
http://mattberseth.com/blog/2007/06/aspnet_ajax_use_pagemethods_pr.html
2.- Try to capture a similar behaviour later using __doPostBack() function to run server code. See if this work for you to capture page method async posbacks:
http://www.dotnetcurry.com/ShowArticle.aspx?ID=256
Hope that helps,

Resources