ASP.NET MVC multi-site SSO using OpenID - asp.net-mvc

I am putting a plan together for a series of sites that will share user account information among them. The idea is that once a user logs in using their OpenID, they can access any of the sites and it will know who they are.
What are the common patterns/best practices that i could employ to achieve this?

If all the sites share a common hostname in their URL then you can set an auth cookie (FormsAuthentication.SetAuthCookie) specifying the path of the cookie to be "/" so that all sites can see the user is logged in.
If the sites are not sharing a common host name, I think the only way to get a truly "once signed in, signed in everywhere [within your ring of web sites]" would be for all authentication to happen at just one site (perhaps one dedicated to authenticating the user) and for the other sites to redirect the user to that site for authentication and then that site would redirect back. In essence, that auth site becomes an identity provider, and almost exactly fills the role of an OpenID Provider (in fact DotNetOpenAuth could be used here for this exact purpose). Since it sounds like your goal is to let the user log in with their OpenID, your OpenID Provider on that one auth site could itself use OpenID to authenticate the user. Your own pure-delegation OpenID Provider could be written such that it always responds immediately to checkid_immediate requests as long as the Realm in the auth request is one of your trusted ring of sites. Thus you could effect single-sign-on across all your sites.

Please consider the following Patterns & Practices on Web Service Security from Microsoft:
Brokered Authentication - http://msdn.microsoft.com/en-us/library/aa480560.aspx
The main topic is - Web Service Security
Scenarios, Patterns, and Implementation Guidance for Web Services Enhancements (WSE) 3.0
http://msdn.microsoft.com/en-us/library/aa480545.aspx
Ultimately theres lots of ways you could do it. I achieved a simple single sign on by building a url with a token from one website pointing to another domain. The encoded & encrypted token contained details to submit back to the previous domain. Upon receiving an incoming request on the second domain, an underlying web service checks that the incoming request's token is valid with the previous domain using a shared private secret, known to both domains.

Related

Okta secure web apps on Azure Virtual Machines

