I am trying to authorize with an ALB from python. As I understand the ALB looks for "AWSELBAuthSessionCookie" cookies before letting you to the website. I also see these cookies when logging into the application myself (using username and password). Question is how do I obtain the values of these cookies if I want to authenticate myself to the website/api from a python program. Has anybody done this before?
I had the exact same problem and could only make it work using an API Gateway since they allow authorization via JWT in the authorization header of the request. This can easily be done in Python, e.g.
import boto3
import requests
client = boto3.client(
"cognito-idp",
region_name="<aws region of the cognito app client>"
)
response = client.initiate_auth(
ClientId="<cognito app client ID>",
AuthFlow="USER_PASSWORD_AUTH",
AuthParameters={
"USERNAME": "<username>",
"PASSWORD": "<password>",
"SECRET_HASH": "<secret hash>",
},
)
token = response["AuthenticationResult"]["AccessToken"]
headers = {"Authorization": f"Bearer {token}"}
requests.get("<api gateway url>", headers=headers)
However, I also needed to allow authorization via the Cognito UI. Thus, I had to use both the ALB and API Gateway.
While this solved the issue of making my application available both from the browser (i.e. for humans) as well as from code (i.e. for machines), it introduced a lot of additional AWS components I had to use. And, as a disadvantegous side effect, the API has a request payload limit of 10MB that cannot be increased. This is another issue for me.
I know it's been a year, but if you've solved the issue, feel free to share your solution.
Related
I would like to make a HTTP call to this resource :
https://bigquery.googleapis.com/bigquery/v2/projects/{projectId}/jobs
As I read to the documentation I use an API key generated from my GCP project to be authenticated. So with requests I make a simple call like this:
import requests
params = {'key': 'MY_API_KEY'}
base_url = 'https://bigquery.googleapis.com'
project_id = 'MY_PROJECT_ID'
r = requests.get(f'{base_url}/bigquery/v2/projects/{project_id}/jobs', params=params)
Unfortunately it returns a response 401 and I can't figure out why.
Thanks a lot and have a nice day !
Update code after guillaume blaquiere reply :
from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import service_account
base_url = 'https://bigquery.googleapis.com'
project_id = 'project_id'
credentials = service_account.Credentials.from_service_account_file(
'service_account.json',
scopes=['https://www.googleapis.com/auth/bigquery',
'https://www.googleapis.com/auth/cloud-platform'],
)
authed_session = AuthorizedSession(credentials)
response = authed_session.request('GET', f'{base_url}/bigquery/v2/projects/{project_id}/jobs')
print(response.json())
# this returns : {'etag': 'tAZvk1k2f2GY8yHaQF7how==', 'kind': 'bigquery#jobList'}
The API Key no longer works for a large number of Google API. Only some legacy continue to accept an API key.
Now, you need an authenticated request. You can find exemple in the google-auth python library documentation. Look at Refresh and Authorized_session.
Don't hesitate to comment if you need help about the credential obtention, I can also help you on this.
EDIT
When you perform the request, it's, by default, only on the current user. In your case, it's the service account when you use the Python code, and your User account when you use the API Explorer (the swagger like in the Google Documentation).
In your case, I guess that your service account has never performed a job (query or load job) and thus, there is no entry for it.
According with the documentation, is you want to see all the user jobs, you have to add the param ?allUsers=true at the end of your URL
response = authed_session.request('GET', f'{base_url}/bigquery/v2/projects/{project_id}/jobs?allUsers=true')
that is my first try with an API, said API being called OPS.
I would like to get information using the API (OAuth 2) within my python code.
The ressource URL is :
http://ops.epo.org/3.2/rest-services/register/{publication}/{EPODOC}/{EP2814089}/biblio
I also received :
Consumer Key: O220VlTQqAmodifiedsf0YeqgM6c
Consumer Secret Key: swWmodified3edjORU
The documentation states that:
OPS uses the OAuth framework for Authentication and Authorization. At this point in
time, only the “Client Credentials” flow is supported using a Consumer key and
Consumer secret.
The actual steps to follow are:
Step 1: Client converts Consumer key and Consumer secret to
Base64Encode(Consumer key:Consumer secret).
This should be done programmatically using the language you are developing the client
application in. For the purposes of this example, a public website was used to perform
this conversion.
By entering the colon separated Client credentials, an encoded response is generated.
This response is then be used for basic Authentication.
Step 2: Client requests an access token using Basic Authentication, supplying its
Consumer key and Consumer secret with base64Encoding over encrypted HTTPS
connection:
OPS authenticates the client credentials passed in the Authorization header using basic
authentication method.
If credentials are valid, OPS responds with a valid access token.
Step 3: Client accesses OPS resources with access token in authorization header
(bearer tokens) over encrypted HTTPS connection
I tried a few samples of code with requests but, until now, nothing worked.
The client credentials flow is described in the OAuth2 RFC-6749. The client id and secret are base64 encoded in a Basic authentication scheme as described in RFC-7617
You should be able to get a token using Python code like:
import requests
import base64
url = 'https://ops.epo.org/3.2/auth/accesstoken'
data = {"grant_type": "client_credentials"}
creds = base64.b64encode("O220VlTQqAmodifiedsf0YeqgM6c:swWmodified3edjORU".encode())
headers = {'Authorization': 'Basic ' + creds.decode('UTF-8'), 'Content-Type': 'application/x-www-form-urlencoded'}
response = requests.post(url, headers=headers, data=data)
access_token = response.json()["access_token"]
When using the previous response I can obtain a token. (Thanks a lot for your answer)
So I tried :
myUrl = 'http://ops.epo.org/3.2/rest-services/register/publication/EPODOC/EP2814089/biblio'
header = {'PRIVATE-TOKEN': myToken}
response = requests.get(myUrl, headers=header)
print(response.text)
but I obtained a 403 error.
I finally got a specific library to do the job :
EPO OPS Library
But I still don't know how to do it on my own...
I have a Python application that calls the Spotify API and then analyses the result (serach about song information and save them in a file). The only problem I got is that there is no way to acquire an authorization token with this poorly implemented API.
Neither the package "spotify" nor spotipy or any other third party library provides me this feature. And obviously if I have a server, I do not run any GUI or so, so I can not see any prompt.
Unfortunately I am not a script kiddie who plays with Node.js on his/her home Windows...
Are there any way to get a fresh token each time without using the fanciest GUI prompt?
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer TEMPORARY_TOKEN_FROM_SPOTIFY"
}
response = requests.get("https://api.spotify.com/v1/me/player/currently-playing", headers=headers)
This is the current code that works the temporary access token from spotify webpage, but it expires really short.
The other problem with the fancypants GUI: If you login with your account, each API request will result in your own user account specific thing, for example, the "now playing" feature.
You could use the Authorisation Code Flow as mentioned and use the Refresh token part of that to renew your tokens that way you only need to log in once, however you could also use the Client Credentials Flow but this does expose your Client Id and Client Secret which is only recommended for server-side applications but doesn't ask for a login but also doesn't access any user specific functionality. You can find out more about the flows available from the Authorisation Guide
How can I authenticate to Azure DevOps REST API in a python script?
I found that there are 2 methods :
Using personal access token (PAT)
Using OAuth 2.0
I am using the second method. Followed the steps in this documentation:
https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops
I wrote this function to autherize to azure DevOps using OAuth 2.0:
def get_authenticated():
client_id = < my client ID as a string >
state = "user1"
scope = "vso.graph_manage%20vso.identity_manage%20vso.profile_write%20vso.project_manage%20vso.tokenadministration%20vso.tokens"
callback_URL = < Callback URL to my azure devops account >
# Azure DevOps Services authorization endpoint
Auth_URL = "https://app.vssps.visualstudio.com/oauth2/authorize?client_id=" + client_id + "&response_type=Assertion&state=" + state + "&scope=" + scope + "&redirect_uri=" + callback_URL
headers = {'Accept': 'application/json;api-version=1.0'}
print(Auth_URL)
response = requests.get(Auth_URL,headers = headers)
print(response)
print(response.status_code)
print(response.headers['content-type'])
response.raise_for_status()
But when calling this function, output I am getting is:
<Response [203]>
203
text/html; charset=utf-8
The auth URL is correct because when I tried to access the same URL in a browser it successfully redirects to a form to enter azure user credentials.
The expected behavior of the script is, when the auth_url is requested, Azure DevOps Services should ask the user to authorize. I think that should be done by prompting for username&password in terminal/via a browser.
I am totally new to python scripting and REST APIs.
Can someone help me by pointing out the faults in my code or pointing to some samples?
The http error 203 indicates that the returned metainformation is not a definitive set of the object from a server with a copy of the object, but is from a private overlaid web. In your code,you added headers = {'Accept': 'application/json;api-version=1.0'}, but in fact the content type should be application/x-www-form-urlencoded.
You can use some OAuth2 library for python to authenticate to Azure DevOps REST API, such as OAuthLib. It includes sevelral samples.
Also, you can refer to following topic, hope it is helpful for you.
Tutorial for using requests_oauth2
I'm trying to access the new REST API for building a server-to-server interface to integrate the CRM with other applications such as the web-shop etc.
I have tried both ways of getting an access-token from Azure AD:
Client credentials
import adal
token_response = adal.acquire_token_with_client_credentials(
'https://login.microsoftonline.com/abcdefgh-1234-5678-a1b1-morerandomstuff',
client_id,
secret
)
and user/password
import adal
token_response = adal.acquire_token_with_username_password(
'https://login.microsoftonline.com/abcdefgh-1234-5678-a1b1-morerandomstuff',
'interface#crm.my_domain.com',
'my_password'
)
In both cases, token_response gets a token-object, containing accessToken, refreshToken, expiresIn and so on. So I don't think there's an error up to this point.
Then I try to make a simple request to the web API:
headers = {'Authorization': '%s %s' % (token_response.get('tokenType'),
token_response.get('accessToken'))}
r = requests.get('https://domain.api.crm4.dynamics.com/api/data/v8.0/Product',
headers=headers)
This always returns a HTTP 401 - Unauthorized: Access is denied.
('WWW-Authenticate', 'Bearer error=invalid_token,
error_description=Error during token validation!,
authorization_uri=https://login.windows.net/eabcdefgh-1234-5678-a1b1-morerandomstuff/oauth2/authorize,
resource_id=https://domain.api.crm4.dynamics.com/')
The user that tries to make the request has Office-365-Administrator privileges and in the CRM has all manager roles and the administrator role. Which for my taste is even a bit much, but I read somewhere, that the user has to have office-365 admin privileges.
In the Azure AD there is an Application configured which has "delegated rights" to the CRM ("Access CRM Online as organization users").
What am I missing here? Or is my REST-get-request wrong?
Microsoft documentation for the new API is practically nonexistent - whenever you click some link you get docs for the older APIs (organization API etc.)
acquire_token_with_username_password has an optional parameter for specifying which resource you want access to:
resource (str, optional): The resource you are accessing. Defaults to
'https://management.core.windows.net/'.
You should thus be able to specify that you want access to CRM by adding resource as an argument to acquire_token_with_username_password:
token_response = adal.acquire_token_with_username_password(
'https://login.microsoftonline.com/abcdefgh-1234-5678-a1b1-morerandomstuff',
'interface#crm.my_domain.com',
'my_password',
resource='https://domain.crm4.dynamics.com'
)
This should give you a proper token for accessing CRM.
After getting the correct token, you also need to modify your Web API call slightly (from Product to products):
r = requests.get('https://domain.api.crm4.dynamics.com/api/data/v8.0/products',
headers=headers)