How to change session token/cookie format in cookie when navigates to other website? - asp.net

I have 2 web applications, one is ASP.NET MVC 5 + WIF hosted in IIS, another is a web service based on WCF and self-hosted. Both of them are under same domain (so there are no security issues to change cookie format) and referring to the same STS (in same security realm), so theoretically if one user already authenticated, he should be able to access other entities within same security realm without authentication.
However, these 2 websites are using different session token format. For ASP.NET MVC 5 project, it uses WIF implemented standard security session token and serialized to cookie; for WCF web service, it uses its own token/cookie format.
Then we have a problem.
When user navigates from ASP.NET MVC website to WCF web service, because WCF web service cannot recognize WIF session token (FedAuth and FedAuth1), so it redirects user to STS and login again, that is not the biggest problem, the biggest problem is, after use logged in, and POST raw SAML2 token back to WCF web service, WCF web service creates its own format token and tries to set client cookie, it actually doesn't work, I guess maybe there are already FedAuth and FedAuth1 cookie in header so header cannot accommodate more tokens (4K limit?)? Having thought about this for a while, there are are several solutions come into my mind:
Unifying token format. I need to subclass SecurityTokenHandler (maybe also need to subclass CookieHandler), use the same token format that WCF service uses, so when jumps to WCF web service, it can recognize the session token. That needs to dig deep into FAM and SAM.
Force re-login. I can clear FedAuth and FedAuth1 cookies before navigates to WCF web service, it is acceptable that user needs to login again, this is a short term fix, but how can I capture this navigation away event and clear cookie? The only way I think I can do is before I change window.location.href, use jQuery.cookie to clear cookie, I am not sure if it is the correct way, this is my first question.
Adding a cookie translation layer between ASP.NET and WCF, use WIF session token in ASP.NET website, and when jumps to WCF web service, change the token format. But for this solution I don't know how to capture the jump action and how can I get raw SAML2 token? May be I can save it in WSFederationAuthenticationModule_SecurityTokenReceived event handler? But how to deal with multi tokens from multi users and multi sessions?
Are there other better suggestions?

Related

Reuse same Identity in MVC app as authenticated by Web API

