I have a question specific to eStreamChat (An opensource Chatroom for .Net). There doesn't seem to be much in the way of documentation on their websites or any examples online so if anyone could help that would be great. I think that the problem is with my hash.
So far I have managed to download and import the project and set up a virtual IIS directory so that I can use it from my own application. I have created a link on one of my own webpages that brings me to their ChatRoom.aspx webpage. The link that brings me there is in the required format eg:
http://localhost:10833/eStreamChat/ChatRoom.aspx?id=lowens×tamp=130425080917&hash=eb9fa849033cbf7b967ba472efb46363903f96dc
The page loads and I can see the chatroom but I get the following error popup: Unable to join room! Hash is invalid!
To get this far I have followed the instructions on this page:
The only line I didn't understand was this: You can configure the secret key from the web.config file so maybe if somebody could explain what I'm supposed to be doing in the web.config it might help.
The error that is being thrown is from the RemoteAuthUserProvider.cs. Here is the code:
NameValueCollection hrefParams = HttpUtility.ParseQueryString(hrefUri.Query);
var calculatedHash = Miscellaneous.CalculateChatAuthHash(hrefParams["id"] ?? String.Empty,
hrefParams["target"] ?? String.Empty, hrefParams["timestamp"]);
if (hrefParams["hash"] != calculatedHash)
{
throw new SecurityException("Hash is invalid!");
}
After debugging:
hrefParams["hash"] is "eb9fa849033cbf7b967ba472efb46363903f96dc" this is
calculatedHash is "5129cf1cf65350a387ce53a2b0d31c960f9d96d3"
So why is that hash not the same?
Cheers
In the Web.config in appSettings a value is needed:
<appSettings>
<add key="AuthSecretKey" value="ENTER A VALUE HERE"/>
</appSettings>
This value needs to match the secretKey in the click method provided on the website so that the hashes will match.
Related
Background
I am working on a RESTful API written in C#/.NET and need to switch between the production database and dev database for testing new API calls. The previous lead developer's API made no sense, so we are replacing the most important parts of it before rebuilding the application from scratch.
The Goal
I need to switch to the SqlMembershipProvider for the dev database server on the fly to test CRUD operations on user accounts.
The Problem
The MSDN "documentation" says that the Membership.CreateUser method calls SqlMembershipProvider.CreateUser, but calling this underlying method directly returns null and sets the status output to invalidAnswer.
Configuration
I have the connection string and provider definition configured in Web.config:
<connectionStrings>
<add name="ConnString" connectionString="server=prodblahblah">
<add name="DevConnString" connectionString="server=devblahblah">
...
<membership defaultProvider="SQLDBMembershipProvider">
<providers>
<add name="SQLDBMembershipProvider" connectionStringName="ConnString" requiresQuestionAndAnswer="false" ...>
<add name="DevSQLDBMembershipProvider" connectionStringName="DevConnString" requiresQuestionAndAnswer="false" ...>
Code
Based upon the bits of advice I found scattered across the internets, I came up with and attempted the following:
SqlMembershipProvider p = (SqlMembershipProvider)Membership.Providers["DevSQLDBMembershipProvider"];
MembershipCreateStatus status;
string question = "";
string answer = "";
MembershipUser mu = p.CreateUser(username, password, email, question, answer, true, Guid.NewGuid(), out status);
Result
The call returns null and sets the output status variable to invalidAnswer. This perplexes me because requiresQuestionAndAnswer is set to false in the configuration, and calling Membership.CreateUser results in null values in the aspnet_Membership table.
Strangely, I get the same outcome when using Membership.Providers["SQLDBMembershipProvider"] instead of ["DevSQLDBMembershipProvider"], so there must be some difference between the way that Membership.CreateUser and SqlMembershipProvider.CreateUser handle password questions/answers.
Small Rant About MSDN "Documentation"
The code example given in the MSDN documentation for SqlMembershipProvider.CreateUser does not even actually show how to use SqlMembershipProvider.CreateUser -- it instead calls Membership.CreateUser and does not mention how to access the non-default providers configured in the Web.config file. The code example in the documentation for a method specifically does not show how to use that method. I think it is fair to say that MSDN has the most infuriatingly unhelpful documentation I have ever seen.
Question
Why does Membership.CreateUser work with empty password question/answer values while SqlMembershipProvider.CreateUser does not? How do I work around this?
I figured out the answer while writing this question. Since it is difficult to find documentation for this stuff anywhere, I decided to post the question and answer it with my findings.
The Answer
It turns out that "" is not accepted while null is. An empty string is invalid while a null is acceptable. This makes perfect sense to everyone, of course. It is inherently intuitive that an empty string is unacceptable while a null string is acceptable. Obvious.
It is definitely a good thing that Microsoft in their infinite[simal] wisdom decided to not show examples of how to use their code in their code examples. They are professionals, after all, and that is just how documentation works.
I have requirement to append USERNAME to the URL in server side using URL Rewrite module.
Why?:
I have website site1, when USER logs in to site1, he will see a link to site2., This link is URL or reports. (Tableau).
Authenticated ticket has been created using FormAuthentication in site1.
When USER clicks the link, authenticated username should be passed to site2.
I could append username from client side, but due to security issues I have to append username to URL in server side before it gets executed.
So I have decided to use URL rewrite provider, which grabs the username by decrypting the cookie value as shown below
namespace PlatformAnalysisUrlProvider.PlatformAnalysisProvider
{
class AnalysisRewriteProvider: IRewriteProvider, IProviderDescriptor
{
public void Initialize(IDictionary<string, string> settings,
IRewriteContext rewriteContext)
{
}
public string Rewrite(string value)
{
string[] cookievalues = value.Spli('=');
FormAuthentication ticket = FormAuthentication.Decrypt(cookievalues[1]);
//Decrypt throws error as shown below
}
}
}
Cookie Values
cookievalues [0] = has the key
cookievalues [1] = has the value
Example:
233AWJDKSHFHFDSHFJKDFDKJFHDKJFKDJFHDHFDHFKJHDFKJHDFJHDKJFHDSKJFHDF
It's a cookie value. But decrypt is not happening
I am getting following error
Unable to validate data.
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(
Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start,
Int32 length, IVType ivType, Boolean useValidationSymAlgo,
Boolean signData)
Here is my settings in IIS for URL Rewrite
Requested URL: Matches the Patterns
Using: Regular Expression
Ignore Case - Checked
Conditions -
Input : {HTTP_COOKIE}
Type : Matches the Pattern
Pattern : .*
Action Type - Rewrite
Rewrite URL - http://11.155.011.123{HTTP_URL}&USERNAME={PlatformAnalysisUrlProvider:{C:0}}
I have also set up MACHINE KEY as suggested by this forum
I have referred this post for development
One of the stack overflow post suggested that it might be firewall or antivirus issue. But I do not have antivirus installed or firwall enabled.
It really helps if someone direct me to code sample where web site hosted in IIS and URL Rewrite provider is used.
Updating Error Log
MODULE_SET_RESPONSE_ERROR_STATUS
Notification - "PRE_BEGIN_REQUEST"
HttpReason - "URL Rewrite Module Error"
Updating post with Machine Key Info
<MachineKey Description="AES" validation="SHA1"
descriptionKey="******"
validationKey="******" CompatibilityMode="Framework20SP2">
Reason May be - The website where cookie getting created is developed using .NET Framework 4.5. The provider where we reading the cookie is Framework 3.5. Is this may be the cause? OR Do we need config file for Provider project?
Updates - I have added machine key to Machine.config , but it still did not work :(
Alternative Solution
Add App.config to class Library
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- ... -->
<add key="SecurityKey" value="somevalue"/>
<!-- ... -->
</appSettings>
</configuration>
Copy config to GAC
Follow this blog - http://techphile.blogspot.in/2007/02/2.html
Encrypt the value (refer here) and create custom cookie during Login
Use the Decrption logic inside custom rewrite provider
The good thing about this is that the error is a general decryption error and not one with URL Rewrite itself, so that gives you a wider area to search for help. The mechanics of URL Rewrite seem to be right.
Decrypting means that it must be encrypted by the same method as you're decrypting it. So it has to be the right cookie and the right decryption method.
Since you're not checking which cookie that you're reading from, you could get unexpected results if the wrong cookie is first in the list of cookies.
Here are some steps that I recommend to troubleshoot this:
Create a simple URL Rewrite rule that will give you the value of your cookie. I created a rule to do that in my example below. You can test it by going to yoursite.com/getcookie. It should redirect to yoursite.com/?Cookie={cookievalue}
Then you can test your code outside of the URL Rewrite provider. You can create a simple console app or winforms app to test the rest of the code.
I recommend adding a check for the existence of the cookie and then a check again for the 2nd value. For example: if (cookievalues[1] != null).
When developing the decryption method, you don't have to worry about URL Rewrite. As long as it works in a test app in .NET then you should be set.
<rule name="Get cookie value" stopProcessing="true">
<match url="^getcookie" />
<action type="Redirect" url="/?Cookie={HTTP_COOKIE}" appendQueryString="false" redirectType="Found" />
</rule>
I am trying out swagger(SwashBuckle) for generating web api documentation. I have successfully generated the documentation using Web API documentation using swagger but I am not able to successfully send API requests, as we have token based authentication (custom header for authentication purpose) for few of the methods.
I tried to find out sample code/resources for the same but did not have much luck. Please let me know if someone has implemented/came across similar thing in their application.
I had the same problem some time ago, and asked in the blog http://bitoftech.net/2014/08/25/asp-net-web-api-documentation-using-swagger/ for a solution.
This was the answer that worked for me:
1.Add new file named “SwaggerExtensions”, then added new JS file named “onComplete.js”, you have to change the build action for this file to “Embedded Resource”.
2.Inside the file “onComplete.js” paste the following code:
$('#input_apiKey').change(function () {
var key = $('#input_apiKey')[0].value;
if (key && key.trim() != "") {
key = "Bearer " + key;
window.authorizations.add("key", new ApiKeyAuthorization("Authorization", key, "header"));
}
});
3.Open file “SwaggerConfig.cs” and inside the register method paste the code below:
SwaggerUiConfig.Customize(c =>
{
c.SupportHeaderParams = true;
c.InjectJavaScript(typeof(SwaggerConfig).Assembly, "AngularJSAuthentication.API.SwaggerExtensions.onComplete.js");
});
Note that you need to change the full assembly name to match your assembly name.
I believe thats it, once you run the UI you will notice that this file has been downloaded and it will set the authorization header correctly.
You need to set up API Key authorisation. The "Describing Security/Authorization Schemes" in the README at https://github.com/domaindrivendev/Swashbuckle has details on this but in short you need to do something like the following in your call to httpConfiguration.EnableSwagger()
c.ApiKey("apiKey")
.Description("API Key Authentication")
.Name("apiKey")
.In("header");
You then need to create a custom attribute derived from IDocumentFilter and apply it to the appropriate methods in your controllers. Lets say you call this ApiKeyFilter. You then need to register this with Swagger by adding the following in EnableSwagger()
c.OperationFilter<ApiKeyFilter>();
I'm not aware of sample code for an ApiKey attribute but I've used https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Dummy.Core/SwaggerExtensions/AssignOAuth2SecurityRequirements.cs before for OAuth2, you should be able to adapt that.
I am using the Facebook comments plugin on a blog I am building. It has some FBXML tags that are interpreted by the facebook javascript that is referenced on the page.
This all works fine, but I have to pass in the current, fully-qualified URL to the plugin.
<div style="width: 900px; margin: auto;">
<div id="fb-root"></div>
<fb:comments href="URL HERE" num_posts="10" width="900"></fb:comments>
</div>
What is the best way to get the URL of the current page? The request URL.
Solution
Here is the final code of my solution:
<fb:comments href="#Request.Url.AbsoluteUri" num_posts="15" width="900"></fb:comments>
You could use the Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString() or Request.Url.AbsoluteUri.
Add this extension method to your code:
public static Uri UrlOriginal(this HttpRequestBase request)
{
string hostHeader = request.Headers["host"];
return new Uri(string.Format("{0}://{1}{2}",
request.Url.Scheme,
hostHeader,
request.RawUrl));
}
And then you can execute it off the RequestContext.HttpContext.Request property.
There is a bug (can be side-stepped, see below) in Asp.Net that arises on machines that use ports other than port 80 for the local website (a big issue if internal web sites are published via load-balancing on virtual IP and ports are used internally for publishing rules) whereby Asp.Net will always add the port on the AbsoluteUri property - even if the original request does not use it.
This code ensures that the returned url is always equal to the Url the browser originally requested (including the port - as it would be included in the host header) before any load-balancing etc takes place.
At least, it does in our (rather convoluted!) environment :)
If there are any funky proxies in between that rewrite the host header, then this won't work either.
Update 30th July 2013
As mentioned by #KevinJones in comments below - the setting I mention in the next section has been documented here: http://msdn.microsoft.com/en-us/library/hh975440.aspx
Although I have to say I couldn't get it work when I tried it - but that could just be me making a typo or something.
Update 9th July 2012
I came across this a little while ago, and meant to update this answer, but never did. When an upvote just came in on this answer I thought I should do it now.
The 'bug' I mention in Asp.Net can be be controlled with an apparently undocumented appSettings value - called 'aspnet:UseHostHeaderForRequest' - i.e:
<appSettings>
<add key="aspnet:UseHostHeaderForRequest" value="true" />
</appSettings>
I came across this while looking at HttpRequest.Url in ILSpy - indicated by the ---> on the left of the following copy/paste from that ILSpy view:
public Uri Url
{
get
{
if (this._url == null && this._wr != null)
{
string text = this.QueryStringText;
if (!string.IsNullOrEmpty(text))
{
text = "?" + HttpEncoder.CollapsePercentUFromStringInternal(text,
this.QueryStringEncoding);
}
---> if (AppSettings.UseHostHeaderForRequestUrl)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
try
{
if (!string.IsNullOrEmpty(knownRequestHeader))
{
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
knownRequestHeader,
this.Path,
text
}));
}
}
catch (UriFormatException)
{ }
}
if (this._url == null) { /* build from server name and port */
...
I personally haven't used it - it's undocumented and so therefore not guaranteed to stick around - however it might do the same thing that I mention above. To increase relevancy in search results - and to acknowledge somebody else who seeems to have discovered this - the 'aspnet:UseHostHeaderForRequest' setting has also been mentioned by Nick Aceves on Twitter
public static string GetCurrentWebsiteRoot()
{
return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
Request.Url.PathAndQuery
should work perfectly, especially if you only want the relative Uri (but keeping querystrings)
I too was looking for this for Facebook reasons and none of the answers given so far worked as needed or are too complicated.
#Request.Url.GetLeftPart(UriPartial.Path)
Gets the full protocol, host and path "without" the querystring. Also includes the port if you are using something other than the default 80.
My favorite...
Url.Content(Request.Url.PathAndQuery)
or just...
Url.Action()
This worked for me for Core 3.0 for full URL:
$"{Request.Scheme}://{Request.Host.Value}{Request.Path.Value}"
One thing that isn't mentioned in other answers is case sensitivity, if it is going to be referenced in multiple places (which it isn't in the original question but is worth taking into consideration as this question appears in a lot of similar searches). Based on other answers I found the following worked for me initially:
Request.Url.AbsoluteUri.ToString()
But in order to be more reliable this then became:
Request.Url.AbsoluteUri.ToString().ToLower()
And then for my requirements (checking what domain name the site is being accessed from and showing the relevant content):
Request.Url.AbsoluteUri.ToString().ToLower().Contains("xxxx")
For me the issue was when I tried to access HTTPContext in the Controller's constructor while HTTPContext is not ready yet. When moved inside Index method it worked:
var uri = new Uri(Request.Url.AbsoluteUri);
url = uri.Scheme + "://" + uri.Host + "/";enter code here
The case (single page style) for browser history
HttpContext.Request.UrlReferrer
I'm just meddling in the ways of the RESTful web service in C# using ASP.Net 2.0 and have managed (via a class library, a reference to dll produced by the former and some adjustment of my web.config) to coax out a URI format like so:
http: //localhost/DevelopmentProject/testhandler/?input=thisismyinput
Which unremarkably just returns the input as a piece of text with the enlightening prefix "Your Input Was: "
I was under the impression that I could get the URI to become further ensmoothened to something more along the lines of:
http: //localhost/DevelopmentProject/testhandler/thisismyinput
and have the same result but have no idea how to get rid of the pesky "?input="
The entry to the httphandlers section of my web.config is (spaces added so code displays):
< add verb="*" path="testhandler/*" type="HandlerLib.testhandler, HandlerLib"/ >
I am running IIS 5.1 on the local machine, will this introduce a problem?
Essentially where am I going wrong?
Thanks.
One solution is to use UrlRewriting to rewrite the Url to what you need.
I use http://urlrewriter.net/ to do all my rewriting, and you could setup something like this in your scenario
<rewriter>
<rewrite
url="DevelopmentProject/testhandler/([\w]+)"
to="DevelopmentProject/testhandler/?input=$1" />
</rewriter>
This would remain "http: //localhost/DevelopmentProject/testhandler/thisismyinput" in your browser address bar, yet process as "http: //localhost/DevelopmentProject/testhandler/?input=thisismyinput"
You could implement URL rewriting, using something like URLRewriter.net
That would let you use the syntax you've mentioned.
I kinda cheated.
Try:
My Article About How I Got Round It
Change your config from:
< add verb="" path="testhandler/" type="HandlerLib.testhandler, HandlerLib"/ >
to:
< add verb="" path="testhandler/*" type="HandlerLib.testhandler, HandlerLib"/ >
Check out the value of Request.PathInfo in your handler's ProcessRequest function
with a URL like http://localhost/DevelopmentProject/testhandler/thisismyinput.
If that doesn't do it, make sure that IIS 5.1 is routing ALL requests to the aspnet_isapi.dll. (Although, it seems like it already is) This is the "Configuration..." button > "App Mappings" tab in your virtual directory in IIS.