How to access the hash fragment in the final url after request - python

Whenever I copy and paste the following into a web browser
Original URL
http://accounts.spotify.com/authorize?client_id=XXX2d0ff4186b517daa4e1c577e4&redirect_uri=http:%2F%2Flocalhost:5000&scope=playlist-modify-public%20playlist-modify-private&response_type=token
I get this for the final url
Final URL
http://localhost:5000/#access_token=XXX-LQY7xCQXTqpmsfroChl5yeUoiIDmoBfybqc9psLE2WFwP2UNQ26nVuiLGQkIWA-4occeXbrScaO5mqmMHZpgDPjTcSEfN9VZCLKKyfE46FUsucmCetP9owY_bRWoraZ8P2wwq0osZEMit0jmOrThvPTyKqp7O_rAbwT1BUsLeB9ux7xdLnTreocpmtZl3wqMXz24B2mwRMEieb_Dq2PUgIaK3zE7X-RvnzqQ&token_type=Bearer&expires_in=3600
My question is how to get the access_token in the final url by using the original URL programmatically. Preferably in python. The original URL will be constant so I won't need to make any changes to the values of the parameters that I already declared
I have already tried
Using python requests, and viewing the response.url.(both using POST and GET) But when I do it only shows the original url.
Same concept using urllib
Displaying it with .json, json(), .text, .headers, and pretty much all of the request functions available, but again it only makes references to the original url.

I assume that the grant flow that you are using is Implicit Grant which is used to obtain user's token. However, using this flow requires user's interaction via browser to complete the flow and get the token.
That means Implicit Grant can't be used to obtain user's access token via browserless application without user's interaction.
In case of browserless application, the authentication flow that you might want to use is Client Credential flow that you can get the access token directly in the response. The limitation of this grant flow is that you can't use the endpoint that requires user's identity.
In the FAQ section of the document might have an answer for your scenario that you might consider a refresh token instead.

I guess that the browser contains a valid session with the identity provider (authorize url -> callback url), but your programmatic way does not (authorize url -> authorize url).
Assuming it is implicit grant, and the aim is to retrieve the access token which is in the url hash fragment. The scripting would need to login to the identity provider or have the relevant session cookies/data.
Sample Python Code:
import requests
from urllib.parse import urlparse
singleSession = requests.Session()
# start with original url as https://oauth-abc.def.com/auth?client_id=123&redirect_uri=https://abc.def.com/oauth-callback&response_type=token&nonce=123&scope=something
# since there is no session with identity provider, the following get request should lead to redirect to identity provider / third party login form page.
url_login_authorize = 'https://oauth-abc.def.com/auth?client_id=123&redirect_uri=https://abc.def.com/oauth-callback&response_type=token&nonce=123&scope=something'
result_login_oauth_page = singleSession.get(url_login_authorize, allow_redirects=True)
# result_login_oauth_page.url is the identity provider login form html page url which could be unique
# post credentials to authenticate with identity provider
url_login_oauth_endpoint = result_login_oauth_page.url + '/login'
result_login_oauth = singleSession.post(url_login_oauth_endpoint, credentials_object, allow_redirects=True)
# post request to grant/confirm the requested scopes with authenticated session
url_login_confirm_oauth_endpoint = result_login_oauth_page.url + '/confirm'
result_login_confirm_oauth = singleSession.post(url_login_confirm_oauth_endpoint, {}, allow_redirects=True)
# end with the final url as https://abc.def.com/oauth-callback#access_token=ilovemoney&expires_in=3600&token_type=Bearer&scope=something
result_oauth_callback_parse = urlparse(result_login_confirm_oauth.url)
result_oauth_callback_params = dict()
for callback_param in result_oauth_callback_parse.fragment.split("&"):
callback_param_split = callback_param.split("=")
result_oauth_callback_params[callback_param_split[0]] = callback_param_split[1]
print("result_oauth_callback_params['access_token']: ", result_oauth_callback_params['access_token'])

Related

Python Requests / HTTPX - Authenticate All Redirected URL - How To

