Validating a user in WCF using ASP.net Identity 2.0 Framework - wcf

I have built a custom Identity.Models framework by simply extending the new asp.net identity framework 2.0 so that I can store the username and other relevant user data in my custom database instead of the default entity database which gets generated and it is working fine.
Now I am building a WCF service from where I would like to authenticate these users and leverage the asp.net identity 2.0 functionalities , but unable to do so.
In my WCF service I made a new Validator class extending UsernamePasswordValidator but it is not working as expected.
public class IdentityValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
using (var context = new MyIdentityDbContext())
{
using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context)))
{
var user = userManager.Find(userName, password);
if (user == null)
{
var msg = String.Format("Unknown Username {0} or incorrect password {1}", userName, password);
Trace.TraceWarning(msg);
throw new FaultException(msg);
}
}
}
}
}
Any suggestions would be highly appreciated.

You are almost there, however, you need one more step to tell the WCF service to be well behaved through introducing service behavior, generally in config. For more details, please read
Authentication and Authorization with ASP.NET Identity 2.0 for WCF Services

Related

Convert use of Membership to something that will work in .NET Core for WCF service calls

I have some legacy framework code that calls a service that I need to replicate in a .NET Core 3.1 solution. The code uses a client built by adding a web reference (ImageService). The code authenticates the user using Membership and sets an authentication cookie that is used by the execution of client methods.
The method below is what I need to replicate in the Core solution. I've created a client in the .NET Core solution also using the WCF web reference. What do I need to do/use to replicate the functionality of the code below?
private static void setImageService(string host, string userId, string password) {
ImageService.ImageService _imageServiceSoapClient = new ImageService.ImageService();
((ClientFormsAuthenticationMembershipProvider) Membership.Provider).ServiceUri = string.Format("https://{0}/ImageService/Authentication_JSON_AppService.axd", host);
((ClientRoleProvider) Roles.Provider).ServiceUri = string.Format("https://{0}/ImageService/Role_JSON_AppService.axd", host);
bool validateUser = Membership.ValidateUser(userId, password);
if (validateUser) {
AppDomain.CurrentDomain.SetThreadPrincipal(Thread.CurrentPrincipal);
} else {
throw new InvalidCredentialException(string.Format("User {0} not authenticated", userId));
}
_imageServiceSoapClient.CookieContainer = ((ClientFormsIdentity) Thread.CurrentPrincipal.Identity).AuthenticationCookies;
}

Migrate Principal from ASP.NET Web API 2 to ASP.NET Core (AuthenticationFilter)

I'm thinking about how can I migrate a ASP.NET Web API 2 project to ASP.NET Core.
Current project details:
All API controllers are inheriting a BaseController.
BaseController is decorated with a custom attribute (CustomAuthenticationAttribute)
CustomAuthenticationAttribute implements IAuthenticationFilter and inside AuthenticateAsync method:
Based on the HTTP headers I'm retrieving details about the user from the database
In case the user is not found, I'm populating HttpAuthenticationContext.ErrorResult and return (cutting the pipeline)
If I find the user, a statement similar to this is executed: HttpAuthenticationContext.Principal = new GenericPrincipal(identity, new string[] { }) in order to set the principal.
The BaseController contains the following code:
protected MyIdentityClass Identity
{
get
{
if (RequestContext.Principal == null)
{
return null;
}
return RequestContext.Principal.Identity as MyIdentityClass ;
}
}
I am able to access the Identity inside any API method.
Inside unit tests, I can assign the principal with the following code:
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { });
My question is this: How can I port this code to ASP.NET Core without modifying all my API controllers and test classes? I've already read Migrate from ClaimsPrincipal.Current but it doesn't satisfy my needs.

How to decrypt asp.net owin token in asp.net core manually?

I have an existing application which generates owin identity token with machine key approach. The same token is used to authenticate various application. One of the application is now in asp.net core. Is there any way to use same owin generated identity token in asp.net core?
or we can decode that token manually in asp.net core
You cannot share anything between ASP.NET and ASP.NET Core when using machine keys. The only way to be able to decrypt something in ASP.NET Core set by an ASP.NET app is if 1) the ASP.NET app(s) utilize the data protection provider 2) the data protection provider key ring is persisted to filesystem or network location accessible by all the apps (ASP.NET and ASP.NET Core alike) and all the apps utilize the same application name.
The docs go into great detail on this.
You can decrypt the Access Token returned from the authorization code flow directly by using IDataProtector. we implement the IDataProtector interface and use the System.Web.Security.MachineKey.Unprotect method.
To Make helper Method to decrypt the OWIN ticket
private class MachineKeyProtector : IDataProtector
{
private readonly string[] _purpose =
{
typeof(OAuthAuthorizationServerMiddleware).Namespace,
"Access_Token",
"v1"
};
public byte[] Protect(byte[] userData)
{
//throw new NotImplementedException();
}
public byte[] Unprotect(byte[] protectedData)
{
return System.Web.Security.MachineKey.Unprotect(protectedData, _purpose);
}
}
To get ClaimsIdentity and a Dictionary of Properties. we just create an instance and pass in the Token to get the decrypted Ticket
var secureDataFormat = new TicketDataFormat(new MachineKeyProtector());
AuthenticationTicket ticket = secureDataFormat.Unprotect(accessToken);
Above AuthenticationTicket itself contains the ClaimsIdentity and a Dictionary of Properties.
refer IDataProtector Interface

