How to access the ACS token on mvc application? - c#

I am using Access Control Service (ACS). I configure my MVC-4 application to use ACS. I put the return url to my controller, which is http://127.0.0.1:81/ACS/LogOn and after logon with any identity provider we are successfully return to the controller. But now can anybody please tell me how i can access the issued token in the controller ?

Assuming that you've used the normal WIF-based mechanisms to configure your app to use ACS, everything you need should be accessible via Thread.CurrentPrincipal. In most cases, you don't want the token itself but instead you want the claims within it. See this example.
If you actually need the underlying token in XML/string form rather than the claims (I wouldn't recommend this most of the time) then you can get it by setting SaveBoostrapContext in your service configuration to true and accessing it via the BootstrapContext property on the claims identity.
Thread.CurrentPrincipal.Identity.BootstrapContext;

Related

ASP.Net MVC - OWIN - Allowing Windows/Individual Authentication

I have an ASP.Net MVC 5 application which is currently using individual authentication (account/login.cshtml page with no authentication/anonymous access) and OWIN. Works fine.
As this is an intranet app I want to allow the users to log in under their windows account, another users windows account or an application account(admin, special user etc. - these accounts have no associated domain account).
For the first option I wanted to display their windows username on the login screen and they can simply click the "ok" button to login. To get the username I modified the Visual Studio Project properties to disable anonymous authentication and enable windows authentication. Also modified the web.config and set the authentication mode to Forms. This causes "HTTP Error 404.15 - Not Found". This appears to be due to an authentication loop caused by OWIN with the following suggestions to fix:
Ensure Login controller methods allow anonymous access (seems to be this way by default).
or Modify Startup.auth, comment out the LoginPath property.
or Modify the web.config, add the appSetting "owin:AutomaticAppStartup" with value "false".
I opted for the LoginPath fix and this appears to work (as does web.config change) in that there are no errors and the login page displays with the windows username (retrieved using System.Threading.Thread.Currentprinciple.Identity.Name).
The problem is now that once the user has logged in the OwinContext has no user ( HttpContext.GetOwinContext().GetUserManager()).
Ideally I don't need IIS or OWIN doing any authentication as it's done by the app - but I need the initial request (for the account/login page) to include the Authenticate headers so I can get the windows user.
Firstly I would like to understand what causes the "HTTP Error 404.15" and fix.
Secondly, how do I get OWIN to work with the authentication change - I just need it to persist the user for controller authentication.
This is just a guess but I believe the error is caused by the misconfiguration you've described: you have set the authentication mode to "Forms" but set the project to use Windows Authentication. It can be confusing but Windows Authentication is not Forms Authentication. When you are using Forms Authentication the user provides the credentials in the form that is submitted, validated (including all anti-forgery goodness) against the user store (I believe you are using ASP.NET Identity which would be a default for "Individual Authentication" setting) and if the validation is successful a cookie to set is included in the response. This cookie is then used to authenticate further requests.
As confirmed by Katana documentation, there is no built-in middleware for Windows Authentication - Microsoft simply assumes that IIS should be used for that. Which effectively prevents us from easily combining Katana OWIN middleware providers with Windows authentication. Now, easily is the key word: we still can "hack" our way around it.
Unfortunately, it still will be a hack: I have not found a way to make the authentication "transparent" (as in "a user opens the login form and can enter both the AD account credentials or the individual account credentials and everything just works"). You will need to maintain the individual account record for every Windows user (as you would do with any external OWIN middleware, such as Google or Facebook). You can automate the account creation and association though and make it look transparent. You can add an "external provider" button for your Windows authentication.
Authenticating the user would look like (in a separate "AD Authentication" controller):
bool userWindowsAuthentication = Request.LogonUserIdentity.IsAuthenticated;
if (userWindowsAuthentication) {
var userStoreDatabaseContext = new ApplicationDbContext();
var userStore = new UserStore<UserModel>(userStoreDatabaseContext);
var userStoreManager = new UserManager<UserModel>(userStore);
var userWindowsLoginCredentials = GetWindowsLoginInfo();
var existingInternalUser = userStoreManager.FindAsync(userWindowsLoginCredentials.UserName)
if (existingInternalUser) {
// It means that the user already exists in the internal provider and here you simply authenticate and redirect to destination
} else {
// It means that the user does not exist. You can automatically create the internal user record here and associate the Windows user with the internal record.
}
} else {
// It means that user is not signed in using Windows authentication, so you either want to redirect back to the login page or restrict access or do something else
}
As you can see, it's "dirty". Another hack: you can have additional layer (separate application or a virtual application) that accepts only Windows authentication. This app can be your log-in resource. If the user is authenticated with Windows AD you can redirect them to the correct login page. You can go even further and add their login info in the redirect request header but if you do so - the header must be encrypted to ensure that Windows authentication cannot be faked and the only thing that should be able to decrypt and validate it should be your main application. Again, dirty, but works.

Refresh identity token from client from code

I am using the fine-uploader with an asp.net mvc backend to upload files directly to an azure blob-storage. The asp.net-server works as the azure-signature-endpoint(sas). This is all secured with an identityserver3 and here comes the problem: The identity_tokens lifetime is set to 5 minutes(as default). And I want the SAS endpoint to be only called authorized. So a user can only access its own data. But after I have the upload running for the set 5 minutes, it breaks. Of course, because it is not authorized and it returns the login-page from the identity-server(which the fine-uploader, of course, can't handle).
It would be easy to solve this problem, by either setting the lifetime from the token to something higher(but this is unreliable as the upload could take hours or days), or disable the lifetime(yeah would work. But I guess the lifetime has a reason to exist).
So my 2 ideas would be:
to just authorize the user once(when he starts the download)
or to refresh the token by code every time the signature gets generated.
First approach
Can I just set a boolean like user is authorized and if this boolean is set just skip authorization and just return the signature or how could I achieve this
Second approach
How would I do this?
Don't use the id token for API access, an instead use access token. Access tokens are for resources (APIs), whilst id_tokens are purely for authentication. The id_token is only meant to be used to provide the RP with means of knowing who the user is - hence no need for long time span. It's only there for converting into a user session (cookie/principal).
With access tokens you have several approaches for keeping a valid token at a client; either by fetching new ones using the client credentials flow or by using the refresh token approach.
I believe there are samples of both in the samples repo of IdentityServer.
Samples repo link

Is it possible to inherit from ClaimsIdentity and have that be passed back to User.Identity?

I'm crafting a custom Owin Middleware to handle logging into .NET web apps using our custom token server.
I've got everything working. The token is parsed into claims for an identity, the identity is put inside of an AuthenticationTicket, and the user is successfully logged in using CookieAuthentication.
I'd like to make querying the claims easier for other developers, so I inherited from ClaimsIdentity. I create an instance of my class and pass it along to the AuthenticationTicket constructor.
My problem is that User.Identity in my controller action is not an instance of my class.
What am I missing? Is something in ASP.NET recreating my Identity instance and simply copying over all of the claims?

How to do ASP.NET Web API integration tests with custom authentication and in-memory hosting

A similar question has been answered here but the answer doesn't seem to work in my case.
I want to test the authentication/authorization process in my Web Api which is using a JWT authentication.
My authentication is handled through a custom MessageHandler that I add to my HttpConfiguration. Authorization in handled by a simple [Authorize] Attribute on Controller/Methods I want to restrict access to.
I'm setting the principal I've extracted from my token this way during authentication (in my custom MessageHandler):
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
This whole process is working fine when I test it manually in a local IIS.
But when testing with an in-memory hosting like here
The ApiController.User property storing the Principal that is used for authorization with [Authorize] get the Thread.CurrentPrincipal in my calling test (the windows principal of my current session) instead of the one set during authentication.
If I set my Thread.CurrentPrincipal to null, I get only bad requests.
TL;DR How do I test my authentication/authorization pipeline with in memory hosting
? As it sets the ApiController.User value to the Thread.CurrentPrincipal value in my test and not getting the one I set successfully during authentication.
I think I can manage to do a work around with implementing a custom [Authorize] Attribute getting the Thread.CurrentPrincipal and not the ApiController.User, but I'd like to avoid that.
Thanks in advance.
EDIT for clarification: all this pipeline (authentication then authorization) is working fine hosted in a running IIS (with an HttpContext which is null during in memory hosting). I'm just trying to test it with in memory hosting (if it is possible). During testing with in memory hosting , putting breakpoints in my custom MessageHandler, I can tell that the Thread.CurrentPrincipal is well set, it's just that [Authorize] doesn't seem to care about that, as, in my ApiControllers the ApiController.User property is already set to the value of my Thread.CurrentPrincipal value in my test (my local Windows session principal)
I have had success following the guidance listed in the "Retrieving and Assigning the Current Principal" section of Chapter 15 in "Designing Evolvable Web APIs with ASP.NET":
In ASP.NET Web API version 2.0, you can solve this problem by using
the new HttpRequestContext class. First, the current identity should
be retrieved and assigned to the current request object, not to a
static property. Secondly, different hosts can use different
HttpRequestContext implementations
In short, in your message handler, do this instead of setting the current Thread and HttpContext's principal:
request.GetRequestContext().Principal = principal;

Token Based Authorization Web API

I'm building an application using backbone.js and web api. JS client will send ajax requests to access api. Building an API is pretty easy but i want to implement authentication and authorization for API.
I'm planning to return a token after a successful authentication and use this token for further requests. This token will be passed in HTTP Authorization headers.
My requirements are as below
1) Verify token on each request and get user id.
2) Use fetched user id for further actions.
First bit can be handled using Custom action filter where the permanent token can be verified against the database.
But i'm not able to find any sample or example for doing a second bit. I want to get a userid from a passed token and carry it further for later processing.
Is there any way of doing it?
Waiting for suggestions or ideas. Any code sample will really help. Thanks in advance.
You can set Thread.CurrentPrincipal upon successful token verification like this:
IPrincipal principal = new GenericPrincipal(new GenericIdentity(username), null);
Thread.CurrentPrincipal = principal;
// if we're running in IIS...
if ( HttpContext.Current != null )
HttpContext.Current.User = principal;
The principal might also be an instance of a custom class implementing the System.Security.Principal.IPrincipal interface (in order to be able to have its user ID associated).
I further suggest you use a DelegatingHandler instead of an action filter for the token verification in order to set the current principal as early as possible during the message lifecycle. Additionally, this way you don't have to decorate every action method/controller with the action filter attribute.
I highly recommend to use OAuth. Anyway, you can set the token and user info in session and use them in subsequent calls. i.e. if the session is active and user info exists then use them otherwise authorize and authenticate user (probably through OAuth) and if it is valid then store them in session to be used in subsequent calls.

Categories