Combining token based authentication with Windows Authentication - asp.net

We currently have an internal API that uses Windows Authentication. I've been charged with looking into making this API public, and one of the requirements is that it should be possible to login without a domain user. Domain users should still be able to login, and should be considered super admins (access everything).
It is also clear that before long, we will need role or claim based authorization. As a prototype, I have implemented a system using ASP.NET Identity. Using JWT tokens and Claims based authorization.
But how do I ensure that users authenticated with Windows Authentication can skip the token step and simply use the API directly?

Found a solution where I add custom AuthorizationFilterAttributes to my endpoints. In the attribute, I check for the Principal type:
public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.RequestContext.Principal is WindowsPrincipal)
{
return Task.FromResult<object>(null);
}
//Custom logic here
[...]
}

Related

What mechanism does OWIN use to determine that a user is authenticated before reading their claims?

I've launched the sample project for ASP.Net MVC that provides single sign-on against Active Directory, and am using this Microsoft tutorial for reference.
Once the user has clicked to sign-in and gets redirect to their organisation's login page, upon returning to the web application the following code verifies that they are authenticated, and successfully reads their claims:
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
#if (Request.IsAuthenticated)
{
<dl>
#foreach (var claim in System.Security.Claims.ClaimsPrincipal.Current.Claims)
{
<text>
<dt>#claim.Type</dt>
<dd>#claim.Value</dd>
</text>
}
</dl>
}
Under the hood, what actually constitutes a true value of Request.IsAuthenticated?
Is it by the very nature that claims exist, or is there a specific value that is being used to provide a result before the claims are read?
That tutorial asks you to add authentication middleware into your request pipeline. In this case you're adding UseCookieAuthentication and UseOpenIdConnectAuthentication to register authentication middlewares. These, and any others you might add (JWT bearer token authentication for example), use their own internal mechanism for parsing the request and assigning a claims identity to your request context. For example, cookie authentication will look for a cookie that represents a persisted session and will decrypt and parse its details out as a claims identity. IsAuthenticated literally just returns true if one or more identities are available.
For more detail you can of course drill into the source code. For example, OWIN's cookie authentication middleware lives here: https://github.com/aspnet/AspNetKatana/tree/dev/src/Microsoft.Owin.Security.Cookies

How to authenticate IdentityServer with firebase or Quickblox

I design a mobile application (Android for now) which depend on large ecosystem.
One of my main components is Auth system and I built it using IdentityServer3.
Now For user to login via the mobile application I use the OAuth2 implicit flow, so I opened a server side web page which take and validate user credentials, then generate id_token and access_token so I have no idea about the user password as client side.
Now, I want to implement another feature which is real-time chatting between users.
I checked a lot of solutions but everyone has a security weakness which may lead in the feature to an unwanted scenarios.
For Example:
QuickBlox:
QuickBlox clouding service (I don't know about the enterprise on-primes one) required to create a user then login with the user to create session using username and password.
QBAuth.createSession(new QBUser("user", "pass"), new QBEntityCallback<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
// success
}
#Override
public void onError(QBResponseException error) {
// errors
}
});
So it has its own UserStore which is separate from my central Auth service, so I thought about creating a dummy password with a layer of security like creating a well defined password consist of
UserName#ServerSideSecretKey
But this is not the way that I should go on as I should depend on my Central Auth service and only generate token, then pass it to QuickBlox to identify my user through my Auth UserInfo endpoint.
Is it something like this which allow me integrate QuickBlox with my Auth service??
I found this line in the documentation:
It's also possible to initialize the SDK with an existent QuickBlox
token. It can be interesting in cases when you build a big system and
you have a custom server side which generates QuickBlox tokens:
try {
QBAuth.createFromExistentToken("31ed199120fb998dc472aea785a1825809ad5c04", date);
} catch (BaseServiceException e) {
e.printStackTrace();
}
but I don't understand how this will work or how to allow QuickBlox validate my generated OAuth2 token.
Firebase:
In Firebase, I know that I can generate JWT tokens, then validate it against my firebase service so I should change my IdentityServer token generation behaviour to be JWT and then validate it against the Firebase secret key that I applied?
So how can I do that in identity server with implicit flow? Or is there another solutions?

Logging Out With AspNet.Security.OpenIdConnect.Server (ASP.NET vNext)

I am using Visual Studio 2015 Enterprise and ASP.NET vNext Beta8 to issue and consume JWT tokens as described here.
In our implementation we're storing some client details in Redis at token issuing time and we would like the flush this information when the user logs out.
My question is what is the best practices for logging out with OIDC?
While I could roll my own contoller for this purpose I couldn't help but notice Open ID Connect (OIDC) seems somewhat primed to handle this case. For example OIDC has an OnLogoutEndpoint handler and LogoutEndpointPath settings. But when I call the OIDC logout URI that handler appears to accept any random x-www-form-urlencoded form I throw at it and doesn't in any particular way seem to be demanding the presence of a token.
Any advice on proper OIDC logout practices would be very much appreciated.
In AspNet.Security.OpenIdConnect.Server, the logic used for the logout endpoint is left as an exercise.
In this sample, it is implemented using an MVC 6 controller, where you're - of course - free to add custom logic to remove cached details from your Redis server.
[HttpPost("~/connect/logout")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout() {
// When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired.
// When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved using AuthenticateAsync.
var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);
// Remove the cached details here. If you need to determine
// who's the authenticated user, you can use the identity variable.
// Remove the authentication cookie and return the user to the client application.
return SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationScheme);
}
You can also do something similar directly from the LogoutEndpoint event. Don't forget to call context.HandleResponse() to make sure the request is not intercepted by another middleware.

