RESTful Verify Password service - asp.net

I'm writing a Verify Password service using the ASP.NET Web Api.
The service accepts a password for the currently signed in user, verifies it, and returns an encoded value. This all happens over SSL.
Calling this method causes no changes to state.
Initially this looks like it should be a GET request however on further inspection I'm concerned about the web server logging plain text passwords.
We could implement this as a POST but that seems like the wrong verb given the action.
Is this simply a case of pragmatism over procedure or is there more we can do to fulfil both the pragmatic and RESTful cases?

You should use Basic Authentication where you pass the username/password as headers. This also fits better as the standard already defined.
There is already a javascript code for doing base64 encoding - if you need to do this on the browser.
If you are doing this to authenticate and the encoded value is the access token (cookie), it is better to use OAuth 2.0.

If the API call sends a response that is not a resource per se (does not involve a resource returned from a data store), you should use verbs not nouns.
You can have a UserPasswordsController controller that exposes an action method like this:
[HttpPost()]
public HttpResponseMessage Validate()
{
if (!this.Request.Content.IsFormUrlEncodedContent())
{
return this.Request.CreateErrorResponse(
HttpStatusCode.BadRequest,
"Body of request must be form URL encoded."
);
}
var parameters = this.Request.Content.ReadAsFormDataAsync().Result;
var userName = parameters["userName"];
var password = parameters["password"];
// TODO: Validate user name and password
var isValid = true;
if(!isValid)
{
return this.Request.CreateErrorResponse(
HttpStatusCode.Forbidden,
String.Format(null, "The password provided for {0} is not valid.", userName)
);
}
return this.Request.CreateResponse(HttpStatusCode.OK);
}
And have a registered route like this:
routes.MapHttpRoute(
name: "UserPasswords",
routeTemplate: "api/v1/validate",
defaults: new { controller = "userpasswords" }
);
You would POST forms data to the validation endpoint that contains the user name and password you wish to validate. A status of Forbidden status indicates the password is invalid, while a status of OK is returned if the password is valid.
If you are new to working on REST interfaces and want to take a pragmatic approach, I highly recommend you take a look at Web API Design - Crafting Interfaces that Developers Love.

Related

Validate Values before Apply PATCH in REST

I'm looking for a way to validate and check the values of the model that is sent to my PATCH method for updating. I haven't found my answer yet.
I've read the JsonPatch Documentation but I didn't find what I want.
Scenario: I have a RESTful Web API, and say I have a resource named "users". Say a client wants to partially update a "user" resource: (PATCH api/users/{id}), when the client sends a JsonPatch Document, for example, I have to check if the email is sent for updating and if yes, I have to check if the email wasn't duplicate. So, how could I do this in a method like below: (I use ASP.NET Web API)
[HttpPatch]
[Route("{userId}")]
public HttpResponseMessage UpdateUser(int userId, JsonPatch.JsonPatchDocument<User> patchDocument)
{
// I could do this but before that I wanna validate the proeprties:
patchDocument.ApplyUpdatesTo(dbContext.Users.Single(u => u.Id == userId));
}

C#/OWIN/ASP.NET: can I *manually* generate and get a valid bearer token string in my API code?

