Salesforce OAuth authentication doesnt work with username and password - oauth-2.0

I created a new connected app in salesforce
I am trying to authenticate using username and password - OAuth method to fetch a token using Postman
I am hitting the following endpoint https://login.salesforce.com/services/oauth2/token with my client_id, client_secret, username and password
I am getting the following error:
{
"error": "invalid_grant",
"error_description": "authentication failure"
}
The username and password are verified to be correct independently
What am I missing here?

If you are using Username and Password OAuth authentication, please make sure you have concatenated the unique security key (for the username that you are using) with the password. For instance (example in Python), your request should be:
import requests
import json
params = {
"grant_type": "password",
"client_id": "client_id", # Consumer Key
"client_secret": "client_secret", # Consumer Secret
"username": "username", # The email you use to login
"password": "password + unique_security_key"}
headers = {'content_type':'application/x-www-form-urlencoded'}
r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params, headers=headers)
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)
To get the security key:
Login to your Salesforce Account
Click on your username on the top right-hand side.
On the left-hand side pane, click on Personal > Reset My Security Token
A Unique security token will be sent to your email. Please concatenate the key with your password.
If you still experiencing the error, please check the following steps:
Navigate Apps > Manage Connected Apps > Your Connected App > Edit > OAuth Policies > Enable Permitted users to All users may self-authorize
AND
Manage Apps > Connected Apps > Your Connected App > Enable IP Relaxation to Relax IP restrictions.
Hope this helps.

Related

Azure DevOps PAT API to be able to list all tokens in organization

Need to obtain the list of all tokens in organization.
Used the token to make a call to https://vssps.dev.azure.com/{organization}/_apis/tokens/pats?api-version=6.1-preview.1
My permission in DevOps are set as the Collection Administrator.
Received response was:
{“$id”:“1”,“innerException”:null,“message”:“The requested operation is not allowed.”,“typeName”:“Microsoft.TeamFoundation.Framework.Server.InvalidAccessException, Microsoft.TeamFoundation.Framework.Server”,“typeKey”:“InvalidAccessException”,“errorCode”:0,“eventId”:3000}
Is there some lack of permissions or do I need to set up something else to get list of tokens in organization?
You don't mention how you get your token, and criteria for authentication flow but I will share my adventure that started similarly yours.
I got your exact error while following this guide: https://learn.microsoft.com/en-gb/azure/devops/organizations/accounts/manage-personal-access-tokens-via-api?view=azure-devops
The token I got from that python code just didn't work.
Then I found this code instead: https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/app-aad-token#--username-password-flow-programmatic
While using the same app registration from the link above, I copied my scope and tenantID from the dysfunctional code into this new code, and then go to your app registration --> authentication --> Allow public client flows to yes, see screenshot.
I ran the script after giving the credentials and now the token worked.
Dumping the code for future reference:
# Given the client ID and tenant ID for an app registered in Azure,
# along with an Azure username and password,
# provide an Azure AD access token and a refresh token.
# If the caller is not already signed in to Azure, the caller's
# web browser will prompt the caller to sign in first.
# pip install msal
from msal import PublicClientApplication
import sys
# You can hard-code the registered app's client ID and tenant ID here,
# along with the Azure username and password,
# or you can provide them as command-line arguments to this script.
client_id = '<client-id>'
tenant_id = '<tenant-id>'
username = '<username>'
password = '<password>'
# Do not modify this variable. It represents the programmatic ID for
# Azure Databricks along with the default scope of '/.default'.
scope = [ '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default' ]
# Check for too few or too many command-line arguments.
if (len(sys.argv) > 1) and (len(sys.argv) != 5):
print("Usage: get-tokens-for-user.py <client ID> <tenant ID> <username> <password>")
exit(1)
# If the registered app's client ID and tenant ID along with the
# Azure username and password are provided as command-line variables,
# set them here.
if len(sys.argv) > 1:
client_id = sys.argv[1]
tenant_id = sys.argv[2]
username = sys.argv[3]
password = sys.argv[4]
app = PublicClientApplication(
client_id = client_id,
authority = "https://login.microsoftonline.com/" + tenant_id
)
acquire_tokens_result = app.acquire_token_by_username_password(
username = username,
password = password,
scopes = scope
)
if 'error' in acquire_tokens_result:
print("Error: " + acquire_tokens_result['error'])
print("Description: " + acquire_tokens_result['error_description'])
else:
print("Access token:\n")
print(acquire_tokens_result['access_token'])
print("\nRefresh token:\n")
print(acquire_tokens_result['refresh_token'])

Customising user credentials in resource owner password credential grant type

I have implemented token Authorization of type Resource Owner Password Credential type in web api and it's working completely fine.
E.g. { grant_type : password, userid: usr1, password: pwd }
And it sends me response with access token.
Now I have got new requirement to implement for Authorization using entitytype (1 or 2).
E.g { grant_type : password, userid: usr1, password: pwd, entityType: 1 }
Is there any way that I can customise the credentials and still continue using my so far implemented token Authorization or do I have to change the entire approach altogether. If I have to change entire approach, what it would be?
Thank you.

Authentication failure when using mail Grails plugin