We are trying to take user login thru an MVC app (not redirect), but have primary authentication done through a Web API 2.0 endpoint, but also be able to authenticate user access to pages from that point on. Naturally we would track the token needed to authenticate future API calls.
However, there is no established User.Identity in the MVC app since we are doing this externally, and we need this User.Identity to enforce authentication for the MVC pages themselves (on a level before it reaches the controller).
So how can I adopt or impersonate the user?
I would've thought the general area of external auth would be it, but when I look at the diagrams showing how it would work, both seem to involve the user's machine directly interacting with the authenticating server (http://www.asp.net/web-api/overview/security/external-authentication-services). We want the API to be inaccessible by the user's machine, except through the web app, so redirects of requests TO the API are not acceptable.

How to authenticate webservice request?

I have an asp.net webforms solution that uses Identity for authentication. Within the solution I have some webservices that handle ajax requests for the site. The controller apis require authentication, which is not a problem from within the solution, since they receive auth cookie from the session. (Or atleast that's how I understood it).
Question is how do I handle authentication when calling the webservice outside the solution, for example from an android app or an outside web page etc?
The calling user should be authenticated, so that only user-relevant data can be accessed.

using WIF in ASP.NET Web API Service

I am trying to do something like this:
I have a MVC4 Web App and a Web-API service (hosted on two separate roles in azure)
Another role runs CustomSTS1.
The MVC Web App trusts the CustomSTS1
Now the customer logs into the site he is redirected to the STS login page.
Once logged in, he is redirected back to the MVC Web Site.
From this web site, the customer performs actions, which in turn invoke the web-API Service.
I have the SAML token in the web app, which I pass to the WebAPI service.
Now when I try to validate the SAML token at the Web API side, I get a
Message=ID1032: At least one 'audienceUri' must be specified in the SamlSecurityTokenRequirement when the AudienceUriMode is set to 'Always' or 'BearerKeyOnly'. Either add the valid URI values to the AudienceUris property of SamlSecurityTokenRequirement, or turn off checking by specifying an AudienceUriMode of 'Never' on the SamlSecurityTokenRequirement.
This is without the Web API service trusting the CustomSTS1
Once I setup the trust,
I am always given a HTTP 401: UNAUTHORIZED, whenever I try to make a HTTP Get request to the WEB API Service.
Now, My Question is, (I know that my current approach is definitely wrong)
How do I setup the Trust relationship with the CustomSTS1, such that the WebAPI service is able to do an ActAS on behalf of the user logged into the MVC site?
OR
Is this architecture wrong?
And is there another way to achieve this?
That approach is wrong conceptually. The MVC application should negotiate a new token for the Web API in the STS using ActAs. That's how it traditionally works for SOAP Services. However, Web APIs are moving away from SAML as it is a complex format that relies on different WS-* specs. OAuth 2.0 is becoming the standard in that area if you want to support SSO at that level.
Another approach is to establish an implicit trust between the MVC app and the Web API, so all the calls to the Web API from the MVC app are done through a more standard Http auth mechanism like Basic Auth using an specific set of credentials that only the MVC app knows. The info about the logged user in the MVC app is passed as additional information.
Regards,
Pablo.

Custom membership that uses web service for authentication

I'm building web portal in ASP.NET MVC 3 that uses distant web service as only way to communicate with database. Web service has requirement to always have Username/Password passed in request header, otherwise it rejects the call.
I have overridden ASP.NET Membership so that my ValidateUser method sends Username/Password to web service Login method, and returns true/false if authentication is successful. It works quite nice with AcountController provided with MVC 3 Empty internet template. Since I have to pass Username/Password on every web service call, I'm saving them in Session.
My problem is:
If I close browser and reopen it... I remain logged to website, but my Session variables are expired, so none of my requests to web service are being accepted, even though I'm still logged with credentials.
I'm looking for nice suggestion how to sync user logged in state with session state. Either to keep them both persistent until log off is used or to have them both dispose on browser being closed.
Thanks for all suggestions :)
When the user signs in using your AccountController, try setting the auth cookie like this:
FormsAuthentication.SetAuthCookie(model.UserName, false);
This should tell ASP.NET to delete the cookie when the browser window is closed. Then, when user opens up a new browser, both the session and the auth cookie should both be destroyed.
Sessions are cookies on the client side. Forms Authentication (which uses your membership provider) also uses cookies.
They are different.
Is your auth ticket or cookie persistent? This MS KB will explain things and scenarios in more detail than I would here...
Hth.

Console Application with ASP.NET Authentication

Here's the situation, I've got a console application that needs to run once a day and make a few requests to pages that require authentication to view. The pages are hosted in a really basic ASP.Net Web Application.
So, I know that in order for the requests to go through successfully I have to authenticate with the server. So I've hooked up the console application to the ASP.Net Membership Provider I'm using for the web app and it successfully determines if a set of a credentials are valid. However, after calling Membership.ValidateUser() any requests I make just get the login screen. After doing some reading it seems that this is because I'm missing the important cookie information that persists my login or what-have-you.
I'm using a basic WebClient to make the requests and then reading/discarding the result.
So the meat of the question is this: Is there a simple way to validate the login information and hold on to it so that I can make the requests successfully, or is this the exact same case as the other two questions I found that require the WebClient to make a "manual" login request to the login.aspx page and try to hold on to the cookie from there?
The questions I'm referencing are:
Authenticating ASP.NET MVC user from a WPF application
and
Login to website and use cookie to get source for another page
With FormsAuthentication the webserver has to generate a Forms Authentication Ticket for you. The best (only?) way to do this is to log into the site, so I'd just log in like the other questions.
If the intent is to send data to the server and/or get data from the server, then the most logical architecture is probably to create a web service using either ASMX or WCF. Then configure the service to use a security token, such as a username token or a SAML token. This will make the client less likely to break when the server code changes its data model.
Otherwise, if you wish to use only a basic WebClient, then you will have to find a way to pass your credentials to the login page and retain the login cookie that is returned from the login request. Then, make sure that the login cookie is included on all subsequent requets, similar to the Stack Overflow question that you referenced, "Login to website and use cookie to get source for another page".

Resources