I am using the OWIN OAuthAuthorizationServer library in an OWIN ASP.NET C# web API to generate and process bearer tokens.
Right now, I have a single endpoint (which you set in the OAuthAuthorizationServerOptions struct) that accepts the grant_type, username and password fields from the frontend. I created a provider class that performs the validation, and then calls context.Validated() or context.SetError() accordingly. The middleware then handles generating the token and returning it to the user, and also "takes over" the login endpoint, doing all the work internally.
Now, I am adding a new feature to my API where the user can change their "role" (e.g. an admin can set themselves as a regular user to view the results of their work, a user can select among multiple roles, etc.) Since I already handle this through the bearer token (I store the user's role there and all my endpoints use the bearer token to determine the current role), I now have a reason to update the contents of the bearer token from the API backend.
What I'm looking to do is to allow the frontend to call an endpoint (e.g. api/set_role) that will accept a parameter. The user requests a certain role, and their current bearer token would accompany the request. The server then would check if the user in question is allowed to use that specific role and, if so, would generate a new token and return it to the user in the response body. The frontend would then update its token in local storage. Or, of course, if the user is not permitted to switch to that role, the backend would return an appropriate error and the frontend would react accordingly.
To do this I basically want to be able to manually generate a token. Similar to how I use identity.AddClaim() in my login provider, I'd like to be able to do that at any arbitrary position within the API's code. The method would take responsibility for transferring over any necessary existing information (e.g. the user's username) into the new token, since it already has the existing one.
Pseudocode for what I want:
if (!userCanUseRole(requestedRoleId)) return Request.CreateErrorResponse(...);
// we have a struct containing parsed information for the current token in the variable cToken
bearerToken newToken = new bearerToken();
newToken.AddClaim(new Claim("user", cToken.user));
newToken.AddClaim(new Claim("role", requestedRoleId));
string tokenToReturnToFrontend = newToken.getTokenString(); // string suitable for using in Authorization Bearer header
return Request.CreateResponse(new StringContent(tokenToReturnToFrontend));
I am not too familiar with "refresh" tokens, but the only way I am using them right now is extending token expiration. To that end the frontend explicitly requests a refresh token and provides its own, which the backend simply copies to a new token and edits the expiry time. The problem with this is that there's a single method for getting a refresh token, and since I have now at least one other reason to refresh a token (and possibly, future developments could add even more reasons to change token contents at various times), I'd then have to deal with storing transient data somewhere (E.g. "when requesting a refresh token, what is the thing the user wanted to do? has it been too long since they requested to do that? etc.) It'd be much easier if I could simply generate a bearer token on demand in the same way that the OAuthAuthorizationServer itself does. (I know it uses the MachineKey to do this, but I don't know exactly how it does it, nor how I would go about doing what I'm trying to do.)
Of note: In another project I provided internal access to the OAuthBearerAuthenticationOptions class that is passed to the authorization server instance, and was able to use that to decode a bearer token inside of a test. I haven't seen anything obvious thought that would let me encode a bearer token this way.
EDIT: I explored the (extremely tersely, almost uselessly documented) OWIN namespace and found the AccessTokenFormat class which appears that it should do what I want. I wrote this code:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity
{
Label="claims"
}
, new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh=true,
IsPersistent=true,
IssuedUtc=DateTime.UtcNow,
ExpiresUtc=DateTime.UtcNow.AddMinutes(5),
});
at.Identity.AddClaim(new Claim("hello", "world"));
string token = Startup.oabao.AccessTokenFormat.Protect(at);
return Request.CreateResponse(HttpStatusCode.OK, new StringContent(token, System.Text.Encoding.ASCII, "text/plain"));
which seems like it should work. (I again allow access to the OAuthBearerAuthenticationOptions class passed to the OAuthAuthorizationServer instance.) However, this code throws an ArgumentNull exception. The stacktrace indicates that it is writing to a BinaryWriter but the OWIN code is passing a null value to the Write method on the BinaryWriter.
Still have no solution.
I did figure out the code to make this work. One could argue I'm "not using OAuth right", but strictly, this code WILL accomplish what I want - to generate a token in code at any arbitrary point and get the string.
First, as I said, I have to provide access to the OAuthBearerAuthenticationOptions class instance. When the OAuth server initializes I'm guessing it populates this class with all of the various objects used for tokens. The key is that we do have access to Protect and Unprotect which can both encode and decode bearer tokens directly.
This code will generate a token assuming that oabao is the OAuthBearerAuthenticationOptions class that has been passed to the OAuthAuthorizationServer instance:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity("Bearer", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"),
new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddDays(1) // whenever you want your new token's expiration to happen
});
// add any claims you want here like this:
at.Identity.AddClaim(new Claim("userRole", role));
// and so on
string token = oabao.AccessTokenFormat.Protect(at);
// You now have the token string in the token variable.

IdentityServer 3 refresh user with refresh token

