Non-interactive authentication fails with WsTrust server issue MSIS7068 - python

Setup:
Users are created on On-Prem AD and synced to Azure AD via Azure AD Connect
I have a single-tenant app set up on Azure AD
I created a user (On-Prem, synced to AAD) that can authenticate without MFA (we need to use username-password authentication due to an internal limitation).
Here is the non-interactive authentication code:
import msal
# create a public client app
authority_url = f"https://login.microsoftonline.com/{TENANT_ID}"
msal_app = msal.PublicClientApplication(client_id=CLIENT_ID, authority=authority_url)
# acquire token
token = msal_app.acquire_token_by_username_password(username=USERNAME, password=PASSWORD, scopes=SCOPES)
I'm getting the following error:
Traceback (most recent call last):
File "/./scripts/aad.py", line 8, in <module>
token = msal_app.acquire_token_by_username_password(
File "/usr/local/lib/python3.10/site-packages/msal/application.py", line 1420, in acquire_token_by_username_password
response = _clean_up(self._acquire_token_by_username_password_federated(
File "/usr/local/lib/python3.10/site-packages/msal/application.py", line 1447, in _acquire_token_by_username_password_federated
wstrust_result = wst_send_request(
File "/usr/local/lib/python3.10/site-packages/msal/wstrust_request.py", line 60, in send_request
return parse_response(resp.text)
File "/usr/local/lib/python3.10/site-packages/msal/wstrust_response.py", line 49, in parse_response
raise RuntimeError("WsTrust server returned error in RSTR: %s" % (error or body))
RuntimeError: WsTrust server returned error in RSTR: {'reason': 'MSIS7068: Access denied.', 'code': 'a:FailedAuthentication'}
Searching through Google I found that this can be caused by MFA, but the user is excluded from MFA. I've also verified that there are no Conditional Access policies in place to block the user accessing the app.
Using Interactive auth works as expected. Any ideas on how to get non-interactive auth to work or what might be the issue here?

First, no guesswork! You would need to login to Azure AD with elevated privilege (Security Reader at the least if not Global Administrator).
Go to Enterprise Applications and locate your application by client id.
One you are at the application, go to Sign-in tab/pane.
Review the sign-in activities. You should see the reason authentication failed in overview tab. Look at the Conditional Access tab and you will know if there is any policy that blocked the sign-in.
Take action based on what you identified in sign-in activity.
Okay, I am going to make an educated guess! When you login as non-interactive, you have two authentication choices - ROPC and Client Credential- both requires client_secret to be passed in the request but you have not! Since you are using username and password, it implies that msal is using ROPC and you must include client secret.

Related

Sharepy library freezes at entering username in PyCharm

I'm trying to authenticate to SharePoint Online. Using sharepy v 2.0, pyCharm community edition, and python 3.9.
When I run:
'sharepy.connect('siteurl')'
From within PyCharm, Sharepy will freeze after I input my username in the run dialog box.
If I add the 'username' parameter and run it. Nothing happens. I'm never prompted for a password
If I use the console and enter in sharepy.connect('siteurl') then username and password (same goes for passing those parameters) I will get an error:
Traceback (most recent call last):
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\sharepy\auth\adfs.py", line 75, in _get_token
token = root.find('.//wsse:BinarySecurityToken', ns).text
AttributeError: 'NoneType' object has no attribute 'text'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\sharepy\session.py", line 15, in connect
return SharePointSession(site, auth=autoauth)
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\sharepy\session.py", line 61, in __init__
self.auth.login(self.site)
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\sharepy\auth\adfs.py", line 27, in login
self._get_token()
File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\sharepy\auth\adfs.py", line 77, in _get_token
raise errors.AuthError('Token request failed. Invalid server response')
sharepy.errors.AuthError: Token request failed. Invalid server response
It should be noted I'm getting O365 from godaddy and the login page is federated? I think is the correct term.
According to the new release of Sharepy, this shouldn't matter.
Has anyone else had this freezing problem happen for them?
How would I authenticate with sharepoint using sharepy given my current situation?
The source of this problem ended up being GoDaddy. As we were federated using GoDaddy as the O365 provider. There was no way to authenticate correctly using sharepy.
The ultimate solution was to defederate away from GoDaddy (pretty easy to do thanks to this guy: Defederation Guide)
The reason we were unable to authenticate was because our provider redirects the login to their own login site. And unfortunately the sharepy builtin method of "auth" wouldn't work with GoDaddy.
I tested this theory before migrating away from GoDaddy. By using a fresh tenant. I also found that when you enable MFA the password/username method of authentication doesn't work.
NOTE: When new tenants are created they utilize a blanket security protocol which forces MFA. Even though MFA is shown as disabled in the Azure AD > Users section. To turn this off you must disable "Security Defaults": portal.azure.com > Azure Active Directory > Properties > "Manage security defaults" (at the bottom of the screen, its a small hyperlink).
A note on MFA and authentication with sharepy. There are methods to leave MFA enabled which work with other sharepoint/python things. I haven't tested them using sharepy yet, but will be turning on MFA and using one of the following methods:
App Password
Sharepoint API client secret
Azure App Registration (Azure App Reg)

Access denied for service account when accessing IAP-protected application

Trying to let a python command line to access(HTTP GET) IAP-protected application.
With https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/iap/make_iap_request.py
But 403 err occurs Exception: Service account xxx#xxxxxxxxx-production.iam.gserviceaccount.com does not have permission to access the IAP-protected application.
Following methods have been tried, but still issue persists as above
1. remove/create the service account
2. re-create the json key file
3. grant the service account project owner permission
if __name__ == '__main__':
os.environ[
"GOOGLE_APPLICATION_CREDENTIALS"] = '/Users/foo/bar.json'
print make_iap_request('https://foo.com/', 'xxxxtheidforthatiapservice.apps.googleusercontent.com')
I think you need to follow the Authenticating from a service account procedure:
Use an OpenID Connect (OIDC) token to authenticate a service account
to a Cloud IAP-secured resource.
Add the service account to the access list for the Cloud IAP-secured project.
Generate a JWT-based access token. This uses a target_audience additional claim that requires a client ID. To find
your client ID, follow the steps below:
a. Go to the Cloud IAP page.
b. Find the resource you want to access, then click More > Edit
OAuth Client.
edit OAuth client on the More menu
c. On the Credentials page that appears, note the client ID.
Request an OIDC token for the Cloud IAP-secured client ID.
Include the OIDC token in an Authorization: Bearer header to make the authenticated request to the Cloud IAP-secured resource.
I faced the same problem.
You have to run the script authenticated as a service account used to access the IAP-protected application programmatically. You can do so either by running script directly from VM which uses that service account as default, or you will need to download SA credentials and do it locally Obtaining an OIDC token from a local service account key file
Besides that, you also need to assign the IAP-secured Web App User role to the desired Service Account for that particular IAP-protected app.
After that, rerun the script.

Accessing Office 365 ProPlus OneDrive folder using the official Python SDK

We are currently trying to access a folder of an Office 365 ProPlus tenant using the official OneDrive SDK for Python (https://github.com/OneDrive/onedrive-sdk-python). One of our clients would like to use a OneDrive folder as a way of storing and sharing programmatically generated files, therefore, we would like to provide basic file operations.
We have a working solution for a personal OneDrive account, however, when we try to apply the same approach for their OneDrive, we face an issue during the authentication process.
We asked them to register the application in the Azure AD following the steps in the official documentation. Next, they sent us the redirect URI, client ID and client secret that we included in our script. We are trying to use the following code:
redirect_uri = 'REDIRECT_URI'
client_secret = 'CLIENT_SECRET'
client_id='CLIENT_ID'
discovery_uri = 'https://api.office.com/discovery/'
auth_server_url='https://login.microsoftonline.com/common/oauth2/authorize'
auth_token_url='https://login.microsoftonline.com/common/oauth2/token'
http_provider = onedrivesdk.HttpProvider()
auth_provider = onedrivesdk.AuthProvider(http_provider,
client_id,
auth_server_url=auth_server_url,
auth_token_url=auth_token_url)
auth_url = auth_provider.get_auth_url(redirect_uri)
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
However, we get the following error message when executing the last line:
Traceback (most recent call last):
File "onedrive-test.py", line 25, in
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
File "/home/username/.local/lib/python3.6/site-packages/onedrivesdk/helpers/GetAuthCodeServer.py",
line 60, in get_auth_code
s = GetAuthCodeServer((host_address, port), code_acquired, GetAuthCodeRequestHandler)
File "/home/username/.local/lib/python3.6/site-packages/onedrivesdk/helpers/GetAuthCodeServer.py",
line 76, in init
HTTPServer.init(self, server_address, RequestHandlerClass)
File "/usr/lib/python3.6/socketserver.py", line 453, in init
self.server_bind()
File "/usr/lib/python3.6/http/server.py", line 136, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.6/socketserver.py", line 467, in server_bind
self.socket.bind(self.server_address)
socket.gaierror: [Errno -2] Name or service not known
We also tried opening the auth_url manually, which took us one step further, but still could not authenticate the application with the following error:
AADSTS50020: User account 'USER ACCOUNT' from identity provider
'live.com' does not exist in tenant 'TENANT NAME' and cannot access
the application 'CLIENT ID' in that tenant. The account needs to be
added as an external user in the tenant first. Sign out and sign in
again with a different Azure Active Directory user account.
We have two questions:
What might casue the first error? This is the comment (see below) that can be found in the readme of the SDK about using the GetAuthCodeServer class. It seems to us that the server cannot be run. Are there any not explicitly defined dependencies that we should be aware of before trying to run the webserver? (We are running the script on Ubuntu 18.10)
If you want to remove some of that manual work, you can
use the helper class GetAuthCodeServer. That helper class spins up a
webserver, so this method cannot be used on all environments.
With respect to the second issue, can you recommend proper material for configuring OneDrive for Business for our use-case? We went through a lot of documentation, but after long hours of research, we still could not find the correct way to fix that issue, especially since we do not have direct acces to the tenant and we cannot easily experiment with things. We would need to give a step-by-step cookbook to our client to set up everything on their side.
Any help would be much appreciated! :)

Azure ADAL for Python - facing issue with acquire_token_with_username_password method

I am trying to retrieve access token using azure user id and password .
Initially I tried with the following python code block
import adal
context = adal.AuthenticationContext(AUTHORITY)
token = context.acquire_token_with_client_credentials(
"https://management.azure.com/",
CLIENT_ID,
CLIENT_SECRET)
This is returning the token without any issue .
I am following an example from https://github.com/AzureAD/azure-activedirectory-library-for-python for retrieving the token using username and password and the code block is the the following
token2 = context.acquire_token_with_username_password("https://management.azure.com/",USER_NAME,PASSWORD,CLIENT_ID)
In this case ,no token is returned , instead following response is returned .
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\authentication_context.py", line 145, in acquire_token_with_username_password
return self._acquire_token(token_func)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\authentication_context.py", line 109, in _acquire_token
return token_func(self)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\authentication_context.py", line 143, in token_func
return token_request.get_token_with_username_password(username, password)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\token_request.py", line 286, in get_token_with_username_password
token = self._get_token_username_password_federated(username, password)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\token_request.py", line 252, in _get_token_username_password_federated
username, password)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\token_request.py", line 211, in _perform_username_password_for_access_token_exchange
username, password)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\token_request.py", line 198, in _perform_wstrust_exchange
result = wstrust.acquire_token(username, password)
File "F:\All_Python\Python_Setup\Python27\lib\site-packages\adal\wstrust_request.py", line 160, in acquire_token
raise AdalError(return_error_string, error_response)
adal.adal_error.AdalError: WS-Trust RST request returned http error: 500 and server response: <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><s:Header><a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><u:Timestamp u:Id="_0"><u:Created>2017-06-07T12:12:56.567Z</u:Created><u:Expires>2017-06-07T12:17:56.567Z</u:Expires></u:Timestamp></o:Security></s:Header><s:Body><s:Fault><s:Code><s:Value>s:Sender</s:Value><s:Subcode><s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:FailedAuthentication</s:Value></s:Subcode></s:Code><s:Reason><s:Text xml:lang="en-US">ID3242: The security token could not be authenticated or authorized.</s:Text></s:Reason></s:Fault></s:Body></s:Envelope>
Process finished with exit code 1
If anybody has any idea on this, please let me know .
According to the information of error stack, per my experience, due to the error comes from the method _get_token_username_password_federated and 500 error code for WS-Trust RST request, it seems that the user/password you used for acquiring token not created in the Azure AD of your app registed, but looks like that created in a federated AD.
Please try to do the two ways below for inspection the issue.
Create a new user in the Azure AD of your app registed on Azure portal with your admin accout, then use the new user/password for retrieving the token.
Inspect your Azure AD configuration to make sure whether deployed Active Directory Federation Services and the current use/password created in a federated AD instance.

How to programmatically post to my own wall on Facebook?

I'm trying to make a simple program to post something to my wall on Fcebook in Python. I tried using this example from pythonforfacebook:
import facebook
oauth_access_token = "****"
graph = facebook.GraphAPI(oauth_access_token)
me = "****"
profile = graph.get_object(me)
graph.put_object(me, "feed", message="I am writing on my wall!")
I tried going to the developer center and making an App. For "Select how your app integrates with Facebook",I chose "Website with Facebook Login" (I don't actually have a website, I just have a program that should post to my facebook wall, but this is the closest option that matches what I want to do...).
However, when I run this, it says:
$ python a.py
Traceback (most recent call last):
File "a.py", line 7, in <module>
graph.put_object(me, "feed", message="I am writing on my wall!")
File "/usr/lib64/python2.7/site-packages/facebook.py", line 140, in put_object
post_args=data)
File "/usr/lib64/python2.7/site-packages/facebook.py", line 298, in request
raise GraphAPIError(response)
facebook.GraphAPIError: (#200) The user hasn't authorized the application to perform this action
How can I log in as the user and authorize my App? Am I even taking the right approach? I don't actually have a website, I just have a program, for the website field I literally entered "http://google.com" and it worked.
I made it work by getting a new token with permissions to post on my wall (specifically, the "publish_actions" permission). I did this by using the Graph API Explorer, selecting my application in the dropdown menu, pressing "Get Access Token" and checking "publish_actions". The only problem is the token expires after an hour.
You must authorize the user for publish_action/publish_stream permission to post on your wall.
If your only task is to post on the wall/ get the basic info; you can use the APP Access Token instead of user access token for performing the action once you've authorized the app. To get the App Access Token, you can uuse-
GET /oauth/access_token?
client_id={app-id}
&client_secret={app-secret}
&grant_type=client_credentials
Or, directly from here. But do not hard code it in your app (for security reasons)
Or, if you want to perform other actions too on the user's behalf you can extend the user token to 2 months validity. Read here for more details
For those of who stumble upon this post after April 24th, Facebook has stopped support for such API calls.
As of April 24,2018, the publish_actions permission has been removed. Please see the Breaking Changes Changelog for more details. To provide a way for your app users to share content to Facebook, we encourage you to use our Sharing products instead.

Categories