How to apply SSO (single sign on)

I already have a 5 asp.net application developed under ASP.NET & SQL. each application has his private users tables "credential" to authorize the users on the login.
How can apply a SSO solution to cover the 5 application ? knowing that the same user has different access credential on each application "The username & Password" not same for the same user on the 5 application.
also if there is any third party tool to do that without change any thing on the 5 application, will be very good.
Thanks.
You can use Identity Server for this purpose (here https://identityserver.github.io/Documentation/docsv2/ is documentation for version 3 and you can find there how to run authorization in your APP).
The identity server provide IdentityServerOptions object where you can define some stuff. But for you will be most important Factory property where you can configure Identity Server behavior.
Here is example:
public class Factory
{
public static IdentityServerServiceFactory Create()
{
var factory = new IdentityServerServiceFactory();
// Users are taken from custom UserService which implements IUserService
var userService = new YourUserService();
factory.UserService = new Registration<IUserService>(resolver => userService);
// Custom view service, for custom login views
factory.ViewService = new Registration<IViewService>(typeof(YourViewService));
// Register for Identity Server clients (applications which Identity Server recognize and scopes
factory.UseInMemoryClients(Clients.Get());
factory.UseInMemoryScopes(Scopes.Get());
return factory;
}
}
Where YourUserService will implemtent IUserService (provided by Identity Server) where you can authorize users how you need, in methods AuthenticateLocalAsync and GetProfileDataAsync you can do your own logic for authentication.
And using of the Factory in Startup class for Identity Server project
public void Configuration(IAppBuilder app)
{
var options = new IdentityServerOptions
{
SiteName = "IdentityServer",
SigningCertificate = LoadCertificate(),
EnableWelcomePage = false,
Factory = Factory.Create(),
AuthenticationOptions = new AuthenticationOptions
{
EnablePostSignOutAutoRedirect = true,
EnableSignOutPrompt = false,
},
};
app.UseIdentityServer(options);
}
Here https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/CustomUserService you can find some exmaple of this using own UserService
Also here https://github.com/IdentityServer/IdentityServer3.Samples are more examples how to working with Identity Server.
Only bad thing is that in every application you must configure using Identity Server as authentication service so you must change existing apps.

Claims based authentication, with active directory, without ADFS

I have a client asking for an integrated authentication based solution utilizing a custom role/membership schema. My original plan was to use claims based authentication mechanism with integrated authentication. However, my initial research is not turning up a whole lot of useful information.
To the point, I have an ASP.NET (not core nor owin) WebAPI application, which has api actions used by angular SPA based (asp.net) web application. I am attempting to authorize the api calls using integrated authentication. My initial effort was focused around a custom AuthorizationAttribute and ClaimsAuthenticationManager implementation. However as I got deeper into that I started running into issues with the custom ClaimsAuthenticationManager, at this point I'm not sure that is the proper route to take.
So my question for you all is, can you at least give me some ideas of what it would take to make this happen? I don't need help with secific bits the code, just need to figure out the appropriate "stack" so to speak.
The only real requirement is WebAPI calls can be authorized, with a custom attribute passing a name of a claim to authorize on, but the claim is not in AD even though it is using windows authentication, the claims themselves would come from a database.
Thank you all in advance!
Look at https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api.
Your scenario isn't much different:
you're using AD for authentication
you're using your db for authorization
Simply put this can be addressed by configuring web-api to use windows authentication.
<system.web>
<authentication mode="Windows" />
</system.web>
And add your own IAuthorizationFilter to Web API pipeline, that will check current principal (should be set), and then override this principal with your own (i.e. query db - get claims, and override it with your custom claims principal by setting HttpContext.Current.User and Thread.CurrentPrincipal).
For how to add filter to WebAPI pipe line check out How to add global ASP.Net Web Api Filters?
public class CustomAuthenticationFilter : IAuthenticationFilter {
public bool AllowMultiple { get { return true; } }
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) {
var windowsPrincipal = context.Principal as WindowsPrincipal;
if (windowsPrincipal != null) {
var name = windowsPrincipal.Identity.Name;
// TODO: fetch claims from db (i guess based on name)
var identity = new ClaimsIdentity(windowsPrincipal.Identity);
identity.AddClaim(new Claim("db-crazy-claim", "db-value"));
var claimsPrincipal = new ClaimsPrincipal(identity);
// here is the punchline - we're replacing original windows principal
// with our own claims principal
context.Principal = claimsPrincipal;
}
return Task.FromResult(0);
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) {
return Task.FromResult(0);
}
}
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
config.Filters.Add(new CustomAuthenticationFilter());
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute( ... );
}
}
Also there is no need for custom authorization attribute - use default one - its understood by everyone, and makes your code more readable.