I would like to create a "Global" dictionary that could be used in my web api v2 project. I would like to collect the usernames of all clients that have authenticated with my API and the time they were authenticated.
Since each client would represent a different HTTP context how could I safely store this data so it can be accessed from other methods in the application? Ideally I would like to add the username and the time they authenticated within m CustomOAuthProvider class as this is where the user authentication occurs.
I would like to avoid using a database as the information is really small and I only need the data while the app is running.
In your Global.asax define a prop public static MyClass MyReference {get; set;}. Then in your method where the user is authorized (logged in), modify this object: Global.MyReference.UpdateMethod(currentUser).
Related
Currently I am about to develop my first REST web API!
I'm currently designing how the system will work yet I am a little confused how things are going to work.
Primarily, a mobile app will consume the Web API, but it must be secure!
For example I wouldn't want an un-authed request handled at all. (Apart from a user registering)
I have found that I can use SSL + Bearer tokens to achieve this user authentication. I am comfortable with this and have tested to see how this would work. And it's suitable.
The problem arises when I wish to retrieve the user details.
In my system a user would log in to the mobile app which would request the token from the server. If all is good, I can log the user into the app. Great! Now, I need to get the information stored about this user to present to them. i.e. name, email, reward points etc...
I am unfamiliar with how to add extra user data AND retrieve it with the Web API. I understand that the token can be used to uniquly identify a user. but how can I extend this data?
Currently I have not much more than a blank WebAPI project with the bearer token authentication implemented. Still using the Entity framework. How can I add more fields of data to a user record?
Furthermore, how can I update these records? For example, a user has gained some reward points, how can update the user data for this?
One final question, Is this suitable for retaining per user data? i.e. can I link other data to a userID or something similar?
Apologies for sounding over-curious, I am very new to MVC
The below code in the IdentityModel.cs would seem like the appropriate place to add user data, but how do I add to this? for example adding a field for reward points? then how would I update upon it?
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
How I would do it:
Create ActionFilter that would validate token, it would use your custom class that would leverage DI, it would obviously get the user ID as well
Now that you know that user is authenticated and you know the user ID just do your regular CRUD based on this user ID
Note: Remember to also validate the payload, since if I send you PUT: /user/887/points {points: 999} I could potentially gain unlimited points.
It's not necessary to use ASP .NET Identity for implementing security in your web API project.
If you use Identity you will have to stick on to "ApplicationUser" and Identity tables for user management where you won't be able to complete your requirement.
A solution is to handle user management with your own custom table and implement security using OWIN middleware classes available for .NET, ie, you need to write code for generating and validating tokens rather than using Identity.
I'm new to ASP.NET MVC world. I'm building an intranet web application. Authentication and authorization is defined in my case as below:
Authentication: If HttpRequest contains an Header with "USER_ID", user is authenticated.
Authorization: There is one in-house WCF Service, which returns list of roles user is entitled to taking USER_ID as input. I keep the roles required by my application in xml file. If user's required role is in svc response then, she is allowed to use the application.
I'm thinking of implementing it like below:
In Global.asax - > Application_AuthenticateRequest, I'll put code to check http Header. If its non_blank, I'll let user to go through this stage.
In OnAuthorization method of AuthorizeAttribute class, I'll put code to fetch role list and match it against required roles from xml file.
Is there any way that I can use existing authentication,authorization infrastructure?
I see code like this
[Authorize(Roles = "admin")]
public string Index() {
return "only admins!";
}
How can I link Roles property like above to some Xml or Table instead of hard coding?
Please help me to implement this logic in asp.net mvc application.
You should check Windows Identity Foundation (WIF), in particular ClaimsAuthorizationManager and ClaimsPrincipalPermissionAttribute. The later allow you to specify what operation and resource need to be secured, while in ClaimsAuthorizationManager you can check whether the current user can perform the operation on the resource, and that can be read from any source you desire.
For Authorization, I would either:
Create a GenericPrincipal in the global.asax AuthorizeRequest event handler with the appropriate roles, and assign it to both HttpContext.User and Thread.CurrentPrincipal.
Or (better), write a custom RoleProvider that gets the users roles from the xml file. If you configure such a RoleProvider, ASP.NET will assign a suitable RolePrincipal to both HttpContext.User and Thread.CurrentPrincipal.
You can then use the standard AuthorizeAttribute.
I am developing an application in asp.net using vs2010.
In application, Admin can create different user accounts using Microsoft member registration wizard.
Users can Login with created credential using Microsoft login control.
Now,I have to access this Logedin user's UserID and UserName in entire application's different forms.
Currently I am accessing this details by writing code in all forms by
MembershipUser newUser = Membership.GetUser();
Guid newUserId = (Guid)newUser.ProviderUserKey;
So, where can i store this login user's UserID and UserName in a common place. So I can access this details from common place?
Please Help me.
Thanks,
Well - that depends fully on where you persist the data for your application.
If you use a database for storage, then logically the data should belong in there, in a user table, with a connectionstring to the database in your application's configuration.
If not using databases, then you properly need some file based storage, for example XML or something you invent yourself and then have a parser which serialize/deserialize the data from files.
In both instances, you'll need to consider security and hashing/salting and make sure the data is kept secure.
I tend to use a static helper class, which stores (and loads) data in HttpContext.Items for the duration of any request. So you would just need to call GetUser once per request. If even that is too much for you, you can use a Session, for example - but don't forget that sessions only live for so long, so be prepared to reload the data if it's lost due to session timeout.
The static class has to be somewhere accessible from the whole application - in a web site project, this means the App_Code folder.
EDIT: reworded and simplified question to be consise...
In my service layer I have something like
GetAllMessages(string userid);
I could have various types of users on my system like Clients / Supplier etc...
This service is only available to all types of users, however what is the best way to implement services only available to selected users e.g.
DeleteAllMessages(string userid); //client only
NewSupplierMessages(string userid); //supplier
Typically these methods will be in one class called MessagesService
NOTE: just to clarify, the user is loggedon and authenticated, however I am wondering if I should write my methods as such:
DeleteAllMessages(ClientUser user); //client only
NewSupplierMessages(SupplierUser userid); //supplier
Basically get the details of the user for every action and call methods in a more strongly typed manner...
EDIT 2:
Note my domain layer is in a seperate class library from my web app, a "client user" will be part of a "client", similarly a "supplier user" will be part of "supplier" - so if I wanted to query my service layer and call the correct code (i.e. retrieve the correct details) - I MUST pass in the user id or a strongly typed class of the user, I cannot see how having a contraint on a DTO object that represents who can access the service as incorrect/ brittle?
Other wise I will have something like this:
GetClientDetails();
The user is handled by asp.net so we know this action can be accessed by the user, however what if there are multiple clients? Surely then we must pass in some some of client id/ if I was to pass in user id I could get the client id from it...
Rather I would say my domain layer is incorrect seeing something like the above signature...
EDIT 3:
The only other alternative I could think off is, when the user authenticates, store the use in a class called UserSession inside the asp.net mvc application as a global state, then inject this using DI (ninject) into my domain service layer, therefore when my signatures can be
GetClientDetails();
The domain service class implementing this interface could be:
public class ClientService : IClientWorkerService
{
private ISession _session;
private IGenericRepo = _repo;
public ClientService(IUserSession _session, IGenericRepo _repo)
{
this._session = _session;
this._repo = _repo;
}
public ClientDetails GetClientDetails()
{
var loggedonuser = _session.GetUser();
if(!loggedonuser.isClient())
throw new NoAccessException()
return _repo.Single<Client>(x=> x.ClientID == loggedonuser.ClientID);
}
}
See MSDN: ASP.NET Authorization
Authorization determines whether an
identity should be granted access to a
specific resource. In ASP.NET, there
are two ways to authorize access to a
given resource:
File authorization
File
authorization is performed by the
FileAuthorizationModule. It checks the
access control list (ACL) of the .aspx
or .asmx handler file to determine
whether a user should have access to
the file. ACL permissions are verified
for the user's Windows identity (if
Windows authentication is enabled) or
for the Windows identity of the
ASP.NET process. For more information,
see ASP.NET Impersonation.
URL authorization
URL authorization
is performed by the
UrlAuthorizationModule, which maps
users and roles to URLs in ASP.NET
applications. This module can be used
to selectively allow or deny access to
arbitrary parts of an application
(typically directories) for specific
users or roles.
An Overview of Authentication and Authorization Options in ASP.NET
Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication
Role-based access control
Custom role based Web Service access
I have two webapplication, one is a simple authenticationsite which can authenticate the logged in user and redirects him then to another site.
Therefore I have to pass ther userId (GUID) to the second application. Currently this is done via the URL but i would like to hide this id.
Has anybody an idea how to do this properly?
[EDIT]: I can't use the Session because of the ApplicationBoundaries (2 different Servers)
This sounds like a tricky situation.
There are however several options you can use but it all depends on what your application does.
Let's call WebApp1 your authenticate site, and WebApp2 your distination site once authenticated.
Can WebApp2 not call WebApp1 behind the scenes? (Services)
THe problem with passing this Guid between applications is it's going through clear text, and considering it's a user id, if anyone manages to intercept this they will have access to WebApp2 for life. Whether you pass it in a querystring or form variable, it's still vulnerable.
If you can't use WebApp2 to query WebApp1, you should consider WebApp1 creating a temporary Guid that expires. That would be much safer long term, but as it's clear text is still susceptible to attack. The 2 web apps will also need access to the same data store.
Ultimately, i think the AUthentication Site should be a service which WebApp2 can consume.
Users should login through WebApp2, which will call WebApp1 securely for authentication.
WebApp2 can then manage it's own session.
If you can't use cookies because it's cross domain then encrypt it, with a nonce.
Setup a shared secret/key between the two servers; send the encrypted GUID and nonce combination to the second server. Unencrypt, check the nonce hasn't already been used (to stop reply attacks), then use the unencrypted GUID.
If you want to be extra tricky have a web service on app1 where it can check the nonce was actually issued (at this point you're heading towards WSTrust and a single sign-on solution, which generally solve what you're trying to do)
Even with cookies, as they're easily edited/faked, you should have some form of checking.
You have two ASP.NET web applications, and one application does nothing but authenticate a user?
this sounds like a job for....
Web Services!
Create a new web service on the authentication app (They are the .asmx extension), and add a single method that takes in the user and password etc, and returns authentication info.
Then import the WSDL on your 2nd app, and call the 1st app like it was a method. It will simplify your code, and fix your issue.
An Example:
AuthenticateUserService.asmx goes on the Authentication app:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AuthenticateUserService : System.Web.Services.WebService
{
[WebMethod]
public bool AuthenticateUser(string username, string passhash)
{
// Fake authentication for the example
return (username == "jon" && passhash == "SomeHashedValueOfFoobar");
}
}
Once this is setup, fire up your main app, and right click the project and click "Add Web Reference".
Enter the url to the asmx on the authentication app, and Visual Studio will discover it and create a proxy class.
Once that is done, we can call that method like it was a local method in our main app:
protected void Page_Load(object sender, EventArgs e)
{
// Now we can easily authenticate user in our code
AuthenticateUserService authenticationProxy =
new AuthenticateUserService();
bool isUserAuthenticated =
authenticationProxy.AuthenticateUser("jon", SomeHashMethod("foobar"));
}
So, what does this really do?
It eliminates the client from the authentication process.
Your current process:
Client Enters credentials to AppA
AppA redirects the client to AppB
AppB redirects the client back to AppA if the credentials match.
Is replaced with a server side SOAP call between AppA and AppB. Now its like this:
Client enters credentials in AppA
AppA asks AppB if they are good
AppA serves proper content to the client.
Pass the GUID through a session, best way.
http://www.w3schools.com/ASP/asp_sessions.asp
OR, since it's 2 different servers, pass the information by POST method:
http://www.w3schools.com/aspnet/aspnet_forms.asp
The other possibility is to store the session state in a database on the local server, and remotely access that database from the other server to see if the user has successfully logged in and within session timelimit.
With that in mind, you can do the entire authentication remotely as well. Remotely connect to the local database from the remote server and check the login credentials from there...that way you will be able to store the session and/or cookie on the remote server.
I would recommend AGAINST the hidden field proposition, as it completely counteracts what you are trying to do! You are trying to hide the GUID in the URL but posting the same information in your HTML code! This is not the way to do it.
Best choice is the database option, or if not possible, then use HTTP POST.
Use session variables or HTTP POST instead of HTTP GET.
Instead of passing it via a query string you should create a hidden form field with its value and then post to your 2nd page, which can then grab the posted value and it will be hidden from the user.
If the servers have a common domain name, you can use a cookie.
EDIT: Cookies will just hide the ID visually, it is still accessible. Same with hidden fields or using POST rather than GET. So if the ID is confidental and you want to avoid to send it over the network unencrypted, you need a different approach.
A solution could be to encrypt the ID on the auth server with a key which is shared by the servers. Another solution could be to generate a random GUID on the auth server, and then let the auth server directly inform the other server (over SSL) which ID the GUID corresponds to.
go for session mangement or use a HTTP Post as said in the above post.