Handling two step authentication using Python requests module - python

My requirement is to capture cookie from authentication server and i'm able to achieve it using requests module. However, this piece of code breaks (doesn't return any cookies) when "two step verification" is enabled. Basically if i enable two-step-verification, it will send secure code to registered devices which can be used as second level of authentication. Appreciate any pointers.
import requests
auth = 'https://auth.corp.xyz.com/authenticate'
params = {"accoundId": "xyz",
"accountPassword": "abc",
"appIdKey": "xxxxxxxxxxxxx"
}
s = requests.session()
r = s.post(auth,params = params)
print r.request.headers['Cookie']
'd01_ac=9eba0c6ec6f1c09bafb29be785ad9d2373d588d3b1633a418ab932166ea5f832ae036a4f2a89a675adc6e31ebdc7c251215a4a354a085865f6c775fb4cd7544d4c64a429f27fce08bc99058d40497202a4abeedb51f73a53f246fe148560GZVX; dslang=US-EN; myacinfo=DAWTKNV2eed01036859507613988fcc6e5540e93e248a4cbee7243868b1bf5f53b3d698002b4823e872d35c848af2be146529062c6ee05e320367fadfe0e5ae507dd3c07baab03e878c12949efbeb9471111e2b0930c38c05a714f3cd8896c8b63a1201468909a0de019534f1652d49f7e7f280a82627920dbdc8a1ea413f570d16b87c063963712d5932d61a658ff380407f96f34c90e58c223d39ca90f11cc76ca521a3babf4c9f21ea0d35b77ece1b0b175ec21bd74d2d9b108759c38b71d285dde24d21c9d2eac3dfe2e4bd01df6968ebc12fe6bf132d80a0232d6b8ee61a7bfe134b86f6662316431313062326531613231MVRYV2'

The idea of 2 step authentication is next:
You app says to the server. I want to authenticate a user. Give me a
token.
Here is a token. Redirect your user to this url and pass a token
with it.
Users logs in on the server
Server redirects user to your site by providing data about user and
a 'token' you gave so you can match the token with an exact user who
wanted to authenticate.
Does it make sense?

Related

Why does Azure Active Directory OAuth work for me and no one else?

I am developing a Python/Flask application and I want to use OAuth for signing in. My employer uses Azure Active Directory so I am trying to integrate with it as an OAuth provider.
I am not an Azure tenant administrator.
I created an App Registration and set up my code following Microsoft's documentation, but I am the only person who can successfully sign in to the app.
I am constructing my authorization URL like this (I have the correct tenant name, client id, and redirect URI in my code):
import urllib.parse
import uuid
authorization_endpoint = 'https://login.microsoft.com/my-tenant.onmicrosoft.com/oauth2/authorize'
query = {
'client_id': 'my-client-id',
'nonce': uuid.uuid4(),
'redirect_uri': 'https://my-app.example.com/authorize',
'response_mode': 'form_post',
'response_type': 'id_token',
'scope': 'openid',
'state': uuid.uuid4()
}
authorization_url = f'{authorization_endpoint}?{urllib.parse.urlencode(query)}'
When I personally test signing in to the app, everything works fine. But when anyone else tries, they visit the authorization URL, sign in with their credentials, and then get a page with this error:
AADSTS165000: Invalid Request: The request tokens do not match the user context. Do not copy the user context values (cookies; form fields; headers) between different requests or user sessions; always maintain the ALL of the supplied values across a complete single user flow. Failure Reasons:[Token values do not match;]
Why does it work for me and for no one else?
The authorization endpoint is wrong. It should be https://login.microsoftonline.com/... instead of https://login.microsoft.com/....

python linkedin oauth2 - where is http_api.py?

