.NET Recaptcha https - asp.net

We've started using the ASP.NET recaptcha control and it works fine. but one of the requirements we have is that all outbound traffic goes over Https.
I know that recaptcha supports https, but It's not clear how to configure (or even if it is configurable) when using the ASP.NET plugin option.
has anyone got any experience of this?
I'll expand a little on what I've found so far....
The Recaptcha package contains 3 public classes
RecaptchaControl,
RecaptchaValidator
and
RecaptchaResponse
RecaptchaControl is an Asp.NET control, the recaptcha specific methods on there seem to be concerning themes/look and feel.
An instance of the Validator has a RemoteIP field (which I presume would represent the verification server), but I can't a way of binding that to the control.
RecaptchaResponse seems to more or less represent an enum with possible responses (valid/invalid/failed to connect).
looks like the Recaptcha control intelligently selects https if the request was https.
I'm presuming it does the same for the validation, but its not clear from source code
http://code.google.com/p/recaptcha/source/browse/trunk/recaptcha-plugins/dotnet/library/
private const string VerifyUrl = "http://www.google.com/recaptcha/api/verify";
private const string RECAPTCHA_SECURE_HOST = "https://api-secure.recaptcha.net";
private const string RECAPTCHA_HOST = "http://api.recaptcha.net";
--------------------------------SNIP------------------------------------
/// <summary>
/// This function generates challenge URL.
/// </summary>
private string GenerateChallengeUrl(bool noScript)
{
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.Append(Context.Request.IsSecureConnection || this.overrideSecureMode ? RECAPTCHA_SECURE_HOST : RECAPTCHA_HOST);
urlBuilder.Append(noScript ? "/noscript?" : "/challenge?");
urlBuilder.AppendFormat("k={0}", this.PublicKey);
if (this.recaptchaResponse != null && this.recaptchaResponse.ErrorCode != string.Empty)
{
urlBuilder.AppendFormat("&error={0}", this.recaptchaResponse.ErrorCode);
}
return urlBuilder.ToString();
}

If you check out http://recaptcha.net/apidocs/captcha/client.html it says:
"In order to avoid getting browser
warnings, if you use reCAPTCHA on an
SSL site, you should replace
http://api.recaptcha.net with
https://api-secure.recaptcha.net."
So clearly recaptcha supports HTTPS submissions. Does the ASP.NET control have any properties you can configure the outbound URL? At worst you might need to use Reflector to examine the code and see how it's built.

The .NET library does not require any configuration to work on HTTPS environment. It will derive from the current HttpContext whether the request is made from HTTPS protocol.
But, there is RecaptchaControl.OverrideSecureMode property that you can use just in case it doesn't work as expected. Set to True to force HTTPS mode.
Update:
I seem to have misunderstood the question. I am afraid there is no HTTPS endpoint for reCAPTCHA verification (between your server and theirs).

We are using the reCAPTCHA plugin for .NET, and we needed to do two things to get it working over SSL in our environment. Our dev environment does not use SSL, and our test and production environments do.
Set the RecaptchaControl.OverrideSecureMode property to true, as Adrian Godong mentioned in his original answer to this question. This allowed the control to work locally and in dev not using SSL, and in test and prod using SSL.
<recaptcha:RecaptchaControl
OverrideSecureMode="True"
ID="recaptcha"
runat="server"
Theme="blackglass"
/>
When we generated the public and private keys, we specified global keys. This allowed us to use recaptcha in all of our different environments (local, dev.mydomain.com, test.mydomain.com and mydomain.com) and fixed the "input error: invalid referrer" error.

Related

Service Fabric Web API Versioning issue

