Bigquery - google auth does not direct to url - python

I'm trying to run a query on bigquery in a Django project and get results. While working successfully in localhost, it does not redirect to the verification link at all when I take it to the live server.
I think I need to change the redirect_uri value as I read it. I added this in Da appflow variable but the url doesn't change. I am using the same query below with the example query in google's document, I am submitting my own query because it contains private information, but it is exactly the same query.
I have added to Authorized redirect URIs, and I put the api in production mode.;
The resulting redirect url is output as localhost in this way;
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=123-nml31ekr2n0didomei5.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fbigquery&state=XF1WdtCoR4HaICwzSKk9A1giBrSzBv&access_type=offline
def query_stackoverflow():
launch_browser = True
project = 'xx-prod'
appflow = flow.InstalledAppFlow.from_client_secrets_file("static/client_secret_518684-nmpoqtgo5flvcgnl31ekr2ni5.apps.googleusercontent.com.json", scopes=["https://www.googleapis.com/auth/bigquery"], redirect_uri=["https://xx.com/"])
if launch_browser:
appflow.run_local_server()
else:
appflow.run_console()
credentials = appflow.credentials
client = bigquery.Client(project=project, credentials=credentials)
client = bigquery.Client()
query_job = client.query(
"""
SELECT
CONCAT(
'https://stackoverflow.com/questions/',
CAST(id as STRING)) as url,
view_count
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE tags like '%google-bigquery%'
ORDER BY view_count DESC
LIMIT 10"""
)
results = query_job.result() # Waits for job to complete.
for row in results:
print("{} : {} views".format(row.url, row.view_count))
On live server google return auth url like this;
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=51864584-nmpoqtgo5flvcgnln0didomei5.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fbigquery&state=W2uMZwzaYMEpFzExodRCf2wA4&access_type=offline
The first problem is that it does not automatically redirect to the link as in localhost, the second problem is that when I open this link manually, the link cannot be reached after mail verification.

From what i can see your code is using installed app flow. This means that the consent screen is going to open up on the machine its running on. If you have this running on a server, are you logging into the server and running it or are you in fact creating a web application?
flow.InstalledAppFlow
web app
If you are making a web application then you should be following this sample.
API access on behalf of your clients (web flow)
You will need to convert it to work with big query.
import google.oauth2.credentials
import google_auth_oauthlib.flow
# Initialize the flow using the client ID and secret downloaded earlier.
# Note: You can use the GetAPIScope helper function to retrieve the
# appropriate scope for AdWords or Ad Manager.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
'client_secret.json',
scope=[oauth2.GetAPIScope('adwords')])
# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required.
flow.redirect_uri = 'https://www.example.com/oauth2callback'
The code for a web application is slightly different then that of an installed application.

Related

Spotipy can't authenticate on Azure Functions (OAuth)

I made a script that works perfectly when it runs locally but isn't able to authenticate in my Azure Functions app. At first, I thought it was because it couldn't read the .cache file.
After looking at the logs it's because it can't open a browser window to create the authentication token. I'm fairly new to Azure functions so I'm not sure how I can enable opening a browser if that's even possible.
I looked into the oauth2.py file in spotipy and found it's optional to open the browser but instead, the console asks for the redirected URL. Is there a way for me to get the redirected URL and enter it into the console instead?
Here's my code:
def create_playlist(cred):
"""Creates the playlist for Discover weekly to be copied to"""
# Gain authorization to create playlist
logging.info('Authenticating spotify secrets to create new playlist...')
# spotipy.CacheFileHandler(cache_path='')
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=cred[0],
client_secret=cred[1],
redirect_uri=cred[2],
scope='playlist-modify-private',
open_browser=False,
))
# Get returned list from get_playlist_info function
logging.info('Determining playlist descriptors...')
info = get_playlist_info()
# New playlist for Discover Weekly
logging.info('Creating new playlist...')
new_playlist = sp.user_playlist_create(user=cred[4],
name=info[0],
public=False,
collaborative=False,
description=info[1])
logging.info('Returning new playlist.')
return new_playlist
In Redirect URIs you enters one or more addresses which you want to whitelist with Spotify. And this URI enables the Spotify authentication service to automatically re-launch your app every time the user logs in.
You can set your Redirect URL by navigating to your Spotify developer dashboard and open the project you are working on. Then click "edit settings" and look for the redirect URIs field and put your redirect URI in the field and lastly save it.
The Authorization Code Flow needs you to add a redirect URI to your application at My Dashboard. The redirect_uri argument or SPOTIPY_REDIRECT_URI environment variable must match the redirect URI added to your application in your Dashboard.
Following are some examples that you can use as redirect URIs.
http://example.com, http://localhost or http://127.0.0.1:9090
The correct way in which you should authenticate yourself is shown in the code snippet below.
token = util.prompt_for_user_token(
username=USERNAME,
scope=SCOPE,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
redirect_uri=REDIRECT_URI)
You should also export your redirect_uri, client ID, and secret before running your script and trying to authenticate. If you don't pass the values directly to the util.prompt_for_user_token function, it will read them from the environment.
Try running these in your terminal before running your script.
export SPOTIPY_CLIENT_ID="YOUR CLIENT ID"
export SPOTIPY_CLIENT_SECRET="YOUR CLIENT SECRET"
export SPOTIPY_REDIRECT_URI='http://localhost/'
For more information you can read this Authorization Code Flow document for Spotipy.

