Unable to create new claim identity - asp.net-core-mvc

I am currently trying to expose a field from an authenticated user, but I'm having a bit of difficulty trying to add a new claim to the authenticated user.
In MVC5 I would do something similar to the following:
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim("FullName", FullName));
return userIdentity;
}
}
When I attempt to do this in MVC6 however I run into problems with objects and methods missing. CreateIdentityAsync() and DefaultAuthenticationTypes both appear to be missing or so says visual studio and when I dig into the Identity source I can see that CreateIdentityAsync is no longer there, however I can't seem to find anything about DefaultAuthenticationTypes.
Right now at this point I think this is a nice to have, but its been driving me nuts for the past few days and would be nice to understand whats wrong or how this has changed.

Related

In MVVMCross 5, how can I navigate backward multiple pages?

In this example, a unique Person is defined by their FirstName and LastName. PageA is a form that selects a unique Person. PageB is a list of unique FirstNames, and PageC is a list of all the LastNames that exist for a given FirstName.
I'm having a hard time solving a particular UX pattern using MvxNavigationService. Here's what I'm attempting to do, (psuedocode):
PageA.SelectedItem = NavigateTo(PageB) [list of Person, grouped
by Person.FirstName];
PageB.SelectedItem = NavigateTo(PageC) [for
Person.FirstName, list of Person.LastName, ];
PageC.Close(SelectedItem);
PageB.Close(SelectedItem);
When I actually try and implement this and run it on Android, the viewmodel logic executes, but the UI doesn't show PageA.
Update: Calling PageB.Close() navigates back to PageC, since PageC was the previous page. Perhaps the problem could be solved by ensuring that PageC is removed from the stack upon closing it. How might this be accomplished?
There's many ways of doing this, using a Custom ViewPresenter on iOS or using an Activity on Android.
One way I achieved this for a small pair (2 view models) was by adding an Instance static variable to the first ViewModel that opens the second ViewModel, like this:
public class FirstViewModel
{
public static FirstViewModel Instance;
public void FirstViewModel()
{
Instance = this;
...
}
}
And then in the second ViewModel's save/close command, I just closed both ViewModels like this and it worked:
public new MvvmCross.Commands.IMvxCommand SaveClickCommand
{
get
{
return new MvvmCross.Commands.MvxAsyncCommand(
async () =>
{
await Navigator.Close(this);
await Navigator.Close(FirstViewModel.Instance);
}
);
}
}

How to pursuade the ApiExplorer to create documentation for ExpandoObject?