I'm working on a service fabric project with multiple stateless services. When i try to add versioning as in the code below
[Authorize]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class SessionController : Controller
{
...
}
it's not working when calling the service later using Postman or using some client winforms app i made just to call this service. And when i say it's not working i mean it's not looking for a specific version i placed in the controller.
e.g.
I'm calling http://localhost:1234/api/v1.0/session/set-session and as you can see in my controller i only have version 2.0. Now my API gets hit this way or another no matter what version number i put in.
I added code to the Startup.cs
services.AddApiVersioning(options => {
options.DefaultApiVersion = new ApiVersion(2, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ReportApiVersions = true;
options.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
});
Specific API call looks like this:
[HttpPost]
[Route("set-session")]
public async Task<IActionResult> SetSession([FromBody] SessionModel model)
{ ... }
Can anyone tell me what am i missing or maybe api versioning is not supported in service fabric at all?
Thanks.
Does your solution work locally? Based on what I see, I would suspect - no. This should have nothing to do with Service Fabric at all.
Issue 1
I see that your base class inherits from Controller, which is allowed, but is usually ControllerBase. No concern there, just FYI. The crux of the problem is likely that your controller has not applied the [ApiController] attribute. API Versioning defines IApiControllerSpecification and IApiControllerFilter, which is used to filter which controllers should be considered an API. This is important for developers building applications that have the UI and API parts mixed. A controller is a controller in ASP.NET Core and it was difficult to distinguish these two in the early days. There is now a built-in IApiControllerSpecification that considers any controller with [ApiController] applied to be an API. This can be changed, replaced, or completely disabled using ApiVersioningOptions.UseApiBehavior = false.
If your library/application is only APIs, you can decorate all controllers at once using:
[assembly: ApiController]
Since your controller is not currently being considered an API, all requests matching the route are being directed there. The value 1.0 is being considered an arbitrary string rather than an API version. This is why it matches at all instead of HTTP 400. I suspect you must only have one API and it is defined as 2.0; otherwise, I would expect an AmbiguousActionException.
Issue 2
Your example shows that you are trying to version by URL segment, but you've configured the options to only consider the header x-api-version. This option should be configured with one of the following:
URL Segment (only)
options.ApiVersionReader = new UrlSegmentApiVersionReader();
URL Segment and Header
// registration order is irrelevant
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"));
Default (Query String and URL Segment)
// NOTE: this is the configuration
// options.ApiVersionReader = ApiVersionReader.Combine(
// new QueryStringApiVersionReader(),
// new UrlSegmentApiVersionReader());
Side Note
As defined, using the URL segment and header versioning methodologies don't make sense. You have a single route which requires an API version. A client will always have to include the API version in every request so there is no point to also supporting a header.
If you define 2 routes, then it makes sense:
[Route("api/[controller]")] // match by header
[Route("api/v{version:apiVersion}/[controller]")] // match by url segment
Versioning by URL segment, while common, is the least RESTful. It violates the Uniform Interface constraint. This issue demonstrates yet another problem with that approach. Query string, header, media type, or any combination thereof will all work with the single route template of: [Route("api/[controller]")]
Observation 1
You have configured options.AssumeDefaultVersionWhenUnspecified = true. This will have no effect when versioning by URL segment. It is impossible to provide a default value of route parameter in the middle of a template. The same would be true for api/value/{id}/subvalues if {id} is not specified.
This option will have an effect if you:
Add a second route template that doesn't have the API version parameter
You update your versioning strategy to not use a URL segment
It should be noted that is a highly abused feature. It is meant to grandfather in existing services that didn't previously have explicit versioning because adding it will break existing clients. You should be cognizant of that if that isn't your use case.

Spring Security OAuth2 Behind a Proxy Server

There seem to be many examples of Spring Security OAuth2, but most of them run on localhost at some specific set of ports. I was able to get my application working with ports specified for my AuthorizationServer and my ResourceServer. The next step I needed to take was move this application behind a proxy server, but the application stopped functioning. The main issues seem to be path related, but I'm struggling with lack of examples on how to accomplish the task of moving OAuth2 Spring behind a proxy server. I've focused on overriding the WhitelabelApprovalEndpoint, but I'm not sure if this is what is required.
I was able to create a controller that is nearly identical to the WhiteLabelApprovalEndpoint, but do not know how to adapt it to accommodate being behind a proxy.
#Controller
#SessionAttributes("authorizationRequest")
public class ApprovalEndpoint {
#RequestMapping("/oauth/confirm_access")
...
private static String TEMPLATE = "<html><body><h1>OAuth Approval</h1>"
+ "<p>Do you authorize '${authorizationRequest.clientId}' to access your protected resources?</p>"
+ "<form id='confirmationForm' name='confirmationForm' action='authorize' method='post'><input name='user_oauth_approval' value='true' type='hidden'/>%csrf%%scopes%<label><input name='authorize' value='Authorize' type='submit'/></label></form>"
+ "%denial%</body></html>";
...
The only change I made to the class was to update the form action string, making the path relative by replacing
action='${path}/oauth/authorize'
with
action='authorize'
This allows the POST to go to the correct URL
http://localhost/proxy/stuff/javaPath/oauth/authorize
instead of
http://javaPath/oauth/authorize
The latter doesn't map when submitted through Apache (the frontend proxy). But it would seem that this creates other problems in the Java application, because this results in the error
error="invalid_request", error_description="Cannot approve uninitialized authorization request."
I see that this exception is thrown in the AuthorizationEndpoint when the authorizationRequest is null. This looks like it should be handled by my custom class having SessionAttributes set properly, but updating the just the path that I'm POSTing to seems to break this.
May be you already solved it but posting the answer as it may help someone.
It is because authorize end point URL (domain + path(including proxy)) should be consistent. I mean either it should be 'localhost' or your proxy path but it should be consistent.
As OAuth uses session internally and later fetches it from the same path (when the POST happens) . So if the URL changes (POST) it wont get the session then it throws Cannot approve uninitialized authorization request.
For my case ,I was using the authorize end point as:
https://mydomain/myapp/oauth/authorize?grant_type=authorization_code&client_id=clientid&redirect_uri=http://localhost:8181&response_type=code
but in the properties I was having :
server:
session:
cookie:
path: /appProxy
context-path: /myapp
port: 8081
After successful authorization when POST is done on it tries to fetch the session from /appProxy/myapp instead of /myapp and resulting in Cannot approve uninitialized authorization request.
So to solve this, I can either remove Session.cookie.path property or run Oauth server on https://mydomain/appProxy/myapp/oauth/authorize to make it consistent.

Check for a static file during Application_BeginRequest?

I have a Global.asx file that needs to do custom authentication, auditing and profiling stuff. This is needed because it supports a SAML based SSO system and needs to override the normal .Net authentication (which doesn't support either SAML or mixed authentication)
I don't want to fire it for static files, such as .js, .css, .png, etc
In Cassini/WebDev and IIS7 it does.
What I want to have is some simple check, like a this.Request.IsStaticFile (which doesn't exist, unfortunately) to identify the static files.
I realise that this would be fairly simple to write, but it feels like something that must already exist - IIS has already applied caching policy stuff for the static files and so on.
I need a code solution, rather than an IIS config change one.
Update
This is my current workaround:
/// <summary>Hold all the extensions we treat as static</summary>
static HashSet<string> allowedExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".js", ".css", ".png", ...
};
/// <summary>Is this a request for a static file?</summary>
/// <param name="request">The HTTP request instance to extend.</param>
/// <returns>True if the request is for a static file on disk, false otherwise.</returns>
public static bool IsStaticFile(this HttpRequest request)
{
string fileOnDisk = request.PhysicalPath;
if (string.IsNullOrEmpty(fileOnDisk))
{
return false;
}
string extension = Path.GetExtension(fileOnDisk);
return allowedExtensions.Contains(extension);
}
This works and is quick enough, but feels horribly clunky. In particular relying on extensions is going to be error prone if we add new static files not thought of.
Is there a better way without changing the IIS config?
You might be able to check which handler is dealing with the request.
In IIS6 only .net files, eg aspx are mapped to a handler that does stuff.
In IIS7 with the integrated pipeline, everything routes through .net, which is normally a good thing. Different handlers still deal with different file types though. In particular I believe the staticfilehandler is the one you need to check for. The httpcontext.handler property should allow you to figure it out.
You could create an extension method to add that IsStatic method...
Simon
There are a few options:
Adding authorization element and deny none for those paths that you do not need any authentication and contains your static files
You are using integrated pipeline. Turn it off on your IIS 7.
There is no doubt that you need to create a custom extension method because ASP.NET routing engine uses this code to decide whether a file exist,
if (!this.RouteExistingFiles)
{
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
{
return null;
}
}
You will not able to decide whether the request is static in Application_BeginRequest using context.handler because Routing Module may change the handler and this module always execute after Application_BeginRequest. My suggestion is to use the similar code which ASP.NEt routing engine uses.

Security for Flex app when ssl is not available

So I know the best practice would be to run my Flex app over ssl along with implementing other forms of security however that isn't an option at this point (for monetary reasons and the app simply doesn't need that much security otherwise my sponsors would pay for it). However, I would like to implement some form of security and I'm wondering whether it's even worth it when I don't have ssl to protect the transactions.
So my setup is that I have a ASP.Net server side with a Flex UI. Right now the UI is the only thing that protects access to the sever: the server doesn't do any sort of verification during each request, it just assumes the person is allowed to do it. Obviously, anybody could write a program to generate posts (even if I could use SSL it would be like swiss cheese). Like I said before, security isn't a big deal, this is an internal app and it's nothing critical, however I do believe in doing things right. Would keeping the user info in session be a viable option and then verifying that the given user has permission, etc. Perhaps some sort of token system?
What would your preferred method of protecting this setup be?
...and no, I won't give you the url :)
ASP.NET Session itself is token based security and yes you can easily implement that by doing
[WebMethod(true)]
and yes, any web method requires login to be done first, it should call User.IsAuthenticated, that verifies the session token.
You can easily implement form authentication (let web.config empty, you can use FormsAuthentication in code).
for example,
[WebMethod(true)]
public string DoLogin(
string username,
string password)
{
//.. do your verification
FormsAuthentication.SetAuthCookie(username,false);
return "Login Sucessful";
}
[WebMethod(true)]
public string ChangePassword(
string oldPass,
string newPass)
{
// verify user is logged on or not..
if(!User.IsAuthenticated)
return "Please Login";
// The code below is secure, only
// authenticated user will go through below
// change pass...
return "Password Changed Successfully.";
}
We developed many Flex+ASP.NET sites, we did exactly same thing, but instead of return "string" we usually return a class like following...
public class WSResult<T>{
public bool Successful;
public string Message;
public T Result;
public T[] Results;
}
The convention is simple, if method was successful then you return Success = true, and depending upon whether you want to return an array of items or just single item, you can return either Results or Result. In case if there has been any error or unathorized access you can set Successful=false and set Message as detailed string. As per following example.
[WebMethod(true)]
public WSResult<BusinessUser> DoLogin(
string username,
string password)
{
try{
BusinessUser user = BusinessUser.GetByUsername(username);
if(user==null)
throw new Exception("User not found");
if(user.Password != password)
throw new Exception("Password did not match");
return new WSResult<BusinessUser>{ Result=user };
}catch(Exception ex)
{
// this will even catch any DAL exceptions or any system error as well
// Log Exception... somewhere for tracking...
return new WSResult<BusinessUser>{ Successful=false, Message = ex.Message };
}
}
Unfortunately, I know diddly squat about flex, but I think I can help anyway. I think you have two reasonably good options.
First though, we need to clarify something... Are you saying the server doesn't do any authorization? Does it at least have the ability to authenticate a user? Do you have any control over the server code? If not, I don't think the following suggestions will help. I'm not sure how you're supposed to secure a server with just client side code. Maybe there is a way, but I can't think of it.
1) Use HTTP digest authentication. This requires that the server is configured to understand it and that there is support in the flex api for adding the appropriate auth header to the HTTP request. The server authenticates the user by his password and can check what operations can be performed by said user against some authorization mechanism.
2) Follow the guidelines in this article to implement the authentication scheme that many atom publishing endpoints use. The flex api will have to provide some support for this, maybe there is an existing third party lib though. If you can get access to the HTTP headers you should be able to implement the rest.
Good luck.
How are you commuicating with the server SOAP. REST etc?
If it is SOAP have a look at the answer to this question
General Password Security && Implementation in Actionscript 3
and here's a link how to add the header to the SOAP message
How to add a "flat" message header to a flex web service call?
Hope this helps
Jon