Authenticate to Azure Functions App using Azure Active Directory in Python daemon application with MSAL

I built a REST API by creating an Azure Functions App and a Python console application should be able to authenticate and make requests to the API.
Here are the steps I have taken so far:
I created the REST API as an Azure Functions App (in C#) where I used AuthorizationLevel.Anonymous.
In the Azure Active Directory I created an app registration (Azure Active Directory > App registrations) where I added a client secret under Certificates & secrets > Client secrets.
In the Azure Functions App I added the registration from step 2 under Authentication > Identity provider where I provided the registration's client ID as well as the value of the registration's client secret.
Here is the code of the Python console application (as described here: https://github.com/AzureAD/microsoft-authentication-library-for-python):
import requests
import msal
import json
with open('configuration.json') as json_file:
configuration = json.load(json_file)
app = msal.ConfidentialClientApplication(
configuration["client_id"],
authority=configuration["authority"],
client_credential=configuration["secret"]
)
result = None
result = app.acquire_token_silent(configuration["scope"],account=None)
if not result:
result = app.acquire_token_for_client(scopes=configuration["scope"])
if "access_token" in result:
url = ... # the URL of a specific function of the Azure Functions App
parameters = {...}
response = requests.get(url=url, params=parameters, headers={'Authorization': 'Bearer ' + result['access_token']})
print("Status code: {}".format(response.status_code))
print("Message: {}".format(response.text))
registration["scope"] equals ["https://graph.microsoft.com/.default"] and registration["secret"] equals the value of the client secret created in step 2.
The code returns:
Status code: 401
Message: You do not have permission to view this directory or page.
What am I missing? I know there are similar issues on Stackoverflow but they did not solve my problem.
If you use the newest authentication, please check the issue url:
Check your Issuer URL:
Or to change the accessTokenAcceptedVersion to 2:
Any way, make sure the issue url version is the same.
(I found there are still many problems with Authentication, and many things will not be automatically configured.)

Failed to use auth code flow with python MSAL

I simply can't get acquire_token_by_auth_code_flow() from the MSAL package to work outside a flask app using the basic example giving in the MSAL documentation.
I think the problem comes from using the wrong authentication response which must be a "dict of the query string received from auth server" according to the documentation. In a flask app, I can simply use request.args which I'm not quite sure how to use outside of flask.
I've already tried using requests.request as well as urlsplit. The device flow is working fine as well as using the MSAL package in Java and connecting via R. So the app seems to be set up correctly.
The basic example code from the MSAL app below produces the error:
state mismatch: XXXXXXXXXXXX vs None
(so auth_response is wrong).
Any thoughts?
import requests
import msal
CLIENT_ID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" # Application (client) ID of app registration
CLIENT_SECRET = "XX-XXXXXXXX-XXXXXXXX.XX~XXXXX~XXXX" # Placeholder - for use ONLY during testing.
AUTHORITY = "https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX"
REDIRECT_PATH = "/getAToken" # Used for forming an absolute URL to your redirect URI.
# The absolute URL must match the redirect URI you set
# in the app's registration in the Azure portal.
ENDPOINT = 'https://graph.microsoft.com/v1.0/me'
SCOPE = ["https://graph.microsoft.com/.default"]
# Cache
cache = msal.SerializableTokenCache()
# Build msal app
app = msal.ConfidentialClientApplication(
CLIENT_ID, authority=AUTHORITY,
client_credential=CLIENT_SECRET, token_cache=cache)
# Initiate auth code flow
session = requests.Session()
session.flow = app.initiate_auth_code_flow(scopes=SCOPE, redirect_uri=REDIRECT_PATH)
# Aquire token
result = app.acquire_token_by_auth_code_flow(auth_code_flow=session.flow, auth_response = dict(parse.parse_qsl(parse.urlsplit(REDIRECT_PATH).query)))
The equivalent code for the last bit from the flask app looks like this with REDIRECT_PATH = "/getAToken":
#app.route(app_config.REDIRECT_PATH) # Its absolute URL must match your app's redirect_uri set in AAD
def authorized():
result = _build_msal_app(cache=cache).acquire_token_by_auth_code_flow(
session.get("flow", {}), request.args)
return redirect(url_for("index"))
Getting a token requires few requests according to documentation. To make it possible you need to create flow and store it inside session before navigating to microsoft login page.
session["flow"] = _build_auth_code_flow(authority=app_config.AUTHORITY, scopes=app_config.SCOPE)
After navigation back to your application you should use this flow object as you did in your example
result = _build_msal_app(cache=cache).acquire_token_by_auth_code_flow(
session.get("flow", {}), request.args)
Make sure that you didn't create it twice. In this case error will be similar, but state mismatch: XXXXXXXXXXXX vs XXXXXXXXXXXX. It may happened if you route called twice.
auth_response must be a dictionary built from the current HTTP request query params.
If this is a desktop application you must switch to PublicClientApplication. You can find a sample here.

How to call the LinkedIn API using Python?

I tried so many methods, but none seem to work. Help me make a connection with LinkedIn using python. Issue in generating Access Token I received CODE but it doesn't work. I have python 3.9 Please post a sample of basic code that establishes a connection and gets a access Token. And which redirectUri I have to use. Can i use any website link for rediectUri.
I tried to check API through curl and Postman but didn't get solution its say Unauthorized Accesss.
https://github.com/ozgur/python-linkedin <---This is where I got some idea how to use API .To recievd Access token .
First solution valid for any (including free) applications, it useses so-called 3-Legged OAuth 2.0 Authentication:
Login to your account in the browser.
Create new application by this link.
If you already have application you may use it by selecting it here and changing its options if needed.
In application credentials copy Client ID and Client Secret, you'll need them later.
On your application's server side create Authorization request URL by next code and send/redirect it to client. If your Python code runs locally you may just open this URL in your browser with import webbrowser; webbrowser.open(url) code. Fill in all fields with your values too. There is redirect_uri in the code, this is URL where authorization response is sent back, for locally running script you have to run Python HTTP web server to retrieve result.
# Needs: python -m pip install requests
import requests, secrets
url = requests.Request(
'GET',
'https://www.linkedin.com/oauth/v2/authorization',
params = {
'response_type': 'code', # Always should equal to fixed string "code"
# ClientID of your created application
'client_id': 'REPLACE_WITH_YOUR_CLIENT_ID',
# The URI your users are sent back to after authorization.
# This value must match one of the OAuth 2.0 Authorized Redirect
# URLs defined in your application configuration.
# This is basically URL of your server that processes authorized requests like:
# https://your.server.com/linkedin_authorized_callback
'redirect_uri': 'REPLACE_WITH_REDIRECT_URL', # Replace this with your value
# state, any unique non-secret randomly generated string like DCEeFWf45A53sdfKef424
# that identifies current authorization request on server side.
# One way of generating such state is by using standard "secrets" module like below.
# Store generated state string on your server for further identifying this authorization session.
'state': secrets.token_hex(8).upper(),
# Requested permissions, below is just example, change them to what you need.
# List of possible permissions is here:
# https://learn.microsoft.com/en-us/linkedin/shared/references/migrations/default-scopes-migration#scope-to-consent-message-mapping
'scope': ' '.join(['r_liteprofile', 'r_emailaddress', 'w_member_social']),
},
).prepare().url
# You may now send this url from server to user
# Or if code runs locally just open browser like below
import webbrowser
webbrowser.open(url)
After user authorized your app by previous URL his browser will be redirected to redirect_uri and two fields code and state will be attached to this URL, code is unique authorization code that you should store on server, code expires after 30 minutes if not used, state is a copy of state from previous code above, this state is like unique id of your current authorization session, use same state string only once and generate it randomly each time, also state is not a secret thing because you send it to user inside authorization URL, but should be unique and quite long. Example of full redirected URL is https://your.server.com/linkedin_authorized_callback?code=987ab12uiu98onvokm56&state=D5B1C1348F110D7C.
Next you have to exchange code obtained previously to access_token by next code, next code should be run on your server or where your application is running, because it uses client_secret of your application and this is a secret value, you shouldn't show it to public, never share ClientSecret with anyone except maybe some trusted people, because such people will have ability to pretend (fake) to be your application while they are not.
# Needs: python -m pip install requests
import requests
access_token = requests.post(
'https://www.linkedin.com/oauth/v2/accessToken',
params = {
'grant_type': 'authorization_code',
# This is code obtained on previous step by Python script.
'code': 'REPLACE_WITH_CODE',
# This should be same as 'redirect_uri' field value of previous Python script.
'redirect_uri': 'REPLACE_WITH_REDIRECT_URL',
# Client ID of your created application
'client_id': 'REPLACE_WITH_YOUR_CLIENT_ID',
# Client Secret of your created application
'client_secret': 'REPLACE_WITH_YOUR_CLIENT_SECRET',
},
).json()['access_token']
print(access_token)
access_token obtained by previous script is valid for 60 days! So quite long period. If you're planning to use your application for yourself only or your friends then you can just pre-generate manually once in two months by hands several tokens for several people without need for servers.
Next use access_token for any API calls on behalf of just authorized above user of LinkedIn. Include Authorization: Bearer ACCESS_TOKEN HTTP header in all calls. Example of one such API code below:
import requests
print(requests.get(
'https://api.linkedin.com/v2/jobs',
params = {
# Any API params go here
},
headers = {
'Authorization': 'Bearer ' + access_token,
# Any other needed HTTP headers go here
},
).json())
More details can be read here. Regarding how your application is organized, there are 3 options:
Your application is running fully on remote server, meaning both authentication and running application (API calls) are done on some dedicated remote server. Then there is no problem with security, server doesn't share any secrets like client_secret, code, access_token.
Your application is running locally on user's machine while authentication is runned once in a while by your server, also some other things like storing necessary data in DataBase can be done by server. Then your server doesn't need to share client_secret, code, but shares access_token which is sent back to application to user's machine. It is also OK, then your server can keep track of what users are using your application, also will be able to revoke some or all of access_tokens if needed to block user.
Your application is fully run on local user's machine, no dedicated server is used at all. In this case all of client_secret, code, access_token are stored on user's machine. In this case you can't revoke access to your application of some specific users, you can only revoke all of them by regenerating client_secret in your app settings. Also you can't track any work of your app users (although maybe there is some usage statistics in your app settings/info pages). In this case any user can look into your app code and copy client_secret, unless you compile Python to some .exe/.dll/.so and encrypt you client secret there. If anyone got client_secret he can pretend (fake) to be your application meaning that if you app contacts other users somehow then he can try to authorize other people by showing your app interface while having some other fraudulent code underneath, basically your app is not that secure or trusted anymore. Also local code can be easily modified so you shouldn't trust your application to do exactly your code. Also in order to authorize users like was done in previous steps 5)-7) in case of local app you have to start Python HTTP Server to be able to retrieve redirected results of step 5).
Below is a second solution valid only if your application is a part of LinkedIn Developer Enterprise Products paid subscription, also then you need to Enable Client Credentials Flow in your application settings, next steps uses so-called 2-Legged OAuth 2.0 Authentication:
Login to your account in the browser.
Create new application by this link.
If you already have application you may use it by selecting it here and changing its options if needed.
In application credentials copy ClientID and ClientSecret, you'll need them later.
Create AccessToken by next Python code (put correct client id and client secret), you should run next code only on your server side or on computers of only trusted people, because code uses ClientSecret of your application which is a secret thing and shouldn't be showed to public:
# Needs: python -m pip install requests
import requests
access_token = requests.post(
'https://www.linkedin.com/oauth/v2/accessToken',
params = {
'grant_type': 'client_credentials',
'client_id': 'REPLACE_WITH_YOUR_CLIENT_ID',
'client_secret': 'REPLACE_WITH_YOUR_CLIENT_SECRET',
},
).json()['access_token']
print(access_token)
Copy access_token from previous response, it expires after 30 minutes after issue so you need to use previous script often to gain new access token.
Now you can do any API requests that you need using this token, like in code below (access_token is taken from previous steps):
import requests
print(requests.get(
'https://api.linkedin.com/v2/jobs',
params = {
# Any API params go here
},
headers = {
'Authorization': 'Bearer ' + access_token,
# Any other needed HTTP headers go here
},
).json())
More details can be read here or here.

python3 upload files to ondrive or sharepoint?

Anyone know if this is possible?
I just want to automate dropping some documents into my onedrive for business account.
I tried
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
from onedrivesdk.helpers.resource_discovery import ResourceDiscoveryRequest
redirect_uri = 'http://localhost:8080'
client_id = 'appid'
client_secret = 'mysecret'
discovery_uri = 'https://api.office.com/discovery/'
auth_server_url='https://login.live.com/oauth20_authorize.srf?scope=wl.skydrive_update'
#auth_server_url='https://login.microsoftonline.com/common/oauth2/authorize',
auth_token_url='https://login.microsoftonline.com/common/oauth2/token'
http = onedrivesdk.HttpProvider()
auth = onedrivesdk.AuthProvider(http,
client_id,
auth_server_url=auth_server_url,
auth_token_url=auth_token_url)
auth_url = auth.get_auth_url(redirect_uri)
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
auth.authenticate(code, redirect_uri, client_secret, resource=resource)
# If you have access to more than one service, you'll need to decide
# which ServiceInfo to use instead of just using the first one, as below.
service_info = ResourceDiscoveryRequest().get_service_info(auth.access_token)[0]
auth.redeem_refresh_token(service_info.service_resource_id)
client = onedrivesdk.OneDriveClient(service_info.service_resource_id + '/_api/v2.0/', auth, http)
I registered an APP and got a secret and id. But when I ran this I got scope is invalid errors. Plus it tries to launch a webpage which isn't great for a command line kinda environment. I think this SDK might be outdated as well because originally this script had login.microsoftonline, but that wasn't reachable so I changed it to login.live.com.
I wrote this sample code you posted. You replaced the auth_server_URLwith the authentication URL for Microsoft Account authentication, which can only be used to access OneDrive (the consumer product). You need to continue using the login.microsoftonline.com URL to log into your OneDrive for Business account.
You are correct that this pops up a dialog. However, you can write a little supporting code so that only happens the first time you log into a particular app. Follow these steps (assuming you are using the default implementation of AuthProvider:
Use the sample code above up through the line auth.redeem_refresh_token()
The AuthProvider will now have a Session object, which caches the credentials of the current user and session. Use AuthProvider.save_session() to save the credentials for later.
Next time you start your app, use AuthProvider.load_session() and AuthProvider.refresh_token() to retrieve the previous session and refresh the auth token. This will all be headless.
Take note that the default implementation of SessionBase (found here) uses Pickle and is not safe for product use. Make sure to create a new implementation of Session if you intend to deploy this app to other users.
Onerive's website shows "Not Yet" on "OneDrive SDK for Python" to "OneDrive for Business"
https://dev.onedrive.com/SDKs.htm
The github sample codes did not work for me either, it tried to popup a window of authentication, but IE can not find the address:
http://('https//login.microsoftonline.com/common/oauth2/authorize',)?redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=034xxxx9-9xx8-4xxf-bexx-1bc5xxxxbd0c&response_type=code
or removed all the "-" in client id
http://('https//login.microsoftonline.com/common/oauth2/authorize',)?redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=034xxxx99xx84xxfbexx1bc5xxxxbd0c&response_type=code
Either way, I got the same result, IE did not show the popup with a line "This page can’t be displayed"

Categories