I've created a very neat way of implementing a PATCH method for my Web.API project by making use of an ExpandoObject as a parameter. As illustrated below:
[HttpPatch, Route("api/employee/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] ExpandoObject employee)
{
var source = Repository.FindEmployeeById(id);
Patch(employee, source);
Repository.SaveEmployee(source);
return Ok(source);
}
However, when generating documentation ApiExplorer is at a loss as to what to do with the ExpandoObject, which is totally understandable. Would anyone have any ideas on how to manipulate the ApiExplorer to provide some sensible documentation?
My idea was to maybe introduce an new attribute which points to the actual Type that is expected:
public IHttpActionResult Update(int id, [FromBody, Mimics(typeof(Employee))] ExpandoObject employee)
{
...
}
But I have no idea where to start, any ideas or suggestions are welcome.
So this has been the source of some late evenings in order to get the Api Explorer to play along with our developed Http Patch mechanism. Truth be told, I'd probably should do a bit of a proper write up to full explain the mechanics behind the whole idea. But for those of you who landed on this page because you want the Api explorer to use a different type in the documentation, this is where you need to look:
Open HelpPageConfigurationExtensions.cs and locate the following method:
//File: Areas/HelpPage/HelpPageConfigurationExtensions.cs
private static void GenerateRequestModelDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator, HelpPageSampleGenerator sampleGenerator)
{
....
}
this is the location where the parameter information is available to you and also provides you with the ability to replace/substitute parameter information with something else. I ended up doing the following to handle my ExpandoObject parameter issue:
if (apiParameter.Source == ApiParameterSource.FromBody)
{
Type parameterType = apiParameter.ParameterDescriptor.ParameterType;
// do something different when dealing with parameters
// of type ExpandObject.
if (parameterType == typeof(ExpandoObject))
{
// if a request-type-attribute is defined, assume the parameter
// is the supposed to mimic the type defined.
var requestTypeAttribute = apiParameter.ParameterDescriptor.GetCustomAttributes<RequestTypeAttribute>().FirstOrDefault();
if (requestTypeAttribute != null)
{
parameterType = requestTypeAttribute.RequestType;
}
}
}
Just, note that the RequestTypeAttribute is something I devised. My WebApi endpoint looks like this now:
public IHttpActionResult Update(int id,
[FromBody, RequestType(typeof(Employee))] ExpandoObject employee)
Thank you to everyone who took time to look into the problem.

aspnet identity; how to login using a legacy password?

i've a site i'm updating to web api with aspnet identity 2.0.
It's a legacy site for which we need to allow the users to use their old passwords; at least during a reasonable migration period
following this article, i've derived a new UserManager from the base UserManager, and set up the PasswordHasher to hash with an old SHA1 algorithm.
My passwordHasher looks like this:
public class SQLPasswordHasher : PasswordHasher
{
public override string HashPassword(string password)
{
string cipherText = EncryptPassword(password);
return cipherText;
}
public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
string cipherText = EncryptPassword(providedPassword);
if (cipherText == hashedPassword)
{
return PasswordVerificationResult.SuccessRehashNeeded;
}
else
{
return PasswordVerificationResult.Failed;
}
}
private string EncryptPassword(string plainText)
{
return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(plainText, "sha1");
}
}
When i register users with this code, I can see the passwords are being hashed and persisted in the database correctly... for the password 'foobar', the hashed value is fixed and recognizable, since this algorithm did not use a salt.
However, I cannot log in as these users. If i set a breakpoint in the new hasher, it never gets it. Neither can i seem to hit a breakpoint anywhere in the account controller when trying to log in.
thanks in advance
I'm answering my own question, in the hopes that someone else may benefit.
The problem was, i couldn't find what in the web api service was being called when logging in. I finally realized that something called /Token was being set up as the url to be called in the app.js javascript.
Searching through the project server side sources and googling led me to this article, which pointed me to the ApplicationOAuthProvider.cs file, in the 'Providers' folder of the template application.
The specific line of interest is where the method GrantResourceOwnerCredentials instantiates it's own user manager, thus:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
From there, all i had to do was add this line:
userManager.PasswordHasher = new SQLPasswordHasher();
and i could finally log in.

Where to filter Identity 2.0 claim ticket in a WebAPI app?