How do I configure ASP.Net OutputCache to vary by http vs https?

Here is the scenario, a user opens up non-secure page from our WebApp, let's call it PageA, in their browser and then clicks a link in there that takes them to a secure instance of PageB. Once in PageB the user can subsequently click a link that takes them back to a secure instance of PageA (which they already viewed and is in OutputCache). I observed that even though PageA is being accessed over a different URL after visiting PageB (the secure one) it's actually pulling the prior cached copy rather making a fresh one. I verified this behavior in a debugging session, and was surprised that ASP.Net used the same OutputCache item for a secure copy of the page.
My question is why is it this way? And how do I tell the ASP.Net OutPutCache to treat access from secure URL as a different/unique item than the non-secure equivalent?
[Background]
We recently switched our Web Sites images over to use Scene7/Akamai for all images. As a result of this we added code to use different Scene7 url's when viewing a given page on a secure connection. This OutputCache issue is not allowing for the logic that outputs the secure url's to execute, and is resulting in ugly browser warnings.
This doesn't answer the question as worded but it may eliminate your need to vary by scheme. If you are hard coding the "http://" for the Scene7 urls you can change them to scheme-relative urls.
<img src="http://site.scene7.com/images/someimage.jpg" />
=>
<img src="//site.scene7.com/images/someimage.jpg" />
That will cause the browser to automatically ask for the resource with the same scheme as the referring page. That's assuming you have an SSL certificate for your scene7 domain of course.
I think that you can do a VaryByCustom="scheme" and add this to your Global.asax.cs file (inlcuding a couple other others that I use as well app version & user):
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom.Equals("version", StringComparison.CurrentCultureIgnoreCase))
{
Assembly asm = Assembly.GetExecutingAssembly();
string[] parts = asm.FullName.Split(',');
string version = parts[1].Trim().ToLower();
return version;
}
else if (custom.Equals("user", StringComparison.CurrentCultureIgnoreCase))
{
var user = Membership.Users.CurrentUser;
return null == user ? string.Empty : user.Id.ToString();
}
else if (custom.Equals("scheme", StringComparison.CurrentCultureIgnoreCase))
{
var scheme = context.Request.IsSecureConnection ? "https" : "http";
return scheme;
}
else
return base.GetVaryByCustomString(context, custom);
}
I've never tried it but you might be able to use the Outputcache VaryByHeader property and the "host" header, which specifies the Internet host and port number of the resource being requested.
The question I'd have is why are you redirecting to PageA over secure after from PageB. If its a non-secure page, couldn't you fix the PageB redirect to always redirect to non-secure.

Resources