1

Everything I've read says to pass parameters to a REST service in the URI, whether by template, or query string:

https://www.myapp/my/login/api/authenticate/ganders/mypassword

or

https://www.myapp/my/login/api/authenticate?user=ganders&password=mypassword

But obviously those are exposing my username and password in clear view.

Our security guy is saying that we need to pass the parameters in the body of the request. How do I do that? Examples, or just a link to an example is sufficient because apparently my googling skills are not very high.

One thing that I've found so far is that if you decorate your service methods with the attribute [FromBody], like this:

public AuthenticationResult Authenticate(**[FromBody]**LoginData loginData)
{
    return AuthenticationResult.Authenticated;
}

that will grab them from the body. My other task is trying to test this? Is this a task for Fiddler? Or Chrome Dev tools?

Another thing I've found so far is that you can only have 1 parameter in the post, is that accurate?

Sorry, lot's of questions here. Spent all day yesterday trying to research this and obviously didn't get very far...

Edit:

So here's what I have so far, this is the "GET" version that we need to convert to a POST (this is Angular calling C# REST API)

$http.defaults.headers.common.Authorization = 'Basic ' + encoded;

var url = $rootScope.serviceBaseUrl + "login/get" + "?username=" + user + "&password=" + password + "&accesstoken=";

$http({method: 'Get', url: url}).success(.....).error(......);

And the REST service:

[HttpGet]
    public AuthenticationResult Get([FromUri]LoginModel login)
    {
        try
        {
            AuthenticationService authService = new AuthenticationService();
            AuthenticationResult result = authService.IsAuthenticated(login);

            if (result.IsAuthenticated)
                return result;
            else
            {
                return new AuthenticationResult()
                {
                    IsAuthenticated = false,
                    User = new User()
                    {
                        UserId = login.Username
                    }
                };
            }
        }
        catch(Exception ex)
        {
            return new AuthenticationResult()
            {
                IsAuthenticated = false,
                User = new User()
                {
                    UserId = login.Username,
                    Token = ex.Message
                }
            };
        }
    }

Edit2: I'm getting closer. I've got the response to go through (via Fiddler), but my json array of data that I'm passing is not getting mapped to my complex type. Here's what I've got: In Fiddler:

User-Agent: Fiddler
Host: localhost:42761
Content-Length: 73
Content-Type: application/json
Accept: application/json

"Request Body":

{
"Username": "ganders",
"Password": "hashedPassword"
}

My "LoginData" object is instantiated on the service-side, but my two properties are null...

9
  • HTTPS does not expose the url, only the ip and port.
    – Daenyth
    Jun 24, 2014 at 14:56
  • @Daenyth sorry, my knowledge is sorely lacking on the web [development] side, what do you mean httpS doesn't expose the url? Doesn't the request go through (when checking Fiddler, or something like that) like it's displayed above?
    – ganders
    Jun 24, 2014 at 14:59
  • You can see it locally because you made the request and can decrypt it. HTTP is completely wrapped in SSL, they're at different network layers. However due to server logging urls and client side browser caching it's probably still good practice to hide them.
    – Daenyth
    Jun 24, 2014 at 15:01
  • Why are you putting user/pass in the url if you are sending HTTP Basic auth headers?
    – Daenyth
    Jun 24, 2014 at 15:48
  • 1
    You should fix the bug causing the hang instead of using two auth schemes like that
    – Daenyth
    Jun 24, 2014 at 18:13

2 Answers 2

2

I'd structure it by moving it inside the json fields if HTTP basic auth isn't an option.

For example:

POST https://my.server/login
{ "username": "user",
  "secret": "someSecureHashAndNotThePlaintextPasswordSeriouslyDontDoThat" }
4
  • 1
    I updated the question above...right now we are just sending via "GET". When you say "move the credentials inside as new fields", do you mean something like this: encosia.com/using-jquery-to-post-frombody-parameters-to-web-api
    – ganders
    Jun 24, 2014 at 15:14
  • That seems reasonable.
    – Daenyth
    Jun 24, 2014 at 15:43
  • We ARE using basic auth, but that's for a different set of credentials (service account).
    – ganders
    Jun 24, 2014 at 15:49
  • 1
    I just accepted and upvoted you (not sure who downvoted) since it was more of a "how-to" question. I've posted a new question on StackOverflow to see why my LoginModel object is not getting populated. Thanks @Daenyth
    – ganders
    Jun 24, 2014 at 18:45
3

Everything I've read says to pass parameters to a REST service in the URI, whether by template, or query string:

Nobody that understands REST would recommend that.

URL (uniform resource locator) is a subtype of URI (uniform resource identifier). A URL is meant to be a string representing the identity of the resource you're interacting with; a URL therefore must contain everything that is necessary to identify a resource and nothing more. While one's username may be argued to be part of the identity of user resource, a password does not and should not be found anywhere in the URL.

The ideal REST/HTTP way to logging into service is through WWW-Authenticate/Authorization headers. If you absolutely cannot implement this as Authorization, an acceptable workaround would be to either POST to an authentication resource /login/ and have both username and password contained in the body; or to POST to the user resource /users/username with the password in the body. Whether to use URL encoding or JSON or XML or other formats for the request's Content-Type, does not matter in REST, pick one that's most convenient to you. Under no circumstances should the password be in the URL. This is irrespective of any security considerations that can arise when putting password in the URL due to logging or caches.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.