i'm using Grails 2.5.1 and mail:1.0.7 plugin to send emails , but when i'm using it i always getting the bellow error :
Class:javax.mail.AuthenticationFailedExceptionMessage:535-5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 https://support.google.com/mail/answer/14257 qq4sm4579366wjc.14 - gsmtp
although i can login with the provided credentials successfully from the browser !!
here are my configurations in the Config file :
grails {
mail {
host = "smtp.gmail.com"
port =465
username = "****"
password = "***"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
and here is the action :
mailService.sendMail{
to userInstance.toEmail
subject userInstance.subject
html "<strong>Test</strong> "
}
anything i'm missing ?
It may be because of gmail's security feature for less secure apps to get authenticated. Just turn on the access for less secure apps.
Follow below steps:
1 Login to your gmail account
2 Access the url:
https://www.google.com/settings/security/lesssecureapps
3 Select "Turn on"
If you have gmail - settings for plugin are correct (i have the same and they are working) , but if your email is not gmail you must have other config.
By the way if you gmail :
Username and Password not accepted.
your username or password is wrong, try to login with this Username and password, watch out for register of letters.
https://grails.org/plugin/mail

Django-allauth stores an empty token_secret with linkedin_oauth2

I'm trying the make further requests to linkedinAPI and to do so I need both token and token_secret.
I have several test accounts in linkedin, the login process success with all of them, however the token_secret stores (for all of them is empty).
Is that an error? I suspect so because using the pair token/token_secret in subsecuent oauth2 calls I get the following from linkedin
{ "errorCode": 0, "message": "[unauthorized]. The token used in the OAuth request is not valid. AQVvM2f2qefU3vULPS-R46DXN8Mnra9ImG14hzeTvMMcXvBVOEiUl4RTZCJrdFZoTfGGN1fFzLvxG-O_UWB8s8EDr35ZsgwW59y4KilndoEkr105Sg2GR90jmUxpqxU572IiARjN5gxAjfoWC4-_UupKlEtafQn23XQqvXeuLvE-FsPAaSA", "requestId": "VOAL1ULK4X", "status": 401, "timestamp": 1395348629428 }
Further details:
I check these tokens using the shell:
from allauth.socialaccount.models import SocialToken
map(lambda st: st.token_secret, SocialToken.objects.all())
And I get empty output:
[u'', u'', u'']
I found a solution myself so I'll explain it.
I'm not very into oauth2 so I don't know about the process neither if it was normal to have an empty secret_token. So I debugged a bit into the django-allauth code, and I saw that the requests they perform use only the token (no secret token)
Then I changed the library and started using the same they do: requests. And with the following simple script I can make any other request to the linkedin API:
def see_my_groups_json(request, url):
import requests
token = SocialToken.objects.get(account__user_id=request.user.pk)
resp = requests.get(url, params={'oauth2_access_token': token.token})
return resp.json()
You should check the SCOPE parameter for linkedin provider. For example, the next configuration requests permission for accessing user's email address, basic profile and to read and share updates on behalf of the user.
SOCIALACCOUNT_PROVIDERS = {
'linkedin_oauth2': {
'SCOPE': ['r_emailaddress', 'r_basicprofile', 'rw_nus'],
'PROFILE_FIELDS': ['id', 'first-name', 'last-name', 'email-address', 'picture-url', 'public-profile-url']
}
}
If after the token generation, we try to make an API call that requires some other privilege, we will get a 401 status code HTTP response.
django-allauth, by default, r_emailaddress scope or none at all, depending on whether or not SOCIALACCOUNT_QUERY_EMAIL is enabled.
Hope this helps you.

OAuts with Signpost - how to sign POST to get Access token

I'm working with client who provided me with somewhat vague
instructions. Here's what I'm doing (using CommonsHttpOAuthConsumer as
consumer and DefaultOAuthProvider as provider)
I'm able to get response token from doing this:
String requestToken = provider.retrieveRequestToken
(OAuth.OUT_OF_BAND);
this is in form of URL with params so I'm parsing the actual token
out for example:
https://foobar.com/oauth/login_authorize?oauth_token=XRFCGPbES3M2bYZy...
Now - the instructions that I get say:
Given the request token obtained in step 1, login with the user’s
credentials (name and password) as POST parameters and sign the
request with the request token/secret
POST https://foobar.com/oauth/login_authorize
That's where I'm having difficulties. Obviously I have to input that
requestToken somewhere so I do this (post is HttpPost that contains user credentials):
consumer.setTokenWithSecret(requestToken, SECRET);
consumer.sign(post);
It doesn't work. It actually generates 200 status but what I get is a
generic error message.
retrieveRequestToken does not return a request token, it returns an authenticationUrl that you need to send your users to so they can sign in. Request token is saved in provider object.
String authenticationUrl = provider.retrieveRequestToken( call_back_url )
Note: According to the oauth standard the users sign in on the providers site with their credentials. After they have done that you (as a consumer) can get the Access Token and after that you can access their data on the providers site.
// After user has signed in
provider.retrieveAccessToken(null)
// access token is saved in provider and provider knows which consumer uses it
// so now you can sign with your consumer and connect with the request
URL url = new URL( protected_resources_url )
HttpURLConnection request = (HttpURLConnection) url.openConnection();
consumer.sign(request)
request.connect()
If you have the user credentials you can do the authorization in your script
// Using grails and functional-tests
get(authenticationUrl)
// Image the site shows a simple form with username/password and a login button
setRedirectEnabled false
form {
username = "mario"
password = "peach"
click "login"
}
And then do retrieveRequestToken and the code mentioned above
Hope this helps you
// Jonas

Resources