How set Authorization attribute role MVC4 to the user?

I'm trying to use the Authorize attribute on MVC 4 application,
[Authorize(Roles = "Administrator, Super-User")]
public JsonResult Remove(int id)
{
.
.
.
}
I know that only the roles "Administrator" and "Super-User" roles are authorized to execute the method Remove, but how I can set the role to the actual User of the application?
The answer is - somehow, so that HttpContext.Current.User is set and the IsInRole method returns true.
The easiest way to do this would be to follow one of built-in mechanisms of authentication/authorization: Forms authentication or Windows authentication.
The former requires that the request carries a valid forms cookie issued by the server. The latter requires that the request principal can be authenticated in the domain controller.
You are however free to implement a custom authentication module.
If you are just starting to learn this, probably you'd like to use Forms Authentication for this. Just let your users log in, issue the cookie and the cookie will automatically be carried by subsequent ajax request (assuming your server code is called from within javascript client-side ajax call).
You can Add the current user to a role using
Roles.AddUsersToRole(new string[]{HttpContext.Current.User.Identity.Name}, "Admin");
Roles class is available in System.Web.Security namespace.
if you want to add users and Roles
-Open your solution in Visual Studio
goto project->ASP.NET configuration->Security Tab
You can add a user to roles using a Role Provider.
var rolesProvider = (SimpleRoleProvider)Roles.Provider;
Check the role exists
if (!rolesProvider.RoleExists("SuperUser"))
{
rolesProvider.CreateRole("SuperUser");
}
Check if the user is in the role already, if not, add the user to the role
if (! rolesProvider.IsUserInRole("JohnSmith", "SuperUser"))
{
rolesProvider.AddUsersToRoles(new[] {"JohnSmith"}, new[] {"SuperUser"});
}

asp.net, wcf authentication and caching

I need to place my app business logic into a WCF service. The service shouldn't be dependent on ASP.NET and there is a lot of data regarding the authenticated user which is frequently used in the business logic hence it's supposed to be cached (probably using a distributed cache). As for authentication - I'm going to use two level authentication:
Front-End - forms authentication back-end
(WCF Service) - message username authentication.
For both authentications the same custom membership provider is supposed to be used.
To cache the authenticated user data, I'm going to implement two service methods:
1) Authenticate - will retrieve the needed data and place it into the cache(where username will be used as a key)
2) SignOut - will remove the data from the cache
Question 1. Is correct to perform authentication that way (in two places) ?
Question 2. Is this caching strategy worth using or should I look at using aspnet compatible service and asp.net session ?
Maybe, these questions are too general. But, anyway I'd like to get any suggestions or recommendations.
Any Idea
Question 1:
From my experience the ASP forms authentication would be enough. No reason to send credentials as POST and certainly not GET. You can use that for a change password or account info method. You might want to look into Membership and Roles.
Question 2:
I would stick with the ASP.NET session. This might make your application more prone to issues and vulnerabilities in the end, and I see it as unnecessary.
Passing the password to between the services is not a good practice. You should consider creating a custom security token in your front-end application and passing this token to the WCF service. WCF service can validate the token using a certificate. With this approach you can
insert any user data into the security token and use in the WCF service
cache the token in the front-end application session, therefore you don't need any distributed cache
centralize login and avoid authenticating user twice
If you don't want to be dependant on ASP.NET then you shouldn't use any session
What I could advice:
Use a UserNameValidator, so that you need to send username/password on each request to the wcf service (there are a lot of article on the web on how to configure a UserNameValidator)
Implement an IAuthorizationPolicy where you can retrieve user data to set the roles etc. This object is created once then reused
The problem is that if you only use these 2 components, you'll need to fetch the data for each request as you've no way to transfert the username from the UserNameValidator to the IAuthorizationPolicy
To avoid that, you'll need to implement the complete authentication mechanism in WCF. It's not hard at all, and here is a very nice link that help me to do it in 1 or 2 hours:
http://www.neovolve.com/post/2008/04/07/wcf-security-getting-the-password-of-the-user.aspx
The "PasswordAuthorizationPolicy" (in the link above) is created once, then reused. And for each request the Evaluate method is called.
It means that you can add any custom property on this class, fill them in the constructor, and then use them forever. You don't need to manage this cache lifetime as it's binded to the client channel, so once the client close the connection the channel will expire all these data will be removed from memory
My suggestion is to create class Authentication (or something else) on WCF side:
public class Authentication<T>
{
public static Dictionary<string, T> Users { get; set; }
}
And if you have User class:
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
You can manage users like this:
Authentication<User>.Users.Add("username", new User());

Resources