I'm trying to get this example to work from https://github.com/ozgur/python-linkedin. I'm using his example. When I run this code. I don't get the RETURN_URL and authorization_code talked about in the example. I'm not sure why, I think it is because I'm not setting up the HTTP API example correctly. I can't find http_api.py, and when I visit http://localhost:8080, I get a "this site can't be reached".
from linkedin import linkedin
API_KEY = 'wFNJekVpDCJtRPFX812pQsJee-gt0zO4X5XmG6wcfSOSlLocxodAXNMbl0_hw3Vl'
API_SECRET = 'daJDa6_8UcnGMw1yuq9TjoO_PMKukXMo8vEMo7Qv5J-G3SPgrAV0FqFCd0TNjQyG'
RETURN_URL = 'http://localhost:8000'
authentication = linkedin.LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL, linkedin.PERMISSIONS.enums.values())
# Optionally one can send custom "state" value that will be returned from OAuth server
# It can be used to track your user state or something else (it's up to you)
# Be aware that this value is sent to OAuth server AS IS - make sure to encode or hash it
#authorization.state = 'your_encoded_message'
print authentication.authorization_url # open this url on your browser
application = linkedin.LinkedInApplication(authentication)
http_api.py is one of the examples provided in the package. This is an HTTP server that will handle the response from LinkedIn's OAuth end point, so you'll need to boot it up for the example to work.
As stated in the guide, you'll need to execute that example file to get the server working. Note you'll also need to supply the following environment variables: LINKEDIN_API_KEY and LINKEDIN_API_SECRET.
You can run the example file by downloading the repo and calling LINKEDIN_API_KEY=yourkey LINKEDIN_API_SECRET=yoursecret python examples/http_api.py. Note you'll need Python 3.4 for it to work.

Salesforce REST API logout

Is there a Salesforce endpoint to logout a session (not involving oauth?).
For example, I have a python script that logged in via the REST API using the username, password, security token method (I am using simple_salesforce for this).
simple_salesforce does not provide an inbuilt way to logout. Instead, according to the developer, logging out should be our responsibility:
https://github.com/heroku/simple-salesforce/issues/35
In the url above, it recommends we hit the salesforce revoke endpoint as described here:
https://help.salesforce.com/HTViewHelpDoc?id=remoteaccess_revoke_token.htm&language=en_US
However, as I mentioned before, I used the username, password, security token method to login, not the oauth.
Assuming, I cannot use the oauth way to login, what url/endpoint do I need to hit to logout the session?
Thanks!
Answering my own question. Perhaps this may be helpful to anyone else.
When using the username, password, security-token method instead of oauth to login, you still use the oauth revoke endpoint to logout. As shown in Salesforce documentation (https://help.salesforce.com/apex/HTViewHelpDoc?id=remoteaccess_revoke_token.htm&language=en), the revoke endpoint has the following url: https://login.salesforce.com/services/oauth2/revoke?token=currenttokenID
The token we will hit the endpoint with is actually our session_id. So, in simple_salesforce, once we have created the sf object as follows
sf = Salesforce(username='myemail#example.com', password='password', security_token='token')
we get the session id by sf.session_id.
Now to hit the endpoint we can use requests (which is already there in the sf object)
payload = { "token": sf.session_id }
url = 'https://test.salesforce.com/services/oauth2/revoke'
r = sf.request.get(url, params=payload)
if r.status_code == 200:
#successfully logged out, good to go!
else:
#uh-oh, something went wrong. check it out
Hope this helps!

Working with the Box.com SDK for Python

I am trying to get started with the Box.com SDK and I have a few questions.
from boxsdk import OAuth2
oauth = OAuth2(
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
store_tokens=your_store_tokens_callback_method,
)
auth_url, csrf_token = oauth.get_authorization_url('http://YOUR_REDIRECT_URL')
def store_tokens(access_token, refresh_token):
# store the tokens at secure storage (e.g. Keychain)
1)What is the redirect URL and how do I use it? Do I need to have a server running to use this?
2)What sort of code to I need in the store_tokens method?
The redirect URL is only required if you're runng a Web application that needs to respond to user's requests to authenticate. If you're programtically authenticating, you can simply set this as http://localhost. In a scenario where you require the user to manually authenticate, the redirect URL should invoke some function in your web app to store and process the authentication code returned. Do you need a server running? Well, if you want to do something with the authentication code returned, the URL you specify should be under your control and invoke code to do something useful.
Here's an example of what the store_tokens function should look like. It should accept two parameters, access_token and refresh_token. In the example below, the function will commit these to a local store for use when the API needs to re-authenticate:
From here:
"""An example of Box authentication with external store"""
import keyring
from boxsdk import OAuth2
from boxsdk import Client
CLIENT_ID = 'specify your Box client_id here'
CLIENT_SECRET = 'specify your Box client_secret here'
def read_tokens():
"""Reads authorisation tokens from keyring"""
# Use keyring to read the tokens
auth_token = keyring.get_password('Box_Auth', 'mybox#box.com')
refresh_token = keyring.get_password('Box_Refresh', 'mybox#box.com')
return auth_token, refresh_token
def store_tokens(access_token, refresh_token):
"""Callback function when Box SDK refreshes tokens"""
# Use keyring to store the tokens
keyring.set_password('Box_Auth', 'mybox#box.com', access_token)
keyring.set_password('Box_Refresh', 'mybox#box.com', refresh_token)
def main():
"""Authentication against Box Example"""
# Retrieve tokens from secure store
access_token, refresh_token = read_tokens()
# Set up authorisation using the tokens we've retrieved
oauth = OAuth2(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
access_token=access_token,
refresh_token=refresh_token,
store_tokens=store_tokens,
)
# Create the SDK client
client = Client(oauth)
# Get current user details and display
current_user = client.user(user_id='me').get()
print('Box User:', current_user.name)
if __name__ == '__main__':
main()
I suggest taking a look at the OAuth 2 tutorial. It will help give a better understanding of how OAuth works and what the various parameters are used for.
The redirect URL is set in your Box application's settings:
This is the URL where Box will send an auth code that can be used to obtain an access token. For example, if your redirect URL is set to https://myhost.com, then your server will receive a request with a URL that looks something like https://myhost.com?code=123456abcdef.
Note that your redirect URI doesn't need to be a real server. For example, apps that use a WebView will sometimes enter a fake redirect URL and then extract the auth code directly from the URL in the WebView.
The store_tokens callback is optional, but it can be used to save the access and refresh tokens in case your application needs to shutdown. It will be invoked every time the access token and refresh token changes, giving you an opportunity to save them somewhere (to disk, a DB, etc.).
You can then pass in these tokens to your OAuth2 constructor at a later time so that your users don't need to login again.
If you're just testing, you can also pass in a developer token. This tutorial explains how.
This is the most basic example that worked for me:
from boxsdk import Client, OAuth2
CLIENT_ID = ''
CLIENT_SECRET = ''
ACCESS_TOKEN = '' # this is the developer token
oauth2 = OAuth2(CLIENT_ID, CLIENT_SECRET, access_token=ACCESS_TOKEN)
client = Client(oauth2)
my = client.user(user_id='me').get()
print(my.name)
print(my.login)
print(my.avatar_url)

