I am new to SharePoint and want to understand how to get the logged in (windows authentication) user details when I submit a custom form to a co-hosted WCF endpoint?
**HTML**
<form action="/TestWCF/Submit" method="post">
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="Submit">
</form>
**WCF**
public void Submit(User user)
{
}
Does the rendered SharePoint page stores a cookie which I should pass along with my custom post method? because if its a asp.net web app I can get a token stored in client and send to server and validate it. but SharePoint I don't have much control.
The username is custom validated. This is done by the FarmService.Authentication.DistributorValidator class in the FarmService assembly. This class inherits from WCF class UserNamePasswordValidator and overrides the Validate method.
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
var repository = new DistributorRepository();
if (! repository.IsKnownDistributor(userName, password))
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
Except for one detail which is absolutely essential. For username password authentication to work your server hosting the service needs an X509 certificate. Else all service invocations will fail. This certificate is specified in the service behavior.
<serviceCertificate findValue="Farm" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
First you need a certificate. Instead of buying one (which is bound to a specific server address and thereby as good as useless for testing purposes) you can create your own. The .net framework comes with tools to generate these and there are several tutorials how to use these tools. Far more easier is selfcert a pluralsight tool which takes care of the whole process in a couple of clicks.
What they don’t tell you here is that you have to run the tool as administrator, else it will crash most ungracefully. What the tool is also unclear about is where to store the generated certificate. By default it is stored in MyStore. When validating the certificate it’s trustworthiness depends on the location it is stored. When the store is not trusted a chain of validation is started. Instead of setting up a chain of certificates you can also directly store your certificate in a trusted store.
To consume this service add a service reference in the client. The mexHttpBinding in the service configuration enables to read all metadata form the service without any credentials.
Setting up a connection to the client requires some fiddling. Again not all of these settings are clear by default.
var endPoint = new EndpointAddress(new Uri(Farm.FarmUrl), EndpointIdentity.CreateDnsIdentity("Farm"));
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
var result = new CustomerDeskOperationsClient(binding, endPoint);
result.ClientCredentials.UserName.UserName = Farm.FarmUserName;
result.ClientCredentials.UserName.Password = Farm.FarmPassword;
Details can refer to A simple WCF service with username password authentication
Hope that helps!
Related
I have a couple of self-hosted windows services running with ServiceStack. These services are used by a bunch of WPF and WinForms client applications.
I have written my own CredentialsAuthProvider. My first implementation of the user database was on MSSQL server using NHibernate. Now since the system is growing I reorganize things a bit. I have created a central 'infrastructue' service which uses Redis as data store and is responsible for account management, central configuration and preferences management. Later it will also contain central logging and RedisMQ. All accounts, roles etc are now stored there (instead of MSSQL). Account migration was successfuly and authentication works fine so far.
Now I have the problem, that clients and servers need to get and set their configurations / preferences. This means that my servers are also clients since they not only serve client requests for their specific business domain but itself need to call the 'infrastructure' server to load / update its own configuration and later log entries and messages.
To authenticate such requests I thought an API key is a good way to go. These requests are not user related and therefore do not need a gateway functionality, they simply need some communication with the central infrastructure server. So I was reading the ServiceStack docs about the API Key Provider, but unfortunately for me a lot remains unclear.
Here first some relevant code from my 'infrastructure' server's Configure method:
private PooledRedisClientManager RedisBusinessPool { get; set; }
//...
container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(connStrBus));
container.Register(c => new AppUserRepository(RedisBusinessPool));
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
}
));
// For the API keys I tried:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
Since I enabled the API Key plugin I get an error on the client when I try to login:
ERROR; AccountManagerWinDesktop; [LoginViewModel+<Login>d__50.MoveNext]; - <username> failed to login to server <myInfrastructureServer>. Exception: 404 NotFound
Code: NotFound, Message: No configuration was added for OAuth provider 'credentials'
Does this mean, that I have to implement my own ApiKeyProvider to cooperate with my implementation of the CredentialAuthProvider? If so, what do I need to add?
In my CredentialAuthProvider implementation I have overwritten Logout, Authenticate, OnAuthenticated and TryAuthenticate. A WPF client offers a UI to store users and roles. They are stored on the Redis database including hashed passwords etc. In my TryAuthenticate implementation I simply have:
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
AppUser user = null;
try
{
//the repository handles all Redis database access
var userRepo = HostContext.TryResolve<AppUserRepository>();
user = userRepo.GetAppUser(userName);
if (user == null)
throw HttpError.NotFound("User '{0}' not found. Please try again.".Fmt(userName));
authService.Request.Items.Add("AppUser", user);
var pwdMgr = new PwdManager();
var hpwd = pwdMgr.GetHashedPassword(password, user.Salt);
if (hpwd == user.Password)
{
//do stuff
}
else
{
// do other stuff
}
return hpwd == user.Password;
}
catch (Exception ex)
{
Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}");
throw;
}
}
What I do not understand right now - Questions:
How are API keys related to my own implementation of CredentialsAuthProvider?
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
Do I also have to implement my own ApiKeyAuthProvidersimilar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
Is there any object / data model for API keys?
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
You should only ever register 1 of any Plugin type, so change your AuthFeature plugin to register all Auth Providers you want to enable, e.g:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
How are API keys related to my own implementation of CredentialsAuthProvider?
An API Key is assigned to a User, i.e. when a request is received with an API Key, they're authenticated as the user the API Key is assigned to. API Keys are created for each new user that's registered, the above configuration creates a secret and publishable key for a new register created with the /register service.
API Keys requires using a User Auth Repository
Your users need to be persisted in an AuthRepository in order to use the API Key AuthProvider. The list of support Auth Repositories are listed on in the documentation. Although you can use your own custom User Auth Repository if it implements IUserAuthRepository and IManableApiKeys interfaces.
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
An API Key is assigned to a User - all of ServiceStack AuthProviders revolves around Authenticating Users. One idea is to create a "User" to represent that App Server. You can use the IManageApiKeys API to create your own API Keys, there's an example of using this in the code-snippet for creating API Keys for existing Users.
Do I also have to implement my own ApiKeyAuthProvider similar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
You wont need to implement anything to use the existing ApiKeyAuthProvider but if it doesn't do what you need you can take ApiKeyAuthProvider.cs and create a customized version that does what you need.
Is there any object / data model for API keys?
The ApiKey class is the model that contains the API Key itself, which is persisted in all supported Auth Repositories.
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
No.
Little prehistory:
I develop RESTful services. That services receives requests from the web frontend and resends it to another server with the actual business logic. I use Shiro to protect my services. Problem is that some business logic functions require a user password. Of course, I can store password in my principal, but I think it is not correct to store credentials there.
Question
So, what is the conceptual right place where I should store credentials to have access inside my REST services?
Update
Ok, I can also store passwords in Shiro sessions, but i don't think that it is the correct place.
Normally, the info is kept in an implementation of AuthenticationToken. This interface has two method: getPrincipal (for example login or email) and getCredentials(). The last is usually used to store a password.
If you look at class UsernamePasswordToken, which is an implementation of this interface, you see that the two are indeed used for username and password.
Now what we did is extend the class AuthorizingRealm for our own authentication mechanism and in the authentication method we store the token in the principal.
#Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
... authentication logic
SimplePrincipalCollection principalCollection = new SimplePrincipalCollection(login, realmName);
principalCollection.add(token, realmName);
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principalCollection, login.getPasswordHash());
return simpleAuthenticationInfo;
}
Now you can get the token later:
PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
AuthenticationToken token = principals.oneByType(AuthenticationToken.class);
I'm creating a new web application that will be written using MVC 5 and Entity Framework Database First Approach. I would also like to use ASP.Net Identity to look after membership, authentication, authorisation etc.
I've read a good bit about the ASP.Net Identity on the web and how it works, however, I am still learning about this topic.
When I created my MVC 5 application in Visual Studio 2013 and looked at the Account Controller my first instinct was that I didn't like what I saw, i.e., a DbContext was being referenced named 'ApplicationDbContext'. The reason I didn't like this was because I prefer to keep my DbContext in the appropriate project within my solution, i.e., in my Model layer which adheres to the separation of concerns logic.
Also, the out of the box MVC 5 project uses Entity Framework Code First to create a default database and tables to store the Users, Roles etc.
Because I must use an existing database with an existing User table, this approach does not suit my needs.
I still want to use the latest ASP.Net Identity for my application as it looks to have many benefits, therefore, I found this article which stripped back alot of the Entity Framework code but still got OWIN powered authentication into an ASP.NET MVC.
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux
Using the tutorial above, here is the HttpPost Login method for my Account Controller
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
//Calling my own custom Account Service which validates users login details
var user = _AccountService.VerifyPassword(model.UserName, model.Password, false);
if (user)
{
var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, model.UserName), }, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);
//ToDo: Manually adding Role, but will pull from db later
identity.AddClaim(new Claim(ClaimTypes.Role, "guest"));
AuthenticationManager.SignIn(new AuthenticationProperties
{
IsPersistent = model.RememberMe
}, identity);
return RedirectToAction("Index", "MyDashboard");
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
return View(model);
}
In my previous MVC applications I usually rolled my own custom membership and when a User logged into the site and was authenticated, I would have stored the any additional user details such as userID, DOB etc in the UserData string of the FormsAuthenticationTicket.
As the code above does not use FormsAuthentication, instead it uses OWIN CookieAuthentication, I am not sure how to store this additional user data.
Therefore, I have a few questions about the problems I am experiencing.
How do I store the userID or any other additional piece of user data (DOB etc) the way I used to in FormsAuthentication? Is this done by adding a Claim to the identity?
Does the method of using ASP.Net Identity/ OWIN above seem correct considering I am using Entity Framework Database First with an existing database?
Should I be using the out of the box code that is used in the Account Controller, i.e., UserManager, ApplicationUser, ApplicationDbContext etc and hooking this up to work with my existing database?
I apologise if my question is confusing, I suppose I'm just a little unsure of what approach I should be using whilst attempting to use ASP.Net Identity in my latest project.
Any feedback would be greatly appreciated.
Thanks.
1) The new Katana Cookie middleware supports claims. This is what makes this better than forms auth cookie; claims model any key/value pair and those can be stored in the authentication cookie. See this post for more details:
http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/
2 & 3) As far as your storage for identity data, if you need to work with an existing table then you might not be able to use Microsoft's EF provided classes. Instead you'd be left on your own to implement IUserStore and all the other store interfaces your app needs. I'm not certain it's worth changing what you're already using to store the user data.
Keep in mind that the OWIN/Katana part is separate from the identity storage.
Here is the solution
To speed things up you can add sample app to your project and start by modifying the sample app, Samples app includes confirmation email, password recovery, roles admin and user role management etc. NuGet package is at:
Install-Package Microsoft.AspNet.Identity.Samples -Pre
See full details on sample app here: ASP.NET Identity 2.0: Customizing Users and Roles
Controll access to controller or Action by using below attributes
[Authorize] //Anyone with authorization
[Authorize(Roles="Administrator")] //Admin role only
Check if user is in role by
HttpContext.User.IsInRole("Administrator")
UserManager.IsInRole(userID, "Administrator")
Get profile data by
// Create manager
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(new ApplicationDbContext()))
// Find user
var user = manager.FindById(User.Identity.GetUserId());
var profileProperty_1 = user.profileProperty_1
I have a simple jQuery mobile PhoneGap application which uses ajax call to server to authenticate a users credentials against servers db (uses CORS).
Once user is authenticated I setup some local storage variables for the session but I suspect this is not a secure method of maintaining state.
I'm wondering if there is a better & more secure way to keep track of the users session state. At the moment I'm thinking of implementing some kind of token based handshake between the app & the server for each subsequent server call post logon. I'm hoping there is a better more standard way to implement secure sessions in PhoneGap.
I think you shouldn't save origin credentials in local storage. At first, you should encrypt credentials by your encrypt algorithms and you can save it in local storage or preference(Android/iOS - best is store in preference) or anywhere you want. If another person get credentials, it have been encrypt, they not use it to authenticate with server(Only you had decrypt algorithms).
Continue, you must do something to prevent other person decompile your app. They will have your decrypt algorithms and use it to decrypt credentials-->origin credentials-->post to server success.
Have many way to secure your app, you can search and research.
Code demo in Android:
SharedPreferences sharedPref = getSharedPreferences("account", Context.MODE_PRIVATE);
Editor editor = sharedPref.edit();
user = your_encrypt(username);
pass = your_encrypt(password);
//encrypt and save account
editor.putString("username", user);
editor.putString("password", pass);
editor.commit();
//get account
String u = sharedPref.getString("username", "");
String p = sharedPref.getString("password", "");
//decrypt username/pass
username = your_decrypt(u);
password = your_decrypt(p);
We have an MVC 2/Entity Framework app that is a replacement/rewrite of an existing system. It's been using ASP membership for security during development but now we need to replace this so it is compatible with the customers existing security infrastructure, partly to allow both old and new systems to run side by side for a while and also because they already have a process and system to setup customers and we can't replace this yet.
The existing security centers around a table in the database that stores a certificate number mapped to a customerid. The customerid is then used to filter relevant data sent back in the UI.
My question is what is the most efficient way to go from certificate number to customerid. Each MVC controller action can grab the certificate number from the HTTPContext and do a look up in the security table to get the customerid but it seems inefficient to this on every controller action. The system could have 1000 concurrent users. We are thinking that it should work similiar to ASP.NET membership, where a username/password login generates a security token that is then placed in a cookie. Instead we would have the certificate replace the username/password login but it would still generate a security token.
The problem is we don't know enough about this system to determine how to go about it, or even if it's the best way forward. If anyone can offer any advice or pointers to how we would implement this it would be much appreciated.
Either
add it to the users Session once you look it up so its available upon login.
add it to the forms auth ticket (make sure you are patched for the POET vulnerability
or this could be forged)
or
cache the table in memory and do you lookups as required. this might be 'slightly' less efficient than session if you are already using the session because you will then be locking two collections (normal session usage) and the collection you store this in will have to be synchronized.
If you choose to store this information in the ticket you can create a CustomIdentity object to store this customer id in.
/// <summary>
/// Deserializes the forms auth cookie with our userid, companyid, etc.
/// </summary>
/// <param name="sender">
</param>
/// <param name="e"></param>
void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
CustomIdentity id = new CustomIdentity(ticket);
//Assign the roles. If they aren't available, get from the session.
//The problem is when we use this custom principal it seems our roles arent populated.
GenericPrincipal principal = new GenericPrincipal(id, new string[] { "User" });
HttpContext.Current.User = principal;
}
}
}
After each request is authenticated via the forms auth ticket you can deserialize this information into a Customer IIdentity object which can then be read throughout the application via:
int companyId = ((CustomIdentity)HttpContext.Current.User.Identity).CompanyId