We have 2 web applications in production since several years. They are currently only accessible from the intranet of the company. Future changes in the company's organization require to make these applications accessible from the internet. It is planned to use Okta to reinforce security. I don't know nothing about Okta yet. As far as possible, the changes should have as little impact as possible.
Current situation:
Web App 1:
ASP.NET MVC solution secured with userid/password ASP.NET Membership with forms authentication. Userid is an internal user code like ADE465 for example.
Web App 2:
ASP.NET MVC solution secured with userid/password authentication through IdentityServer2 (Thinktecture). Userid is firstname dot lastname like john.doe for example.
All web apps are hosted on IIS on an Azure virtual machine named (let's say) FABVM03.
For the future Okta integration: no need to have SSO (Single Sign On). Would it be possible to simply secure with Okta everything accessed on the server FABVM03? Or everything accessed from a specific URL ?
For example, if someone tries to access https://example.com/webapp1/login.html Okta should comes up and ask for authentication (Okta verify) and if successful allow the user to access the requested url. In fact, the 'already in place' login/password should then be asked as it is already the case. I agree the user would have to enter credentials 2 times: first for Okta verify, next for login the specific web application. But that's okay. As you will have understood, no code modification in the web apps would be necessary in this scenario.
My question is to know if something like that is possible with Okta. If not what is the less impacting possible solution with Okta ?
Okta is not to enforce your policies (PEP), it's mainly SSO and Access Management solution.
Okta has a component, called OAG (Okta Access Gateway), which can be used to reverse-proxy your on-prem applications (which will work in your situation too, as your VPC is effectively equal to "on-prem in a cloud"). Which can do something like you want (protect your application and ask for authentication/authorization), but it's an additional package on top of basic Okta costs.
What you may need is a level of protection added on Azure Network layer, not sure if there is something like that though. I've seen some modules for nginx, capable of intercepting traffic and redirecting it to Okta, if not accompanied with a token. So try to dig into these 2 directions...
You need some proxy-based solution to talk to Okta and enforce the protection for your applications. There are open source tools:
https://github.com/vouch/vouch-proxy
https://github.com/oauth2-proxy/oauth2-proxy
https://github.com/buzzfeed/sso
Or you can checkout some commercial tools:
https://www.okta.com/products/access-gateway/
https://www.datawiza.com/platform/

Restrict client access in a single realm with keycloak

I have a single realm with 3 single-page applications and a shared backend. I want to restrict the access to one of the SPAs so that users without a specific role can't log in.
But once you create a user in the realm, he can log in to every SPA client. I can restrict the endpoints of the backend but I don't want to programmatically reject the user in the specific SPA but automatically on the login page.
I tried to use client roles which don't seem to have an effect in this case. The only solution I have found so far is to create separate realms which I think is conceptually the correct way but unfortunately brings up some practical issues, e.g. the administrators of one realm must be able to manage (CRUD) users of another realm which seems fairly unintuitive.
users without a specific role can't log in - it isn't good requirement. How system will known if user has a specific role without log in (authentication)? Keycloak provides Open ID Connect SSO protocol, which is designated for authentication. After successful OIDC authentication is token generated, which may contains also user role. So only then authorization can be applied. So let's change requirement to: users without a specific role can't access SPA, which better fits into OIDC concept.
The mature OIDC SPA libraries offer authorization guard (name can differs, it is some kind of post login function), where authorization can be implemented. Authorization requires to have a specific role in the token usually, otherwise user is redirected to the custom route, e.g./unauthorized. That's the page, where you can say a reason for denying access. Common use case is also customization of the app based on the user roles. For example users with admin role will see more items in the menu than standard users - that's also kind of authorization. Random example of SPA library with authorization guard (I'm not saying that's a best implementation) - https://github.com/damienbod/angular-auth-oidc-client/issues/441
Keep in mind that SPA is not "secure" - user may tamper code/data in the browser, so in theory user may skip any authorization in the browser. He may get access to SPA, so it's is important to have proper authorization also on the backend (API) side. Attacker may have an access to SPA, but it will be useless if API denies his requests.
BTW: You can find hackish advices on the internet how to add authorization to the Keycloak client with custom scripting (e.g. custom scripted mapper, which will test role presence). That is terrible architecture approach - it is solving authorization in the authentication process. It won't be clear why user can't log in - if it is because credentials are wrong or because something requires some role in the authentication process.
You should indeed not create multiple realms, since that is besides the point of SSO systems. Two approaches are possible in your - presumably - OAuth 2.0 based setup:
restrict access at the so-called Resource Server i.e your backend
use a per-SPA "scope" for each SPA that is sent in the authentication request
The first is architecturally sound but perhaps less preferred in some use cases as you seem to indicate. The second approach is something that OAuth 2.0 scopes were designed for. However, due to the nature of SPAs it is considered less secure since easier to spoof.
I was able to restrict users access to application using following approach:
I've created to clients in my default realm (master) i called my clients test_client1 and test_client2 both of them are OIDC clients with confidential access by secret
I've created a role for each of them, i.e. i have role test_client1_login_role for test_client1 and test_client2_login_role for test_client2.
I've created a two users - user1 and user2 and assign them to client 1 and client2 role. But to restrict access to client1 i have to delete default roles:
That did the trick, when i am logging with user2 i see test_client2 and not test_client1 as available application:
But i did n't delete roles from user1 and therefore i could see both clients when i am log in with user1:
Therefore you should use different clients for your applications, assign to each of a client specific role and remove from users default roles and add one releted to specific application.

IdentityServer3 organisation for multiple api

I have a DashboardApi and an EnterpriseApi on my system. May be one more later.
I am new at IdentityServer3 and I wonder solve my problem.
IdentityServer saves client applications that will use an api. So I have 2 or 3 api. Will I create IdentityServer for all api? Because DashboardApi will consume EnterpriseApi. EnterpriseApi will consume another api.
And users will login to Dashboard application. I could not imagine the organisation.
To answer the question: you may have one instance of IdentityServer being your identity provider/authority across different "resource" APIs as long as they all point back to that same authority when it comes to token validation.
Then an access token used for "DashboardApi" can be used by "EnterpriseApi". It is important to proxy the token properly and in my experience it would be advantageous to create different scopes for each API to have better access as to which calls may be used to proxy into the second API through the first (especially if user consent is a concern).

Logging in with IdentityServer with custom client-side log in page

I have a setup of IdentityServer with configuration of a client with hybrid flow. Is it possible to have an ASP.NET MVC app to use this instance of IdentityServer to log-in the user without looping to IdentityServer's log-in page? That is, use a custom log-in page on the client side to get user credentials and then make a server-side connection with IdentityServer to do the authorization? Is there any sample that demonstrates this? Thanks!
From how I interpret your question, the Resource Owner Password Credential Flow seems to fit your scenario.
See the FAQ-like answer here.
"Q. Which Flow Types designed to be used ONLY in trusted environment (like backend REST API/ micro-services isolated from internet, or owned servers/devices, in general: trusted OAuth2 clients)?
A.
Resource Owner Password Credential Flow (ROPCF) [it involve human: app show its own login page then pass user/pass... to STS].
Client Credential flow [machine to machine (API to API): supply client-id and secret]."
*Disclaimer - I understand you are currently using Hybrid flow- My answer simply implies you could change your solution. If that is not possible, then I would suggest looking into multiple OAuth implementations for an MVC app.
Since I didn't get an answer for this, I'm just posting what I've found so far.
It looks like it is not possible to bypass the IdentityServer's log-in page.
For more info about IdentityServer flows see: OIDC and OAuth2 Flows

ASP.NET MVC 2 and authentication using WIF (Windows Identity Foundation)

Are there any decent examples of the following available:
Looking through the WIF SDK, there are examples of using WIF in conjunction with ASP.NET using the WSFederationAuthenticationModule (FAM) to redirect to an ASP.NET site thin skin on top of a Security Token Service (STS) that user uses to authenticate (via supplying a username and password).
If I understand WIF and claims-based access correctly, I would like my application to provide its own login screen where users provide their username and password and let this delegate to an STS for authentication, sending the login details to an endpoint via a security standard (WS-*), and expecting a SAML token to be returned. Ideally, the SessionAuthenticationModule would work as per the examples using FAM in conjunction with SessionAuthenticationModule i.e. be responsible for reconstructing the IClaimsPrincipal from the session security chunked cookie and redirecting to my application login page when the security session expires.
Is what I describe possible using FAM and SessionAuthenticationModule with appropriate web.config settings, or do I need to think about writing a HttpModule myself to handle this? Alternatively, is redirecting to a thin web site STS where users log in the de facto approach in a passive requestor scenario?
An example of WIF + MVC is available in this chapter of the "Claims Identity Guide":
http://msdn.microsoft.com/en-us/library/ff359105.aspx
I do suggest reading the first couple chapters to understand all underlying principles. This blog post covers the specifics of MVC + WIF:
Link
Controlling the login experience is perfectly fine. You should just deploy your own STS (in your domain, with your look & feel, etc). Your apps would simply rely on it for AuthN (that's why a app is usually called a "relying party").
The advantage of the architecture is that authN is delegated to 1 component (the STS) and not spread out throughout many apps. But the other (huge) advantage is that you can enable more sophisticated scenarios very easily. For example you can now federate with other organization's identity providers.
Hope it helps
Eugenio
#RisingStar:
The token (containing the claims) can be optionally encrypted (otherwise they will be in clear text). That's why SSL is always recommended for interactions between the browser and the STS.
Notice that even though they are in clear text, tampering is not possible because the token is digitally signed.
That's an interesting question you've asked. I know that for whatever reason, Microsoft put out this "Windows Identity Foundation" framework without much documentation. I know this because I've been tasked with figuring out how to use it with a new project and integrating it with existing infrastructure. I've been searching the web for months looking for good information.
I've taken a somewhat different angle to solving the problem you describe.
I took an existing log-on application and integrated Microsoft's WIF plumbing into it. By that, I mean that I have an application where a user logs in. The log-on application submits the credentials supplied by the user to another server which returns the users identity (or indicates log-on failure).
Looking at some of Microsoft's examples, I see that they do the following:
Construct a SignInRequestMessage from a querystring (generated by a relying party application), construct a security token service from a custom class, and finally call FederatedSecurityTokenServiceOperations.ProcessSignInresponse with the current httpcontext.response. Unfortunately, I can't really explain it well here; you really need to look at the code samples.
Some of my code is very similar to the code sample. Where you're going to be interested in implementing a lot of your own logic is in the GetOutputClaimsIdentity. This is the function that constructs the claims-identity that describes the logged-in user.
Now, here's what I think you're really interested in knowing. This is what Microsoft doesn't tell you in their documentation, AFAIK.
Once the user logs in, they are redirected back to the relying party application. Regardless of how the log-on application works, the WIF classes will send a response to the user's browser that contains a "hidden" HTML input that contains the token signing certificate and the user's claims. (The claims will be in clear text). At the end of this response is a redirect to your relying-party website. I only know about this action because I captured it with "Fiddler"
Once back at the relying party web site, the WIF classes will handle the response (before any of your code is run). The certificate will be validated. By default, if you've set up your relying party web site with FedUtil.exe (by clicking "Add STS Reference in your relying party application from Visual Studio), Microsoft's class will verify the certificate thumbprint.
Finally, the WIF framework sets cookies in the user's browser (In my experience, the cookie names start out with "FedAuth") that contain the users claims. The cookies are not human readable.
Once that happens, you may optionally perform operations on the user's claims within the relying party website using the ClaimsAuthenticationClass. This is where your code is running again.
I know this is different from what you describe, but I have this setup working. I hope this helps!
ps. Please check out the other questions I've asked about Windows Identity Foundation.
UPDATE: To answer question in comment below:
One thing that I left out is that redirection to the STS log-on application happens by way of a redirect with a query-string containing the URL of the application the user is logging in to. This redirect happens automatically the first time a user tries to access a page that requires authentication. Alternatively, I believe that you could do the redirect manually with the WSFederationAuthentication module.
I've never tried to do this, but if you want to use a log-on page within the application itself, I believe the framework should allow you to use the following:
1) Encapsulate your STS code within a library.
2) Reference the library from your application.
3) Create a log-on page within your application. Make sure that such page does not require authentication.
4) Set the issuer property of the wsFederation element within the Microsoft.IdentityModel section of your web.config to the login page.
What you want to do is an active signin. WIF includes WSTrustChannel(Factory) which allows you to communicate directly with the STS and obtain a security token. If you want your login form to work this way, you can follow the "WSTrustChannel" sample from the WIF 4.0 SDK. Once you have obtained the token, the following code will take that token and call the WIF handler to create a session token and set the appropriate cookie:
public void EstablishAuthSession(GenericXmlSecurityToken genericToken)
{
var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
var token = handlers.ReadToken(new XmlTextReader(
new StringReader(genericToken.TokenXml.OuterXml)));
var identity = handlers.ValidateToken(token).First();
// create session token
var sessionToken = new SessionSecurityToken(
ClaimsPrincipal.CreateFromIdentity(identity));
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
Once you have done this, your site ought to behave the same as if passive signing had occurred.
You could use the FederatedPassiveSignIn Control.
Setting your cookie like this:
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
Doens't work for SSO to other domains.
To cookie should be set by the STS not at the RP.

Resources