I wonder if there is a way to authenticate each redirected URL when working with Python modules such as httpx or requests?
Problem Statement
I am trying to connect to an API endpoint under the company network. Due to the company's cyber security measures, the API endpoint will be randomly masked with a company proxy, which causes the 307 Redirect status code.
my current code snippet looks like the below:
import httpx
api_url = 'https://demo.vizionapi.com/carriers'
head = {
'X-API-Key':'API KEY'
}
response = httpx.get(url=api_url, verify='supporting_files/cacert.pem',
headers=head, auth=('my username', 'my password'),
follow_redirects=True)
With above code, I received the 401 authentication needed error (But auth has been passed). This error will only happen when redirection occurs due to the company proxy.
Question:
My assumption is the authentication is only being passed into the first URL not the redirected URL. Therefore, I wonder if anyone know how I can use the same auth parameter for all URLs (direct & redirect)?
Any suggestion will be deeply appracaited.
I don't know what requests behavior with regards to auth during redirect is, but the first solution to come to mind is to manually follow the redirects yourself. Put your request in a loop that checks for the 3xx response codes, and handle auth however you want to.

How would I log in with a .ROBLOSECURITY using roblox api?

I am creating a bot that gets all the free items available on the item catalog, I want the person using the bot to just put their roblox cookie into a .txt file, how would I log in with the cookie in python?
If you're using requests, then you're most likely using requests.Session(). You can simply use session.cookies
Code example:
import requests as r
cookie = "" # cookie goes here (accessed via text file)
requestSession = r.Session() # initiate a session
requestSession.cookies[".ROBLOSECURITY"] = cookie
Then you can make a request using the Session and it will include the ROBLOSECURITY in the headers.

Python requests - download image and write to file not working due to nature of URI and authentification procedure

I am writing a script that downloads Sentinel 2 products (satellite imagery) using sentinelsat Python API.
A product's description is structured as JSON and contains the parameter quicklook_url.
Example:
https://apihub.copernicus.eu/apihub/odata/v1/Products('862619d6-9b82-4fe0-b2bf-4e1c78296990')/Products('Quicklook')/$value
Any Sentinel API calls require credentials. So does retrieving a product and also opening the link stored inside quicklook_url. When I call the example in my browser I get asked to enter username and password in order to get
with the name S2A_MSIL2A_20210625T065621_N0300_R063_T39NTJ_20210625T093748-ql.jpg.
Needless to say I am just starting with the API so I am probably missing something but
requests.post(product_description['quicklook_url'], verify=False, auth=HTTPBasicAuth(username, password)).content
yields 0KB damaged file and
requests.get(product_description['quicklook_url']).content
yields 1KB damaged file.
I have looked into requests.Session
session = requests.Session()
session.auth = (username, password)
auth = session.post('URL_FOR_LOGING_IN')
img = session.get(product_description['quicklook_url']).content
The problem is I am unable to find the URL I need to post my session authentification. I am somewhat sure that the sentinelsat API does that but my looks have not yielded any successful result.
I am currently looking into the SentinelAPI class. It has the download_quicklook() function, which I am using right now but I am still curious how to do this without the function.
I guess you don't need to sent a post request. Basic authentication works by sending a header along with each request. The following should work
session = requests.Session()
session.auth = (username, password)
img = session.get(product_description['quicklook_url']).content
Your first attempt is failed because of using POST I think.
requests.gett(product_description['quicklook_url'], verify=False, auth=HTTPBasicAuth(username, password)).content
should also work.

Streamlabs API 405 response code