How do I access onedrive in an automated fashion without user interaction?

I am trying to access my own docs & spreadsheets via onedrive's api. I have:
import requests
client_id = 'my_id'
client_secret = 'my_secret'
scopes = 'wl.offline_access%20wl.signin%20wl.basic'
response_type = 'token' # also have tried "code"
redirect_uri = 'https://login.live.com/oauth20_desktop.srf'
base_url = 'https://apis.live.net/v5.0/'
r = requests.get('https://login.live.com/oauth20_authorize.srf?client_id=%s&scope=%s&response_type=%s&redirect_uri=%s' % (client_id, scopes, response_type, redirect_uri))
print r.text
(For my client I've also tried both "Mobile or desktop client app:" set to "Yes" and "No")
This will return the html for the user to manually click on. Since the user is me and it's my account how do I access the API without user interaction?
EDIT #1:
For those confused on what I'm looking for it would be the equivalent of Google's Service Account (OAuth2): https://console.developers.google.com/project
You cannot "bypass" the user interaction.
However you are very close to getting it to work. If you want to gain an access token in python you have to do it through the browser. You can use the web browser library to open the default web browser. It will look something like this (your app must be a desktop app):
import webbrowser
webbrowser.open("https://login.live.com/oauth20_authorize.srf?client_id=foo&scope=bar&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf")
This will bring you to the auth page, sign in and agree to the terms (it will differ depending on scope). It will direct you to a page where the url looks like:
https://login.live.com/oauth20_desktop.srf?code=<THISISTHECODEYOUWANT>&lc=foo
Copy this code from the browser and have your python script take it as input.
You can then make a request as described here using the code you received from the browser.
You will receive a response described here

Categories

Resources