I currently have a MVC4 home-grown secure token service (STS) that communicates with our own authentication database. All is working just fine with this setup. As a new feature I need to add the ability for single sign on (SSO) through ADFS2 for those users that are on the domain (bypasses the current un/pw screen, and they're just 'in'). To be clear there really are 3 different login possibilities that need to be handled: domain user (SSO), domain credentials (domain user not on domain entering their domain un/pw), and the original un/pw auth from database. Knowing what I know about adding web.config settings to the relying application to wire up the STS, how would I wire up both wsFederation passive redirect options (current redirect to STS for un/pw, and the ADFS option)? Is this something that would have to be handled in code, through an overloaded class such as WSFederationAuthenticationModule? What would be the best way to handle what I want? Any code examples? Thanks for your time!
You just have your login screen on your custom STS and two additional buttons, "login with ADFS" or "login as domain user". Both buttons are redirects to two other STSes your STS is federated with (your STS plays then role of either an Identity Providing STS or a Relying STS).
That is not very complicated. What you need is to create two SignInRequestMessages and using their WriteQueryString build two urls to two different STSes. Another way would be to use the WSFederationAuthenticationModule::CreateSignInRequest method.
http://msdn.microsoft.com/en-us/library/system.identitymodel.services.signinrequestmessage(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.identitymodel.services.wsfederationauthenticationmodule.createsigninrequest(v=vs.110).aspx
Consuming responses is tricker as you need a single uri (or two different uris) that play an endpoint roles. In the uri you need a token receiver and try to create a token out of the SAML sent by the provider.
If you peek at the source of a community replacement of the wif:FederatedPassiveSignIn method I wrote once, you will get the idea
http://code.google.com/p/net45federatedpassivesignin/source/browse/trunk/+net45federatedpassivesignin+--username+wzychla#gmail.com/Community.IdentityModel.Web/Controls/CommunityFederatedPassiveSignIn.cs?spec=svn6&r=6
(at least half of the code is responsible for the WebForms user control infrastructure but the other half is what you are looking for)
Unfortunately also, such custom mixed scenario is not easily handled with just the configuration of federation modules.
Related
Looking for guidance to understand the use case behind ForceAuthn=true for SAML-driven Single Sign-On.
We know that ForceAuthn=true will always challenge the user for credentials which creates friction thus negative experience for the user.
However, that's UX story. What about security?
If ForceAuthn=false, I authenticate once and the second time a seamless login will happen.
This might create an issue where unware user using public PC can leave the access open for the next person.
If you have are (or work) for a provider (e.g. SaaS) and have SAML-driven SSO with clients, what is your policy/experience around this topic?
It's not common for service providers to set ForceAuthn=true. As the service provider, it's not your decision on how to authenticate a user when you are entrusting that process to the identity provider. And, what happens when the IdP is using a non-interactive authentication mechanism like Kerberos? While they may see the redirects occurring, there's no user interaction with or without forcing authentication. Point being, if you're outsourcing authn, then outsource it, and then have the IdP indemnify you for anything around authentication.
What I do see service providers doing is using ForceAuthn=true to use as "singular transaction authorization" like for authorization of steps in workflows and digital signing.
I was trying to register an Application Login Module in Websphere but I don´t find any easy example in web.
There are a lot of IBM documents, but too much complex, and I can´t figure out how to register an Application Login Module.
I already have success with a System Login Module bounded to WEB_INBOUND, it works, but affects all my system. I want a Login Module to serve only my applications web, with JAAS authentication.
I´ve tried to bound a login module to existing WSLogin but it doesn´t seems to be working.
Any help ?
tks[]
You need to setup security domains to get the separation you are looking for wrt to the login configurations. The security framework uses the WEB_INBOUND login configuration to authenticate the user for all web applications irrespective of adminConsole or user applications. When you create a security domain and customize the WEB_INBOUND configuration at the server/cluster domain level, it will be used for all the user web applications deployed in those processes. You need to setup the multidomain in a cell topology and assign the domain to the server/cluster where you applications are deployed.
Once you setup the domains, the WEB_INBOUND configuration at the server/cluster domain will be used by the user applications hosted in that server/cluster while the WEB_INBOUND configuration at the admin/global domain will be used for the adminConsole application at the Deploymener Management process where it is deployed.
The application JAAS login configurations are meant to be used by the applications directly. One can create an application login configuration and programmatically use it in the application to perform direct login -
LoginContext lc = new LoginContext("myAppLoginCfg1", callBackHandler);
I asked around and this is the answer that comes from the owner of container security:
The WEB_INBOUND is a JAAS system login that is always configured by default. However, you can specify your own JAAS application login or customize the existing WEB_INBOUND system login. If you want only one application to use a different JAAS login from all your other applications, you can use a security domain that has those different security configurations. The only catch is that application server has to be in a separate server from the other apps. That way, you can map your security domain to that server.
Here's an info center article about security domains:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/tsec_sec_domains_config.html?cp=SS7K4U_8.5.5%2F1-8-2-33-1
And one on application logins:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/rsec_logmod.html?cp=SS7K4U_8.5.5
And system logins:
http://www-01.ibm.com/support/knowledgecenter/#!/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/usec_sysjaas.html
And here is a much more practical answer that comes from the security dev lead:
So an additional question is - why would you want to do that? Do you want to do anything specific for just one app during login that you do not want for other app logins? (I would think so) You can get the app name in your custom login module and can use that to provide your own app based login requirement in your login module (or skip it) if needed.
Me: Ya, this is what I would do. You can also implement this based on what is in the request. I did one where it would request a SAML token from an STS and put it on the runas subject if I could tell that the request came from WebSeal (and not if it didn't).
If what you need to do for the 'app-specific' case requires skipping what is done in ltpaLoginModule and wsMapDefaultInboundLoginModule (that should run for the other apps), you can't really do that. However, you can modify their behavior.
Read through the task I've given a link to below. Yes, I understand it is a WS-Security task, but its about using APIs. You'll get what I'm talking about if you read closely, particularly the 3rd ("When a caller...") and 5th ("To use a..") paragraphs. The parts that you should be concerned about in the code is the WSCREDENTIAL* stuff.
http://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/twbs_config_wssec_caller_no_reg.html
I'm looking for a bit of best-practice advice from someone a bit more knowledgeable than me in the Federated Security area.
Our Scenario
We host a (subscription) webservice (WCF/Asp.Net/IIS). We also have a purely JavaScript component (widget) that our customers embed within their intranet applications. The widget calls the webservices for data so therefore we need the widget to make cross-domain requests from their domain to our domain.
The widget currently does this using a combination of JsonP and Script Tag Injection approach to Ajax. (Reason - a combination of the age of the widget and continuing support for older non-CORS browsers).
The Problem
All of our customers require a Single-SignOn so their users are not asked to login to the widget. We have achieved this in until now by issuing an ApiKey to a new user and asking them to enter that into the widget on first use, and a cookie is then created for use thereafter.
We need to integrate Federated Authentication into this scenario. The webservice (on our domain) is the Relying Party (RP) and the widget (hosted on the customer domain) is the Client. The Identity Provider and STS would also be on the customer domain.
From my research so far I think I can make the following statements:
This scenario requires an Active Federation approach. Passive Federation is never used when the RP is a webservice.
We need to add Federated endpoints to our WCF service to allow an Active client to call us supplying a Saml token.
Making our widget an Active client that communicates with the webservie directly is not possible. This would require the Widget to request identity and pass it onto the RP. This would be too much for a JavaScript only app.
Possible Solutions
Is it actually up to the host page of the widget (aka. the customer's intranet application) to be the Client in the FedAuth scenario?
We could provide a proxy that would be hosted in the customer domain and act as the Active Client for our webservices RP. The widget could then be unaware of any authentication.
Are we missing something really obvious?
I would really appreciate a couple of words in comment on the above if you can help us out and can spare the time. I'd be happy to hear that my assertions are incorrect as well. All news is good news at this point...
We eventually found a workaround:
For customers who want Saml Authentication we host the widget component in our domain in a standalone webpage and they embed in their webpage using an iframe.
this approach achieves the appearance of widget integration within their site, although not as originally intended, and it allows us to leverage Passive authentication. The iframe behaves just like a normal browser in that respect and handles the handshake with the STS server.
This is less than ideal but we were unable to come up with anything better. It suits our customer's needs whilst maintaining security. That doesn't mean I have to like it though.
I have a main website running on AppEngine. It's on a subdomain like main.example.com. This main application is a content portal for our customers. It offers an Ajax application built on YUI. Customers can upload data to it. Users authenticate using Federated Login.
The Ajax application on it allows users to process the data previously uploaded. To do it it should use an webservice running on other subdomain like service.example.com. The webservice does not run on AppEngine but on our services - it's CPU heavy and built on other set of technologies. It would need to download the data on main application - but the downloading service - like everything on the main application - is behind the authentication wall.
I could programatically always allow the service to download wharever it wishes but I think this can turn into a major security problem.
How can I reuse the OpenID authentication "token" to allow it (the service) to appears to the main application as the authenticated user so it can download data? Or If I can do this what would be the best way to accomplish what I intend to do?
You can't really reuse the authentication token. What you should use is something akin to OAuth, though since you control both ends you can make it somewhat simpler:
Generate a shared secret, accessible by both main.example.com and service.example.com
When a user accesses service.example.com for the first time (no authentication cookie), redirect them to main.example.com/auth?continue=original_url (where original_url is the URL they attempted to access)
When you receive a request to main.example.com/auth, first log the user in the regular way (if they're not already). Then, take their user ID or other relevant credentials, and generate an HMAC from them, using the shared secret you established in step 1. Redirect the user to service.example.com/finish_auth, passing the computed HMAC, the authentication details such as user ID, and any parameters you were passed in such as the continue URL.
When you receive a request to service.example.com/finish_auth, compute the HMAC as above, and check it matches the passed in one. If it does, you know the request is a legitimate one. Set an authentication cookie on service.example.com containing any relevant details, and redirect the user back to their original URL.
This sounds complicated, but it's fairly straightforward in implementation. This is a standard way to 'pass' credentials between mutually trusting systems, and it's not unlike what a lot of SSO systems use.
We have one web application (sharepoint) that collects information from disparate sources. We would like to be able to link users to the main websites of those various sources and have them pre-authenticated. I.E. they enter their credentials for the other sources (which are a number of different types LDAP, AD and home grown!) and we retrieve some information for them, and remember there details (Possibly Single Sign-on to keep em nice and safe). The user can then click a link that will open the full app in another window already authenticated.
Is this even likely to be possible?
Office Server has a Single-Sign-On api as a builtin feature. you may want to look into that. It enables you to register user credentials securely, and to access it at runtime.
You need to act as a web browser acts to different sites with storing credentials (usually in cookies) locally. Use therefore a a proper client library with cookie support. This could go probably for most of sites. There are sites using HTTP authentication, which are also easier to access from appropriate client libraries. The most demanding can be access to SSL websites, but again, most client HTTP libraries cover that nowadays as well.
All you need now is just to prepare your web application to act as a proxy to all those separate web resources. How exactly this is done in Sharepoint, well, I hope others will answer that...
True Single Sign-on is a big task. Wikipedia describes common methods and links to a few SSO projects.
If you want something lighter, I've used this approach in the past:
Create a table to store temporary security tokens somewhere that all apps can access.
From the source app (Sharepoint in your case), on request of an external app, save a security token (maybe a guid, tight expiration, and userid) in the token table.
Redirect to a request broker page/handler in the destination app. Include the final page requested and the guid in the request.
In the broker, look up the security token. If it exists and hasn't expired, authenticate, authorize, and redirect to the final page if everything is good. If not, send a permissions err.
Security-wise, a guid should be near impossible to guess. You can shrink risk by letting the tokens expire very quickly - it shouldn't take more than a few seconds to call the broker.
If the destination app uses Windows Auth and doesn't have role-based logic, you shouldn't have to do much. Just redirect and let your File/UrlAuthorization handle it. You can handle role-based permissions with the security token db if required.