0

I have a javascript variable that I want to pass back to the server side, which I thereafter intend to use it as an access token to grant user access to other pages which requires this token.

I wonder how do I pass this javascript variable back to server, so I can set it to a session variable? Do I need to send it back using ajax?

this is the part of jQuery I use to retrieve the token from server

$(document).ready(function () {
        $('#loginForm').submit(function(e) {
            var blargh = $(this).find('input').serialize();

            $.ajax({
                type: 'post',
                url: '/WebAPI/api/authenticate/login',
               data: blargh,
                success: function (data) {
                    $.each(data, function(index, token) {
                        $('#container').prepend('<input type="hidden" name="MY_HIDDEN_FIELD_NAME" id="MY_HIDDEN_FIELD_NAME" value="'+token+'">');
                    });
                },
                error: function(jqXHR, status, errorThrown) {
                    alert("Error " + status + "\nError Thrown" + errorThrown )
                },
            });
            e.preventDefault();

        });

    });
starcorn
  • 8,261
  • 23
  • 83
  • 124
  • 1
    isn't what you're describing just an authentication cookie? – Andras Zoltan Jul 05 '12 at 10:48
  • Not really. I have created a WebAPI which require the user to login first before he can use other things in the WebAPI. What the user gets back is a token, which he then need to use. What I'm now doing is simply a shell on top of the WebAPI, so that the user can access the webAPI without the need to input the URLs manually. – starcorn Jul 05 '12 at 10:51
  • But that's exactly what an authentication cookie achieves already. You seem to have reinvented wheels. – Darin Dimitrov Jul 05 '12 at 11:50
  • @DarinDimitrov I don't how authentication cookie is used. But the shell I'm making can reside on other server than on the same server as the WebAPI. Thus I need to be able to pass this authentication token to the server where the shell lies in. The authentication token itself is generated by the WebAPI. – starcorn Jul 05 '12 at 16:45
  • Well, then I suggest you to read about Forms Authentication and the cookies that it uses. The idea is that an anonymous user performs a first request to the LogOn method providing his credentials and if they are valid he is provided with an authentication cookie which he uses on subsequent requests. – Darin Dimitrov Jul 05 '12 at 16:52
  • @DarinDimitrov the thing is I'm not using some conventional login. I'm using the webapi to login. Which I'm afterward, if correct, is granted an access token which I have to supply if I want to access other webapi methods. – starcorn Jul 05 '12 at 16:59
  • The WebApi Authorize attribute will happily use the authentication section you have defined in your web.config. So define Forms Authentication and you get authentication for free without reinventing wheels. – Darin Dimitrov Jul 05 '12 at 17:00
  • @DarinDimitrov I assume you mean `[Authorize]` attribute? I just tried it anyway. Using the authorize attribute would redirect me to the webapi's login page if I have created one. But I want to keep WebAPI clean with only REST urls. – starcorn Jul 05 '12 at 19:31

4 Answers4

0

Couldn't you pass it back as either a hidden form element or pass it back in the query string of a ajax postback?

Example of a hook to get the post back value in global.asmx

protected void Session_Start(object src, EventArgs e)
    {
        if(!string.IsNullOrEmpty(Request.Form["MY_HIDDEN_FIELD_NAME"]))
        {
            Session["MY_SESSION_NAME"] = Request.Form["MY_HIDDEN_FIELD_NAME"]
        }
    }
John Mitchell
  • 9,653
  • 9
  • 57
  • 91
  • would I need to create a separate view to retrieve this hidden variable? – starcorn Jul 05 '12 at 10:47
  • @starcorn: I don't see why you would. If it's a hidden form element then it's just like any other form value. If it's using AJAX than you'd want a controller action for it, but the result would likely be JSON so no view would be necessary. – David Jul 05 '12 at 10:49
  • If its just a hidden value and you are going to use it for more than one page you could put a hook into the global.asax page and grab it from there for all pages, you'd need to ensure that the name is pretty unique though so it doesn't get re-used – John Mitchell Jul 05 '12 at 10:49
  • Does the hooking part equals to this question? http://stackoverflow.com/questions/560084/session-variables-in-asp-net-mvc . – starcorn Jul 05 '12 at 10:58
  • @JohnMitchell I added the jQuery script I'm using first to retrieve the token from server. Now if I use the hidden field approach I would need to send the token back using ajax again? – starcorn Jul 05 '12 at 11:33
  • As suggested by @Ajay beni you could use the request header, or for you could also use a query string (just change my above code from Request.Form to Request.QueryString). Either way you'll probably need to do a AJAX Postback in some fasion. The last way of doing it would be using a WebAPI or similar call and doing a REST postback. – John Mitchell Jul 05 '12 at 15:05
0

I would recommend sending you the acess token in request headers when u are sending a ajax request

xhr.setRequestHeader('custom-header', 'value');

and on the server side you can fetch the request header

Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99
  • Please note: 'I thereafter intend to use it as an access token to grant user access to other pages which requires this token' - how would you send this for page-requests? – Andras Zoltan Jul 05 '12 at 10:50
  • The problem with this approach is some proxy servers strip out custom request headers :( But its definitely a nice approach. – John Mitchell Jul 05 '12 at 10:50
  • I think you need to pass token in every request and in MVC side you can write a action filter to check access token for every request – Ajay Beniwal Jul 05 '12 at 11:09
0

First - why is your client generating the token (I hope I've understood you correctly there)? The server should generate the token and the client must then be responsible for maintaining it.

If it's an API token that'll only ever be used in the browser from javascript, then I recommend using an authentication cookie - all browsers know how to handle them and you can also easily expire them server-side if you no longer want to allow a particular token to have access (that's quite an important point). Also I strongly recommend against relying on server-side session to maintain the authentication session.

Authentication tokens should ideally be stateless (just like in Forms Authentication's cookie) - the burden of proof is on the client to send you a correct token, with that token containing the information you need to re-initialise the current requests state with the correct user.

If, however, it's a general purpose API for any type of client then you should allow the client to send the token to you in the query string of all requests at a very minimum. You should also support taking it in the request header as well - clients that can easily support setting request headers often prefer to because it then hides the auth token from the URL and makes formatting requests easier (there's also the potential to max out a web server's query string limit if the token is big enough).

I then recommend you look, at a minimum, at overriding MVCs AuthorizeAttribute (there are 2 - one for the 'standard' MVC 4 pipeline and one for the new Web API pipeline, & they would both need to be done if you are using both technologies. The link is for the MVC 4 one) to crack out your cookie/header/query string value. In there you can get the value, decrypt the token, identify the user and set the roles. The core code of that attribute then contains the logic for denying a request based on whether the user is authenticated/has a certain role/is a certain user.

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
0

To pass back an additional item in the AJAX POST, you could add it like this...

var blargh = $(this).find('input').serialize();
blargh.someItem = "value";

Bear in mind that this only works when the form is submitted using AJAX, so not where JavaScript isn't available or is disabled.

All the normal security disclaimers apply!

Fenton
  • 241,084
  • 71
  • 387
  • 401