I have created a FastAPI application which has a database with postgresql. The application uses docker, a container for the app and another for the database. Furthermore, it implements authentication with JWT tokens and encrypts passwords with bcrypt. My problem is that logically the endpoint to create new users requires authentication. How do I create the first user? That is, temporarily remove authentication from the endpoint and create the user, but I must write the step by step for project delivery and I do not consider pertinent to give that solution.
I tried to build the containers and write the steps to insert a user from the database container terminal. However the record is saved in the database but with the password unencrypted, so when I try to authenticate it doesn't work.
In summary, how to create that first user?
You should define a startup event which would populate the database with an admin account for you. This way, you don't ever have to temporarily remove authentication while still having a valid account that you can use. Here's an example of how you could do it:
from fastapi import FastAPI, Request
from domain import *
app = FastAPI()
users = {}
#app.on_event('startup')
async def populate_admin():
if "admin" not in users:
users['admin'] = {
'username': 'admin_user',
'password': hash('totally_secret_password')
}
Naturally, you would want to use an actual database for your persistance layer and an actual hash function like bcrypt. Another thing commonly implemented is to read the username and password of the "admin" user from some config file or environment variables instead of having it hard-coded in the function. Hope this helps!
I currently have Django and LDAP working. However, I want to limit LDAP authentication to only the accounts within the local account DB.
i.e if no local account is present deny access/ldap auth occurring.
From looking at the options from LDAPSearch I'm unable to find a direct option to provide this. Any ideas on how to achieve this?
Limiting based on LDAP OU is not an option based on the LDAP address structure in place.
Thanks,
As felix001 pointed out in the comments, the project documentation describes a flag AUTH_LDAP_NO_NEW_USERS:
Prevent the creation of new users during authentication. Any users not already in the Django user database will not be able to login.
Enabling it in the settings turns the desired behaviour on:
# settings.py
...
AUTH_LDAP_NO_NEW_USERS = True
However, this feature is not contained in the currently released 1.7.0 version, so a backport is necessary. The least invasive impl I can think about is:
# myapp/backend.py
from django_auth_ldap import backend as ldap_backend
# backport for AUTH_LDAP_NO_NEW_USERS setting
ldap_backend.LDAPSettings.defaults.update(NO_NEW_USERS=False)
class MyLDAPBackend(ldap_backend.LDAPBackend):
def get_or_build_user(self, username, ldap_user):
user, built = super().get_or_build_user(username, ldap_user)
if self.settings.NO_NEW_USERS and built: # user was not found in local db and created instead
raise ldap_user.AuthenticationFailed(
f'username {username} does not exist in local DB.'
)
return user, built
Activate AUTH_LDAP_NO_NEW_USERS in settings and use the custom backend instead of the LDAPBackend for now:
# myapp/settings.py
AUTH_LDAP_NO_NEW_USERS = True
AUTHENTICATION_BACKENDS += ('myapp.backend.MyLDAPBackend',)
Dropping the backport is also easy: once the next version of django-auth-ldap is released, the only thing you will need to adapt is the AUTHENTICATION_BACKENDS tuple (and of course, remove the myapp/backend.py module).
I'm trying to use BCryptAuth to protect resource as well as for login system.
I'm trying to fetch only one document based on user's email entered at login page.
class BCryptAuth(BasicAuth):
def check_auth(self, email, password, allowed_roles, resource, method):
account = app.data.driver.db['users'].find_one({'email': email})
return account and \
bcrypt.hashpw(password.encode('utf-8'),account['salt'].encode('utf-8')) == account['password']
But when i try to access the users end point via postman, it actually authenticates but returns all documents. I'm bit confused. If my approach is wrong, pls provide me one.
The Auth class you mention will only allow or not the access to the API. It does nothing for resource filtering.
If you want resource filtering when getting users, you can create an event hook and make a pre-GET dynamic filter. Check the documentation, it should help.
I am trying to use simple_salesforce to query salesforce data with Python. I am using my username and password, which I am 100% sure is correct. I got the org ID from logging into Salesforce and looking at my company profile. It's only a 15-digit ID. I am specifically using an orgID to avoid using a security token as I don't know what it is. What am I doing wrong?
Code:
from simple_salesforce import Salesforce
sf = Salesforce(instance_url='https://na1.salesforce.com', session_id='')
sf = Salesforce(password='password', username='email', organizationId='15 digit org id')
Output:
File "C:\Python27\lib\site-packages\simple_salesforce\api.py", line 100, in __init__
proxies=self.proxies)
File "C:\Python27\lib\site-packages\simple_salesforce\login.py", line 124, in SalesforceLogin
code=except_code, message=except_msg))
simple_salesforce.login.SalesforceAuthenticationFailed: INVALID_LOGIN: Invalid username, password, security token; or user locked out.
I wrote most of simple-salesforce (although not the organizationId part, as I don't have an IP-whitelisted account to test against)
The standard/vanilla/regular/99% of users should use version is the simple username, password, security_token method.
So something like this
from simple_salesforce import Salesforce
sf = Salesforce(username='nick#nickcatalano.com', password='nickspassword', security_token='tokenemailedtonick')
By far the most confusing part is the security_token part (and was the part I got snagged with.) It turns out the Security Token is emailed to you after a successful password reset. So if you go into your salesforce account and reset your password, I believe you'll end up with an email with the subject salesforce.com security token confirmation which will contain a Security Token in the email. That's your security_token.
To be honest, the security_token kwarg is more a convenience than anything. In the normal email/password/token flow that most users rely on what is actually being sent is email as the login and {password}{security_token} as the password. I believe you could concat that yourself and just pass in a email and password kwarg if you want, but I figured forcing people to concat the password and token themselves would get go against the simple part of simple-salesforce
There is a way to log in with simple-salesforce with only a username and password. No security token required:
from simple_salesforce import Salesforce, SalesforceLogin
session_id, instance = SalesforceLogin(username='<user>', password='<pass>')
sf = Salesforce(instance=instance, session_id=session_id)
# Logged in! Now perform API actions, SOQL queries, etc.
sf.query_all('<soql>')
Explanation
All examples using simple-salesforce begin with a call to the Salesforce constructor to log in. This constructor accepts either an existing session ID, or authentication credentials to log in and make a new session. When logging in, it calls the lower-level SalesforceLogin function to do the real work, but interestingly SalesforceLogin does not enforce the same constraints on its arguments—it issues the correct SOAP call to log in with just a username and password, without requiring a token or organization ID.
Using this trick, we call SalesforceLogin directly, obtain the new session ID, then pass it directly into the Salesforce constructor. From that point on, we are able to make authenticated API requests.
Note
The version of simple-salesforce on PyPI (i.e. pip install simple-salesforce) is very outdated with the simple-salesforce GitHub repository. The latest version supports additional login parameters like domain for login with custom domains. To get the latest version, use
pip install --upgrade https://github.com/simple-salesforce/simple-salesforce/archive/master.zip
(Pip-installing from zip is faster than using git+ssh:// or git+https://, as noted in this answer.)
Edit
How will resetting my password show me what the token is?
It just will. If user has ever before requested the security token (which is sent to you via email - so you need to have access to the email address associated with your user) - every subsequent password reset will result with new token being generated and emailed to you. On top of that, once you're logged in to the system (to the web version, not via API) you will have an option to reset your token (and again, this will send you an email).
It's like you haven't read or tried anything we have written!
Looking for an answer drawing from credible and/or official sources.
https://help.salesforce.com/htviewhelpdoc?id=user_security_token.htm
https://help.salesforce.com/HTViewSolution?id=000004502
https://help.salesforce.com/HTViewSolution?id=000003783
And from the library's documentation:
https://github.com/neworganizing/simple-salesforce
To login using IP-whitelist Organization ID method, simply use your
Salesforce username, password and organizationId
This. If your IP address is whitelisted - you don't need the token. If it isn't - you NEED to generate the token. Period.
Original answer
I'm not familiar with that Python library but... Go to Salesforce -> Setup -> My personal infromation and check login history. if it contains stuff like "failed: security token required" then you're screwed and you will have to use the security token.
I'm not aware of any bypass that uses org id (I've connected via API from PHP, Java, C#... so I'd be very surprised if that Python library had some magical way to bypass it. You probably are used to passing a session id that assumes you're already authenticated and have a valid session.
Another option would be to check your IP and add it to trusted IP ranges (it's an option in the setup). It's useful when for example whole office has same static IP; less useful if you're working from home.
If that's also a no-go - you might want to look for libraries that use OAuth2 instead of regular SOAP API to authenticate.
Although this is kinda late, somebody searching for this very same issue may be helped as to what I did.
I struggled by adding the company ID as well, but the problem here is, unless you're a self-service user, the company ID can be blank.
sf = Salesforce(password='password', username='email', organizationId='')
As other users mentioned, make sure you're using IP-White listing or it will not work.
A security token is an automatically generated key that you must add to the end of your password in order to log into Salesforce from an untrusted network. For example, if your password is mypassword, and your security token is XXXXXXXXXX, then you must enter mypasswordXXXXXXXXXX to log in. Security tokens are required whether you log in via the API or a desktop client such as Connect for Outlook, Connect Offline, Connect for Office, Connect for Lotus Notes, or the Data Loader.
To reset your security token:
At the top of any Salesforce page, click the down arrow next to your name. From the menu under your name, select Setup or My Settings—whichever one appears.
From the left pane, select one of the following:
If you clicked Setup, select My Personal Information | Reset My Security Token.
If you clicked My Settings, select Personal | Reset My Security Token.
Click the Reset Security Token button. The new security token is sent via email to the email address on your Salesforce user record.
If you ip is whitelisted / trusted and you still get invalid login not using the token, You MUST include the security_token='' in the connection string for it to work.
sf = Salesforce(username='USERNAME', password='PASSWORD', security_token='')
A security token is required to login.
Whenever your password is reset, your security token is also reset.
If you do not have a token and cannot reset it.
Try changing your password.
Thanks.
I was able to test that this was working with my security token against a developer org with no issues. This was all done as a standard user with no administrator privileges. Using the OrgId just failed out.
By resetting my password I received a new security token.
username = login for your instance.
password = your password
The code below should get you logged in.
from simple_salesforce import Salesforce
sf = Salesforce(username='username',password='password', security_token='whatever came in reset password')
Is it possible to use a database for authentication with Trac?
.htpasswd auth is not desired in this install.
Using Trac .11 and MySQL as the database. Trac is currently using the database, but provides no authentication.
Out of the box, Trac doesn't actually do its own authentication, it leaves it up to the web server. So, you've got a wealth of Apache-related options available to you. You could maybe look at something like auth_mysql to let you keep user credentials in a database.
Alternatively, take a look at the AccountManagerPlugin on trac-hacks.org
You can use Account Manager Plugin with SessionStore
The AccountManagerPlugin offers several features for managing user accounts:
allow users to register new accounts
login via an HTML form instead of using HTTP authentication
allow existing users to change their passwords or delete their accounts
send a new password to users who’ve forgotten their password
administration of user accounts
Please refer to http://trac-hacks.org/wiki/AccountManagerPlugin
Do the following on your trac.ini
[components]
; be sure to enable the component
acct_mgr.svnserve.* = enabled
acct_mgr.svnserve.svnservepasswordstore = enabled
; choose one of the hash methods
acct_mgr.pwhash.htdigesthashmethod = enabled
acct_mgr.pwhash.htpasswdhashmethod = enabled
[account-manager]
password_store = SvnServePasswordStore
password_file = /path/to/svn/repos/conf/passwd
; choose one of the hash methods
hash_method = HtDigestHashMethod
hash_method = HtPasswdHashMethod
Now trac will use user in the database