ASP.NET apps using OWIN permit multiple Identity sources (Facebook, Google, etc.). Most of the provider-specifc information those sources provide is irrelevant to my app, potentially even large, and I don't want it in my cookies all session. My app is primarily WebAPI, but I suspect the question applies equally to MVC and WebForms.
For now, all I need is an integer account ID. Where/when should I reconstruct the identity, after external authentication?
For example, here is one way I could filter claims:
public ReplaceExistingClaims(ClaimsIdentity identity) {
{
Claim customClaim = GetCustomClaimFromDbForIdentity(identity);
foreach (Claim claim in ClaimsIdentity.Claims) ClaimsIdentity.RemoveClaim(claim);
ClaimsIdentity.AddClaim(customClaim);
}
And following are two different places I could inject those claims changes:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions
{
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
ReplaceExistingClaims(context.Identity);
return Task.FromResult(0);
}
}
};
Above, I know I can hook an individual provider from Startup IF it provides an Authenticated event. I have two conceptual problems with this. One: it requires me to write and wire up my code separately for each provider I plug in. Two: there is no requirement for providers to provide this event. Both of these make me feel like there must be a different intended insertion point for my code.
public ActionResult ExternalLoginCallback(string returnUrl)
{
ReplaceExistingClaims((ClaimsIdentity)User.Identity);
new RedirectResult(returnUrl);
}
Above, I know I can put code in ExternalLoginCallback. But this happens too late for two reasons. One: The user has already been issued a ticket I consider invalid, but the default [Authorized] considers valid because it's signed by me, and now they are making requests to my site with it. There could even be race conditions here. Two: There is no guarantee the browser will visit this redirect, and I'd prefer from a design perspective if it didn't have to, e.g. to simplify my WebAPI client code.
To the best of my knowledge, the best solution will meet these requirements:
same code applies to all providers
client receives my custom ticket from my server (e.g. without image claims)
client never receives another ticket format from my server
the authentication process requires the minimum possible HTTP round-trips
token-refresh and other core identity features are still available
once a user is [Authorize]d, no further account transformation is necessary
database/repository access is feasible during ticket generation
Some pages I'm researching, for my own notes:
How do I access Microsoft.Owin.Security.xyz OnAuthenticated context AddClaims values?
https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Facebook/FacebookAuthenticationHandler.cs
https://katanaproject.codeplex.com/workitem/82
https://www.simple-talk.com/dotnet/.net-framework/creating-custom-oauth-middleware-for-mvc-5/
You have to implement DelegationHandler and put all your authentication routines in it.
Register at Application start (DI usage is enabled):
private static void RegisterHandlers(HttpConfiguration config)
{
var authHandler = new MyFacebookAuthHandler();
config.MessageHandlers.Add(authHandler);
}
And this is an example of implementation:
public class MyFacebookAuthHandler : DelegationHandler
{
public override sealed Task<HttpResponseMessage> OnSendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
try
{
// Process credentials
// Probably you have to save some auth information to HttpContext.Current
// Or throw NotAuthorizedException
}
catch(NotAuthorizedException ex)
{
return request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex).ToCompletedTask();
}
catch (Exception ex)
{
return request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex).ToCompletedTask();
}
return base.OnSendAsync(request, cancellationToken);
}
}
The ClaimsAuthenticationManager class is specifically for this.
https://msdn.microsoft.com/en-us/library/system.security.claims.claimsauthenticationmanager(v=vs.110).aspx
Code sample from that reference:
class SimpleClaimsAuthenticatonManager : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
}
return incomingPrincipal;
}
}

How to access the Session in MVC.Net 4 from different Thread