I'm trying to use Streamlabs API. Streamlabs API uses Oauth2 for creating apps. So first I send whoever's using my app to an authorization link containing my app's client id and the scopes I want to use.
(Something like this: streamlabs.com/api/v1.0/authorize?client_id=CLIENT-ID-HERE&redirect_uri=REDIRECT-URI&response_type=code&scope=SOME+SCOPES+HERE)
Once I've done that I receive a code at the redirect uri specified. I then use that code to get the access token for permanent access to the connected user's account. I then receive the access token from a POST request that works perfectly... Now I run into the problem. When getting the temporary code before the access token I specified the scopes: "donations.read +donations.create+alerts.write+alerts.create".
When authorizing, the app asks for permission to the different scopes. The scope in focus is "alerts.write" so that I can send test alerts using POST requests. But this doesn't work for some reason. To send a test alert I have to send a POST request to this url: "https://streamlabs.com/api/alerts/send_test_alert"
I've tried doing that in two different ways.
1:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert"
data = {
"access_token":"UserAccessTokenHere",
"type":"donation"
}
response = requests.post(url=url, data=data)
print(response.text)
2:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert?access_token=UserAccessTokenHere&type=donation"
response = requests.post(url=url)
print(response.text)
If I do print(response) it prints "Response [405]".
But if I do print(response.text) I get a long HTML document for this page: Error response page
Any ideas what's going wrong with my Python requests? send_test_alert documentation here: Link
I've contacted support and looks like you've made the same error as me.
You're not actually sending a request to the right URL.
You are a sending a request to: "https://streamlabs.com/api/alerts/send_test_alert"
You should be using the URL: "https://streamlabs.com/api/v1.0/alerts/send_test_alert"

How to use oauth2 to access StackExchange API?

I'm following the instructions mentioned here: https://api.stackexchange.com/docs/authentication
But since there is no code provided, I'm not able to understand the flow correctly.
I've been trying to get the authentication part done using two methods below but I have hit a deadend.
1)
import requests
from pprint import pprint
resp = requests.get('https://stackexchange.com/oauth/dialog?client_id=6667&scope=private_info&redirect_uri=https://stackexchange.com/oauth/login_success/')
pprint(vars(resp))
2)
import oauth2 as oauth
from pprint import pprint
url = 'https://www.stackexchange.com'
request_token_url = '%s/oauth/' % url
access_token_url = '%s/' % url
consumer = oauth.Consumer(key='mykey',
secret='mysecret')
client = oauth.Client(consumer)
response, content = client.request(request_token_url, 'GET')
print(response, content)
I'm not sure how to go forward from here? I need to use the access token that is returned and use it to query the API. A sample code would really really help! Thanks.
EDIT: This is the code I'm using currently:
from requests_oauthlib import OAuth2Session
from pprint import pprint
client_id = 'x'
client_secret = 'x'
redirect_uri = 'https://stackexchange.com/oauth/login_success'
scope = 'no_expiry'
oauth = OAuth2Session(client_id, redirect_uri=redirect_uri, scope=scope)
pprint(vars(oauth))
authorization_url, state = oauth.authorization_url('https://stackexchange.com/oauth/dialog')
print(authorization_url)
Instead of having to click on the authorization_url and get the token, is there a way I can directly fetch the token within the script itself?
Of the two methods you used, the first is the recommended method for desktop applications. It is probably correct.
OAuth is intended to force the user to go to a specific webpage and acknowledge that they are giving permission (usually through clicking a button) for an application to access their data. The HTTP responses you print are merely the webpage where a user needs to click accept.
To get a feeling for the flow, put the first address (https://stackexchange.com/oauth/dialog?client_id=6667&scope=&redirect_uri=https://stackexchange.com/oauth/login_success/) in the address bar and click accept on the loaded page. The access_token will be in the URL right after that.
If you are making the application only for yourself, the access_token can be copied into your Python script. The token expires in one day; if that is too short add no_expiry to scope to make it last forever. DO NOT share the token with anyone else, since it gives them access to details of your account! Each user of the script must generate their own token.
Test the access_token by inserting in your app's key and the access_token you just obtained into the url: https://api.stackexchange.com/2.2/me?key=key&site=stackoverflow&order=desc&sort=reputation&access_token=&filter=default
If you need a more automated, integrated, user-friendly solution, I would look at selenium webdriver to open a browser window and get the resulting credentials.
Just one minor correction on Marc's answer. If you want the access token to last forever, you should add no_expiry instead of no_expire.

Categories