We are setting up a new application framework and we are wondering the best practices for setting up database security for our users. In our old framework, there was a user logon process and once the user was logged on, the framework controlled what forms and menu options a user was permitted to. All users accessed the database with the same user account.
The disadvantage to this approach is that you cant use SYSTEM_USER to find out who is making a particular database request.
The new framework will still have a logon form and it will control what menu options a person can access. Should we be setting up a database user account every time a new user is added to our application? Would this cause any licensing concerns since you cant use connection pooling?
It won't cause licensing issues, but it will generate a large number of connections which may cause performance issues.
A better solution would be to add a parameter to your stored procedures to pass in the UserID of the current user so that it can be logged.
If passing in the parameter is undesirable, you can put the current user in CONTEXT_INFO(), or if you are using SQL 2016, SESSION_CONTEXT() and log it from there. https://www.mssqltips.com/sqlservertip/4094/phase-out-contextinfo-in-sql-server-2016-with-sessioncontext/
Related
I am new to Salesforce, but am an experienced developer. I am provided a link to a Salesforce report, which mostly has the right filters (query). I would like to use an REST API to pull that information as CSV or JSON so that I can do further processing on it.
Here are my questions:
Do I need special permissions to make API calls? What are they?
Do I need to create an "app" with client-key & secret? Does my admin need to grant me permission for this too?
There are a lot of REST APIs from Salesforce, which one do I need to get the info from the report? Analytics?
How do I authenticate in code?
You'd have to work with the System Administrator on the security pieces. Anybody who knows how the company works, can all users see everything, is there Single Sign-On in place, how likely is the report to change...
You will need an user account to pull the data. You need to decide if it'll be some "system account" (you know username and password and have them stored in your app) or can it run for any user in this org. It might not matter much but reports are "fun". If there will be data visibility issues 6 months from now, you'll be asked to make sure the report shows only French data to French users etc... you can make it in report filters or have multiple reports - or you can just use current users access and then it's the sysadmin that has to set the sharing rules right. (would you ever think about packaging what you did and reusing in another SF instance? Making a mobile app out of it? Things like that, they may sound stupid now but will help you decide on best path)
The user (whether it'll be system account or human) needs Profile permissions like "API Enabled" + whatever else you'd need normally ("Run Reports" etc). If you're leaning towards doing it with system user - you might want to look at Password Policies and maybe set password to Never Expires. Now this is bit dangerous so there would be other things you might want to read up about: "API only user" (can't login to website), maybe even locking down the account so it can login only from certain IP ranges or at certain times when the job's supposed to be scheduled...
Connected App and OAUth2 stuff - it's a good idea to create one, yes. Technically you don't have to, you could use SOAP API to call login, get session id... But it's bit weak, OAuth2 would give you more control over security. If you have sandboxes - there's little-known trick. You can make connected app in production (or even totally unrelated Developer Edition) and use client id & secret from it to login to sandboxes. If you create app in sandbox and you refresh it - keys stop working.
(back to security piece - in connected app you can let any user allow/deny access or sysadmin would allow only say these 3 users to connect, "pre-authorize". Could be handy)
Login - there are few REST API ways to login. Depends on your decision. if you have 1 dedicated user you'll probably go with "web server flow". I've added example https://stackoverflow.com/a/56034159/313628 if you don't have a ready SF connection library in your programming language.
If you'll let users login with their own credentials there will be typical OAuth "dance" of going to the target page (Google login, LinkedIn, Twitter...) and back to your app on success. This even works if client has Single Sign-On enabled. Or you could let people type in their username and pass into your app but that's not a great solution.
Pull the actual report already
Once you have session id. Official way would be to use Reporting API, for example https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm
A quick & dirty and officially not supported thing is to mimic what happens when user clicks the report export in UI. Craft a GET request with right cookie and you're golden. See https://stackoverflow.com/a/57745683/313628. No idea if this will work if you went with dedicated account and "API access only" permission.
So from what I have read on IdentityServer I should be storing details about the user such as first name and last name inside claims. How would a web application then be able to access the claim information? Since the User Info endpoint requires a valid access token representing the user, I suppose I would need to make an API that could access that returned the profile information of other users? Is this the right way to do it? (use case, web page needs to display contact details that are stored in claims of another user)
Also what would be the way for multiple language profile information be stored and retrieved in the claims? For example a user can have a name/title in multiple languages. I'm thinking of making [LanguageCode]_[ClaimType] (fr_first_name) naming convention and either adding all languages to just the profile IdentityResource or creating separate resources per language.
Your best bet is to set up a project using the IdentityServer4 QuickstartUI example and review that code to better understand how it all works. As of version 4, Identity Server is only focused on the sign-in / sign-out process and the various flows around authentication. They also provide a basic EF-driven persistence model, and they also support the ASP.NET Core Identity persistence model (also EF-driven), but both of those are not meant to be production-ready code.
Basically, persistence of user details is considered your responsibility. That being said, the cookies used for ASP.NET Core authentication greatly restricts how much data you can/should store as claims. The best model is to keep "real" identity provider (IDP) claims as claims, don't add new claims to that list, copy what you need into some other separate user-data table you manage completely, and use the unique claims identifier (almost always "subject id") as the key to your user data. This also makes it easier to migrate a user to another IDP (for example, you'll know user details for "Bob" but he can re-associate his user data away from his Facebook OIDC auth to his Google auth).
Basic persistence isn't too difficult (it's only 12 or 13 SQL statements) but it's a lot more than will fit in a Stackoverflow answer. I blogged about a non-EF approach here -- also not production-ready code (for example, it has ad-hoc SQL to keep things simple), but it should get you started.
We have the angularjs application where we have different roles associated to the users. For ex: the two roles are Admin and Local. Based on the role, we show some menu items for the Admin and adds more features/screen to the Admin .
The userInfo with the Admin Property is returned from the login response and based on what we decide which all menu and screens to be rendered .
But if we user the developer tool, and the set the break point where the admin property is used, and set the admin property as true the user even he is a local user would be able to access admin privileges .
In short who has some idea about the javascript code can get the admin privileges . Is there any idea other than minification of the code to prevent this kind of security threats
Thanks
As the front-end of your application will run on the client machine there is actually no way to stop a user from debugging or modifying the code. Thus it's impossible to prevent someone from tricking their local instance of the application to think it's signed in as an administrator.
If you simply want to hide the admin interface, one possibility is to have separate (or additional) templates for administrators and restrict access to these based on the user's privilege. If there is anything to be gained from this is up to you. You will still need to validate the rights to execute any privileged action on the server anyway. Obtaining administrative privileges on the client must never be the same as obtaining them on the server side.
What's the best practice or the common way of keeping (or not keeping) Evernote users in your application's database?
Should I create my own membership system and create a connection to Evernote accounts?
Should I store Evernote user data (or only part of it) in my own app and let the user log in only with Evernote?
Summary: you must protect their data but how you protect it is up to you. Use the integer edam_userId to identify data.
I think the API License agreement covers protection in the terms:
you agree that when using the API you will not, directly or indirectly, take or enable another to take any of the following actions:...
1.8.4 circumvent or modify any Keys or other security mechanism employed by Evernote or the API;
If you cache people's data and your server-based app lacks security to prevent people looking at other's data, then I think you're pretty clearly violating that clause. I think it's quite elegantly written!
Couple that with the responsibility clause 1.2
You are fully responsible for all activities that occur using your Keys, regardless of whether such activities are undertaken by you or a third party.
So if you don't protect someone's cached data and another user is able to get at it, you're explicitly liable.
Having cleared up the question of your obligations to (as you'd expect) protect people's data, the question is how do you store it?
Clause 4.3 covers identifiers pretty directly although it's a bit out of date now that we are all forced to use oAuth - there are no passwords ever entered into anything other a web view. However, mobile or desktop client apps must provide a mechanism for the user to log out, which must completely remove the username and password from your application and its persistent storage.
For a web app, you can't even save the username: If your Application runs as an Internet service on a multi-user server, you must not ask for, view, store or cache the sign-in name or password of Evernote user accounts.
The good news is that you can rely on the edam_userId value which comes back to you in the oAuth token credentials response, as discussed here.
When you look at the Data Model, you can see the unique id under the User and going into the User struct, see the reassuring definition The unique numeric identifier for the account, which will not change for the lifetime of the account.
Thinking about the consequences, as you can't get the user id until you have logged into the service, if you want to provide a local login for people you will have to link your local credentials to the user id. That may irk some people if they have to enter a username twice but can't be helped.
You can allow users to log-in via OAuth. Here's a guide on how that process works.
But you'll probably also want to store a minimal amount of user data, at least a unique identifier, in your database so you can do things like create relationships between the user and their notebooks and tags. Refer to the Evernote data model for those relationships. If you're using rails, this will also help you take advantage of rails conventions.
I am using Entity Framework and have the same model on many databases and servers. I want to set my connection string at runtime based on the logged in user. I am currently overriding CreateObjectContext() in my DomainService and setting the connection string there. This works great, but I'm concerned with the lack of security. For example, in my DomainService, I have an invoke method called SetConnectionString() where I pass in the connections string each time I need a new Entity. This is being done from the DomainContext (client side). Since I am using SQL Integrated Security, I am concerned that someone could manipulate the connection string on the clinet and get access to a database that they are not authorized to use.
What is the most secure way to dynamically set the connection string for the domain entity I want to use at runtime?
I do have the database name and server settings in a database that I could look up from the DomainService if I passed in my project id or some other piece of information, but I am then right back to the same issue - someone could easily spoof this info.
Ideas??
-Scott
Hopefully my answer is relevant as the same security issues are faced by flash developers...
The only way to make this really secure ("this" being database connections from your client side code) is to make each user only have read-only access to their data in the database.
As you are realizing, there is no way to stop the user from monitoring/modifying data that you are sending back to the server. Even if you encrypt the communication, the user still has access to the code and in the case of flash, source code due to trivial decompilation.
I am not a DB developer, but I do security audits of stuff like you are asking often, so the following advice could be wrong, but I just googled, and it seems like maybe you could use views to restrict users (sets of credentials) to specific information.
If not, this article seems relevant to what you want:
http://technet.microsoft.com/en-us/library/cc966395.aspx
What about using the ASP.NET membership framework? Tie the user login with a Login call in the framework to make sure the user an authorized user. Add a "RequiresAuthentication" attribute to each of the functions you want to protect in your domain service.
Here are more details on using ASP.NET membership with Silverlight: WCF RIA Services - Authentication, Roles, and Profiles