MVC 5 + ASP Identity authorization - sharing cookie in subdomains - cookies

I have local website with subdomains like:
localhost:55307
aaa.localhost:55307
bbb.localhost:55307
It works perfectly except authorization - if I log in in localhost:55307 I'm not logged in aaa.localhost:55307 because my subdomains are treated as separate domain. I looking for solution but I can't find any for Asp Identity (Form authentication in MVC 4 it's useless).
Based on some questions and answers in SO I did:
Edit CookieAuthenticationOptions class in Startup.Auth.cs as below:
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieDomain = ".localhost",
ExpireTimeSpan = new TimeSpan(0,12,0,0,0),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
Get MachineKey from IIS Manager and add to web.config:
<system.web>
<authentication mode="None" />
<machineKey validationKey="61D42DE996486DEA64CEA26C0373C547E0D07108789662C2D2E15210A65C475925055009D962FEB3D5D93E9BEA3E3717187F1BCBF63E386EB198F641E6157044" decryptionKey="06CF7C1C31BDBD4E7056D0F3531BE253E98A658B50974155" validation="SHA1" decryption="Auto"/>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" maxRequestLength="1073741824" />
</system.web>
Now i can login but cookies aren't shared - I still logged in one subdomain.
PS. I now that there is a lot of similar questions in StackOberflow but no one of them is about MVC 5 and ASP Identity and no of them got solutions.

Related

HTTP 500 error on forced HTTPS redirects with external logins

I have a load balancing environment on AWS powered by Elastic Beanstalk. The SSL certificate is applied on the load balancer. To force https redirects, i have followed the accepted answer in this post Redirect to https through url rewrite in IIS within elastic beanstalk's load balancer. These are the exact lines of code which i have written in web.config
<rules>
<rule name="Force Https" stopProcessing="true">
<match url="^healthcheck.html$" negate="true" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
This is working perfectly for everything else apart from external logins. Whenever i try to login from external providers, it gives HTTP 500 error. If i remove these lines, then logins are working perfectly both on localhost and on AWS. Kindly help me get a solution so that i am able to force HTTPS redirects and successfully get external logins.
Another thing worth mentioning is that without forced redirects, external providers redirect to http version of the site, even when i request from the https version.
Update
The exact code i am using for facebook login is as below
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
AppId = "xxx", // production values
AppSecret = "xxx",
BackchannelHttpHandler = new FacebookBackChannelHandler(),
UserInformationEndpoint = "https://graph.facebook.com/v2.7/me?fields=id,name,email,first_name,last_name",
Scope = { "email" },
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new Claim("FacebookAccessToken", context.AccessToken));
return Task.FromResult(true);
},
OnApplyRedirect = OnApplyRedirectHttps
}
});
Your application is running into an issue where it thinks it's using HTTP, but in reality it's using HTTPS. This is due to the HTTPS-to-HTTP connection-swap that's happening from the ELB.
So, whenever your app is using the request URL, you need to look at the X-Forwarded-Proto header.
This header will tell your application whether HTTP or HTTPS was used to connect to the ELB.
Source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
As part of the external login redirect (to Facebook, Twitter, etc.), your app will very often attach a return URL. You need to ensure that URL is using HTTPS rather than HTTP.
Query the X-Forwarded-Proto header to determine which is used and ensure your return URL has the proper protocol.
This is going to become a common theme in your app. Just get used to doing it this way.
Update:
For example, as per this SO article:
change facebook redirect_uri web api
you will want to put the following code at the start of your Startup.Auth.cs file:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});

Spring 4 REST web-services not working with security