We are trying to set up Identity Server 3 in the right way.
We got authentication working fine and we manage to retrieve the refresh token.
The client application is using Angular.
Now when the acces_token expires any calls to the rest api fails (we managed to get it to return 401) but we are wondering how to re-authenticate the user.
In our tests, any api call made from Javascript is failing (401) but as soon as the page is refreshed the whole mechanism is kicking in. We do see that we are redirected to the identity server but it does not show up the login page, we are sent back to the client application with new tokens apparently.
What I would like to do is to refresh the access token without having to force the user to refresh the page.
What I'm not sure though is whose responsibility is it? Is that the client application (website) or the angular application? In other word, should the application handle this transparently for Angular or should angular do something when it receives a 401, in which case, I'm not too sure how the information will flow back to the web app.
Any clue?
Additional Information: We are using OpenId Connect
I got it working!
As I said in the comments I used this article. The writer is referencing a very nice lib that I am using as well.
Facts:
Identity Server 3 is requesting the client secret upon access token refresh
One should not store the refresh_token or the client_secret on the javascript application as they are considered unsafe (see the article)
So I chose to send the refresh_token as en encrypted cookie sith this class (found of ST BTW, just can't find the link anymore, sorry...)
public static class StringEncryptor
{
public static string Encrypt(string plaintextValue)
{
var plaintextBytes = plaintextValue.Select(c => (byte) c).ToArray();
var encryptedBytes = MachineKey.Protect(plaintextBytes);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedValue)
{
try
{
var encryptedBytes = Convert.FromBase64String(encryptedValue);
var decryptedBytes = MachineKey.Unprotect(encryptedBytes);
return new string(decryptedBytes.Select(b => (char)b).ToArray());
}
catch
{
return null;
}
}
}
The javascript application is getting the value from the cookie. It then deletes the cookie to avoid that thing to be sent over and over again, it is pointless.
When the access_token becomes invalid, I send an http request to the application server with the encrypted refresh_token. That is an anonymous call.
The server contacts the identity server and gets a new access_token that is sent back to Javascript. The awesome library queued all other requests so when I'm back with my new token, I can tell it to continue with authService.loginConfirmed();.
The refresh is actually pretty easy as all you have to do is to use the TokenClient from IdentityServer3. Full method code:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> RefreshToken(string refreshToken)
{
var tokenClient = new TokenClient(IdentityServerConstants.IdentityServerUrl + "/connect/token", "my-application-id", "my-application-secret");
var response = await tokenClient.RequestRefreshTokenAsync(StringEncryptor.Decrypt(refreshToken));
return Json(new {response.AccessToken});
}
Comments are welcome, this is probably the best way to do that.
For future reference - using refresh tokens in an angular (or other JS) application is not the correct way as a refresh token is too sensitive to store in the browser. You should use silent renew based on the identityserver cookie to get a new access token. Also see the oidc-client-js javascript library, as this can manage silent renew for you.

How can I send authorization information back to my client app when using AngularJS, WebAPI 2 and Oauth 2?

I have a AngularJS client application that uses javascript (not coffeescript or typescript) Oauth2 to authenticate against a WebAPI 2 application using the latest Identity 2. All the software in my application is the very latest and is based on this example. My client browser targets are IE9 and above.
Note that I made some minor changes from the example above in that I do not urlencode all of the data sent to the server using the transform. Instead I urlencode only in the authenticate method below:
user.authenticate = function (userName, password, rememberMe, successCallback, errorCallback) {
var config = {
method: 'POST',
url: '/Token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: 'grant_type=password&username=' + encodeURIComponent(userName) + '&password=' + encodeURIComponent(password),
};
I am developing with VS2013 Update 2 and on the server, I use C#, the latest Entity Framework and SQL Server 2012.
To login my client calls a /Token method to the WebAPI and passes the userid and password. The WebAPI then responds with a token to the client which I store. With each request to the WebAPI the token is sent back and authenticated:
$http.defaults.headers.common.Authorization = 'Bearer ' + user.data.bearerToken;
This works very well so far but as it stands the application is unable to tell the difference between users that have different roles assigned to them.
Some of the WebAPI methods can only be executed by users who have a certain role. I would like to adjust the menus of my front-end AngularJS application so that only if the user has this role then the appropriate links will appear visible. I do realize that this would not stop a user from checking the HTML and posting but I am not concerned about this as I will still have method decoration to limit the ability of users not in a role to perform actions.
Can someone give me an example of how I can do this using just the suite of products mentioned above that I mention in the question plus JavaScript Web Tokens if they help make bring the solution up to date. From what I understand roles are handled by claims but I do not understand how to add these and send them back to the client with tokens. I have done a lot of research on the internet but I've not been able to find any good examples as I think most of this is very new and not many people have had the chance to explore how a SPA can use these very latest software components.
When answering this question please note that I am not looking for an answer that can tell the community how to set up roles on the server or an answer that explains about how important it is to provide role checks on the server. I think almost everyone is aware of this. What I really think will be of use is some very detailed technical suggestions with sample code and an explanation. To keep the answer focused it would probably be of help to everyone if answers that do not meet this need are not posted as suggested answers.
Thank you in advance.
The short answer to your question is ApplicationOAuthProvider.CreateProperties method. Its created for you by default and is found under WebApi2/Provider/ApplicationOAuthProvider.cs, By default it only sends the userName
//WepApi2/Providers/ApplicationOAuthProvider.cs
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
I would make the following update (in case I need to send more user data later on):
public static AuthenticationProperties CreateProperties(string userName, ClaimsIdentity oAuthIdentity)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName},
{ "roles",string.Join(",",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}
};
return new AuthenticationProperties(data);
}
If you haven't made major changes to the WebApi project, ApplicationOAuthProvider.CreateProperties is only referenced in two places, just update the calling code to pass the oAuthIdentity along with user.UserName and you'll get the user roles sent along with the access token response:
{
"access_token": "ZpxAZyYuvCaWgShUz0c_XDLFqpbC0-DIeXl_tuFbr11G-5hzBzSUxFNwNPahsasBD9t6mDDJGHcuEqdvtBT4kDNQXFcjWYvFP7U2Y0EvLS3yejdSvUrh2v1N7Ntz80WKe5G_wy2t11eT0l48dgdyak8lYcl3Nx8D0cgwlQm-pePIanYZatdPFP9q5jzhD-_k9SF-ARTHgf0ePnbvhLBi1MCYQjvfgPKlbBHt0M5qjwGAeFg1IhSVj0gb4g9QTXoiPhRmxGBmjOpGgzxXixavmrpM7cCBFLoR3DCGnIJo6pwT-6VArxlB8-ZyyOZqh_6gGtptd0lIu8iJRUIGwO9HFNkROdoE9T4buwLnhPpWpy9geBjPVwsB1K3xnbch26YbklhxIHVybBxeIVXd17QTw_LjlQ5TJdqpAYfiZ5B9Nx2AFYYYe3--aemh4y1XOIvN",
"token_type": "bearer",
"expires_in": 1209599,
"userName": "MK",
"roles": "Admin,Public",
".issued": "Fri, 23 May 2014 17:36:54 GMT",
".expires": "Fri, 06 Jun 2014 17:36:54 GMT"
}
Now you have the roles available, you can use Angular conditional directives to show/hide actions according to user roles.
If you need more clarification, please let me know.
Edit:
Decorating your controller methods with Authorize attribute is valid, since the HttpContext.Current.User.Identity is actually a ClaimsIdentity. But as not to hard code security logic inside the application, I prefer using ClaimsAuthorizationManager
public ActionResult Secure()
{
if(!ClaimsPrincipalPermission.CheckAccess("resource", "action"))
return new HttpUnauthorizedResult();
ViewBag.Message = "You are allowed to perform action on resource.";
return View();
}
Roles creation using RoleManager:
RoleManager roleManger = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>());
roleManager.Create(new IdentityRole() { Name = "Admin" });
Roles assignment using UserManager:
userManager.AddToRole(user.Id, "Admin");
There are 2 ways I see you can approach your problem.
include the "Role" Information to the token by a hash or a simple string append as you are the one generating the token, then you can decipher it on the angular.
it seems you want to use ASP.NET Identity system and store and retrieve the role information there. If that is the case you can go through this post pay attention to "Initialize the database to create Admin Role and Admin User" section.
IMO, #1 will give you more flexibility on how you store and use your user data as #2 you are following Microsoft's IdentityUser , although it look magic sometimes and it tend to post limitation and you need to spend time to understand how it works behind the scene and make it work for your project.
To know more about the "Individual User Accounts" you pick during the WebAPI project you created, you can go to http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visual-studio#indauth
I have a very similar scenario as yours, but instead of using tokens to authenticate, I use an Identity Server (Thinktecture) to handle my authentication. My app redirects to the Identity Server to authenticate and it comes back with some very basic claims (username and email). This happens as soon as someone tries to first browse to the page. Once the user is authenticated and redirected to my app I make another call to the server to get the user's permissions. These permissions are stored inside a Security service (AngularJS) which also exposes a "hasPermissions" method. I then use ng-if to decide if I am going to display certain parts of the page - including menu items. Something to this effect:
var service = {
currentUser: ...,
isAuthenticated: function() {
return ...;
},
checkAccess: function(permission) {
return service.isAuthenticated() ?
!!(service.currentUser.permissions.indexOf(permission) > -1) : false;
}
}
Remember that all all the permissions and html elements are visible to anyone who decides to hit the dev tools button and take a peek. You have to do the same checks on the server side before you perform any action. We have a custom Authorization attribute based off of this that checks if the user has the necessary permissions to execute the MVC/WebAPI action before it is executed for simple cases or actually check it within the Action or the HTTP resource before doing anything that needs elevated privileges.
If you want the client to not see any html elements or certain sections of your site you can either point your templates to a MVC action that will authenticate and then return the HTML template or redirect to another page (not the SPA realm) and have them authenticated on the server before the response is served back.
Here another answer:
In ApplicationOAuthProvider.cs
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
simply add a custom header!
context.OwinContext.Response.Headers.Add("Roles", userManager.GetRoles(user.Id).ToArray());

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

Resources