I have a MVC.Net4 Application in which i have Longrunning backround operations which is why i use the System.Threading.Tasks.Task Class.
I start the Tasks after the User clicked a certain Button on the GUI, from that Task im going to use async methods from a intern API which i need to await. This is all working.
public ActionResult DoAsyncAction()
{
//ReturnValue that needs to be further populated by the async action in productive environment
var arv = new AsyncReturnValue
{
ProgressBar = new ProgressBar {Action = "SomeAction", User = "SomeUser"}
};
var t = new Task<AsyncReturnValue>(DoAction, arv);
//Add a Progressbar before Task starts so i can visualize the process on the view
HttpContext.GetSession().ProgressBars.Add(arv.ProgressBar);
//from my understanding this is similar to an event that gets triggered when my DoAction Method finished so i need to remove
//the progressbar there again since the process will be finished in that case
t.ContinueWith(DoActionkComplete);
t.Start();
//Returns the User to the Index Page while the Task is processing
return View("Index");
}
Now what i really want to do is visualizing the operation. I use jQuery Progressbars on the GUI and my Own ProgressBar Object in the Session for this. I have a List of ProgressBars on my Session and a PartialView strongly Typed to a List of those ProgressBars.
ProgressBar Class:
public class ProgressBar
{
public string Action { get; set; }
public string User { get; set; }
}
PartialView:
#using AsyncProj.Models
#model List<AsyncProj.Models.ProgressBar>
#{
ViewBag.Title = "ProgressPartial";
}
#{
var foo = (MySessionObject) HttpContext.Current.Session["__MySessionObject"];
foreach (var pb in foo.ProgressBars)
{
<div style="border: 1px solid black">
<p>#pb.Action</p>
<div id="progressbar">This will be turned into a ProgressBar via jQuery.</div >
</div>
}
}
And then the Object i have in my Session:
public class MySessionObject
{
public List<ProgressBar> ProgressBars { get; set; }
public string User { get; set; }}
Whenever i start a new Task i will add another ProgressBar to that List, which works just fine.
No where i get into Troubles is when i want to Remove the ProgressBars from Session again.
In the DoActionkComplete Method which i set in Task.ContinueWith() i want to Remove the ProgressBar corresponding to the finished action. I have the ProgressBar Ready there, its stored in my AsyncReturnValue Class which i have in the Task.Result at this point:
public class AsyncReturnValue
{
public ProgressBar ProgressBar { get; set; }
}
In this Method i would like to remove the Progressbar from the Session with
HttpContext.GetSession().ProgressBars.Remove(pbToRemove). But the problem with that im still operating on a different Thread so i have no valid HttpContext there and my SessionObject is null on that Thread.
This is what my DoActionComplete Method looks right now:
public void DoActionkComplete(Task<AsyncReturnValue> t)
{
//i set the user hardcode because its only a demo
DeleteProgress.Add(new ProgressBarDeleteObject {ProgressBar = t.Result.ProgressBar, User = "Asd123"});
}
I created a Workaround where i have a static List of Progressbars on my Controller. In the DoActionComplete Method i add the ProgressBars i want to delete to that List. I need to use polling (with jQuery $.get() and setinterval) in order to delete them.
I have a custom Class for the DeleteList on which i can set a Username so i know who is the Owner of that ProgressBar and only show it to him, else everyone would see it because its Static.
public class ProgressBarDeleteObject
{
public ProgressBar ProgressBar { get; set; }
public string User { get; set; }
}
Dont get me wrong, my workaround works just fine but i want to know the clean way. From what i know static Lists on Controllers could technically grow very big and slow the site down. Such Lists also lose its entries when the ApplicationPool restarts the Application.
So my Actual Question would be how can i access a HttpContext SessionObject from a different Thread like i'm using? And if its not possible, what would be the proper Way to achieve what i want?
So my Actual Question would be how can i access a HttpContext SessionObject from a different Thread like i'm using?
That's not possible.
And if its not possible, what would be the proper Way to achieve what i want?
First, let's back up to the original scenario. The problem is here:
I have a MVC.Net4 Application in which i have Longrunning backround operations which is why i use the System.Threading.Tasks.Task Class.
That's the wrong solution for that scenario. The proper solution is to have a reliable queue (Azure queue / MSMQ) with an independent background process (Azure webjob / Win32 service) doing the processing. This is a more reliable solution because any work you toss onto the ASP.NET thread pool may be lost (especially if you don't inform ASP.NET about that work).
Once you have this architecture set up, then you can use SignalR to communicate from your web server to your clients. SignalR will use polling if it has to, but it can also use more efficient methods (such as websockets).
You can specify the SynchroniztionContext that the ContinueWith task continues on and then you should be able to access the progress bars. Try changing your t.ContinueWith(DoActionkComplete); call to
t.ContinueWith(DoActionkComplete, TaskScheduler.FromCurrentSynchronizationContext());
If you are using .NET 4.5 you can rewrite your method with async\await
public async Task<ActionResult> DoAsyncAction()
{
//ReturnValue that needs to be further populated by the async action in productive environment
var arv = new AsyncReturnValue
{
ProgressBar = new ProgressBar {Action = "SomeAction", User = "SomeUser"}
};
//Add a Progressbar before Task starts so i can visualize the process on the view
HttpContext.GetSession().ProgressBars.Add(arv.ProgressBar);
var result = await Task.Run(DoAction());
//i set the user hardcode because its only a demo
DeleteProgress.Add(new ProgressBarDeleteObject {ProgressBar = result.ProgressBar, User = "Asd123"});
//Returns the User to the Index Page while the Task is processing
return View("Index");
}
And if you make the DoAction method async as well, you can remove the Task.Run part as that uses up a thread from the thread pool.

Resources