I am using Spring 4, with Spring Security 4 to secure web-services. A normal web-service worked fine without security. My secured web-services also seemed to work great working locally and with unit testing.
We are using the SiteMinder example, which means we have authentication happenind from a remote authority. This delivers a token to the browser when we login. We pass the authentication token with a request header, and this is pulled from customerUserDetailsService. That class and methods pull the token from the header, authenticates the user against that remote authority, and we get a username. From that username, we make a DAO call to our database to get the User Details and their Roles, which in the Spring Security Context uses the roles to grant authority. This is all working fine, and we get an authenticated user and we have thier roles/grantedAuthorities.
So, as previously stated, we are now just securing web-services with spring-security.xml to secure the web-services based on the role of the user. Again, this all seemed to work fine with unit testing. We had a token for a user who did not have access to web-sites and we correctly got back a 403 error. When we used a token for a user who did have the right role, was able to execute the web-service.
Now I am trying to deploy this into a new environment, and I am not having much luck.
So, I have a spring-security.xml that looks like:
<http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">
<!-- Additional http configuration omitted -->
<intercept-url pattern="/records/authorizedRecords" access="hasRole('portalUser')" />
<intercept-url pattern="/records/myCode" access="hasRole('portalUser')" />
<intercept-url pattern="/users/email" access="hasRole('appAdmin')" />
<custom-filter position="PRE_AUTH_FILTER" ref="openAmFilter" />
</http>
<beans:bean id="openAmFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<beans:property name="principalRequestHeader" value="openam_token"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:property name="userDetailsService" ref="customUserDetailsService"/>
</beans:bean>
</beans:property>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<beans:bean id="customUserDetailsService" class="com.agmednet.server.security.CustomUserDetailsService"></beans:bean>
<beans:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
When we tried access to:
<intercept-url pattern="/users/email/*" access="hasRole('appAdmin')" />
this did not seem to match:
/rest/users/email/myemail#someemail.com
so I changed it to:
<intercept-url pattern="/rest/users/email/*" access="hasRole('appAdmin')" />
And I get this from the log.
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/rest/trials/integratedtrials'; against '/rest/users/email/*'
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted
DEBUG: org.springframework.security.web.FilterChainProxy - /rest/trials/integratedTrials reached end of additional filter chain; proceeding with original chain
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
At this point, I know we have an authenticated user, the username, and the roles are listed right there in the logs. We seem to find a matching URL in the spring-security.xml, the URL matches, the roles match, and now I feel we should be executing the logic behind the web-service, but I get an error message:
Apache Tomcat/8.0.30 - Error report
/services/rest/users/email/myemail#someemail.com
The requested resource is not available.
I am absolutely floored here .... unsecured web-services work great. I have to be missing something? Is it with the word "rest" in the URL? Web-services have always worked when they were unsecured. I added security and add unit tests to test this all out, and now I am unsure of what happened?
The problem is that I am an idiot!!!!
In the /WEB-INF/web.xml file I had this defined:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
I suppose that is why when I call any RESTful web-services with:
/rest/users/email/myemail#someemail.com
it doesn't work.
But when I use:
/api/users/email/myemail#someemail.com
now it works.
Conclusion: I am an idiot!!!

Sitecore ItemWebApi - "Access to site is not granted"

Sitecore ItemWebApi Gurus,
Why am I getting a response of "Access to site is not granted" every time I attempt to make a Sitecore ItemWebApi request?
Here are the security settings in my Sitecore.ItemWebApi.config
<site name="website">
<patch:attribute name="itemwebapi.mode">StandardSecurity</patch:attribute>
<patch:attribute name="itemwebapi.access">ReadOnly</patch:attribute>
<patch:attribute name="itemwebapi.allowanonymousaccess">false</patch:attribute>
</site>
</sites>
Here's how I'm setting up my ItemWebApi request (please note that I have used a fake username, password, and GUID for the purpose of stack overflow):
var client = new WebClient();
var n = new NameValueCollection();
n["X-Scitemwebapi-Username"] = "extranet\\Sample_Username";
n["X-Scitemwebapi-Password"] = "SamplePassword";
client.Headers.Add(n);
var result = client.DownloadString(
"http://localhost:11111/-/item/v1/?sc_itemid={11111111-1111-1111-1111-111111111111}&scope=c");
The response I get back from my request is always:
Access to site is not granted
I'm using sitecore 7.1.
Turns out I was using the wrong password for the user. The code above in my question is perfectly valid and will return a json response containing the desired information about a sitecore item.
I'd like to also add that you need to verify that the sitecore user which you are trying to authenticate with has been "enabled" in sitecore. I had added a user for my Item Web Api through a sitecore package and wasn't aware that when you do that, sitecore by default disables the user. You actually have to manually "enable" the user before it is active.

Integrated Windows Security when calling an ASMX service

I have some issues with an ASMX web service running on Win XP with IIS 5.1. The IIS is set up with Integrated Windows Authentication and with anonymous access disabled. (When I have anonymous access enabled, everything works as a charm.)
However, when I turn of anonymous access and run with only Integrated Windows Authentication on my IIS, I get the following exception:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.
This exception is generated from my really simple console application that I'm using just to test the concept:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; // .None;
binding.UseDefaultWebProxy = false;
EndpointIdentity spn = EndpointIdentity.CreateSpnIdentity("WORKGROUP/VirtualXP-91051");
Uri uri = new Uri("http://169.254.91.91/MyWebSite/MyService.asmx");
EndpointAddress address = new EndpointAddress(uri, spn);
MyServiceSoapClient client = new MyServiceSoapClient(binding, address);
client.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
String req = "( the request string is blanked out.. ;) )";
string resp = client.ReqAddressData(req);
Console.WriteLine(resp);
Console.ReadLine();
The interesting part of App.config:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
This isn't rocket science, so I must be missing something obvious. I've done some searching here on SO, and eve though I can find many similar questions I've found nothing that solved my problem.

Problems with Oracle Membership Provider and Framework 4

I'm having serious problems with creating a Web service in Visual Studio 2010 (Framework 4).
Anyway, I have to use a Oracle membership provider (I have installed "Oracle Providers for ASP.NET 4 11.2.0.2.0', which modifies the framework's machine.config), but I can not connect to the membership.
My code in web.config is as follows:
<configuration>
<connectionStrings>
<remove name="OraAspNetConString"></remove>
<add name="OraAspNetConString" connectionString="User Id=USUARIO;Password=PASSWORD;Data Source=DATABASENAME;" providerName="Oracle.DataAcces.Client"/>
</connectionStrings>
<system.web>
<membership defaultProvider="OracleMembershipProvider" userIsOnlineTimeWindow="30"/>
<roleManager defaultProvider="OracleRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All"/>
<authentication mode="None"/>
<authorization>
<allow users="*"/>
</authorization>
I also added the reference 'System.Web.ApplicationServices' to my project.
To test the connection to the membership of Oracle I have put this code in one of the OperationContract that has my web service:
MembershipUserCollection userC = Membership.GetAllUsers();
sample.StringValue += " - " + userC.Count;
bool resp = Membership.ValidateUser(id, id2);
The obtained MembershipUserCollection always appears without users. UserC.Count always equals zero.
The parameters 'id' and 'id2', username and password respectively, are used to validate (that is a poor use, I know) but always returns false.
Anybody can help me with this?
Thanks a lot.
PD: Authentication mode is 'None', I've tried with 'Forms' and still not working.
Problem solved.
I needed to put the name of the application (applicationName) on the label of the membership and role manager providers (in the file machine.config).
:-)