I'm trying to get the weather data for London in JSON but I am getting HTTPError: HTTP Error 401: Unauthorized. How do I get the API working?
import urllib2
url = "http://api.openweathermap.org/data/2.5/forecast/daily?q=London&cnt=10&mode=json&units=metric"
response = urllib2.urlopen(url).read()
The docs open by telling you that you need to register for an API key first.
To access the API you need to sign up for an API key
Since your url doesn't contain a key, the site tells you you're not authorized. Follow the instructions to get a key, then add it to the query parameters.
http://api.openweathermap.org/data/2.5/forecast/daily?APPID=12345&q=...
Error:
Invalid API key. Please see http://openweathermap.org/faq#error401 for more info
API calls responds with 401 error:
You can get the error 401 in the following cases:
You did not specify your API key in API request.
Your API key is not activated yet. Within the next couple of hours, it will be activated and ready to use.
You are using wrong API key in API request. Please, check your right API key in personal account.
You have free subscription and try to get access to our paid services (for example, 16 days/daily forecast API, any historical weather data, Weather maps 2.0, etc). Please, check your tariff in your [personal account]([price and condition]).
here are some steps to find problem.
1) Check if API key is activated
some API services provide key information in dashboard whether its activated, expired etc. openWeatherMap don't.
to verify whether your key is working 'MAKE API CALL FROM BROWSER'
api.openweathermap.org/data/2.5/weather?q=peshawar&appid=API_key
replace API_key with your own key, if you get data successfully then your key is activated otherwise wait for few hours to get key activated.
2) Check .env for typos & syntax
.env is file which is used to hide credentials such as API_KEY in server side code.
make sure your .env file variables are using correct syntax which is
NAME=VALUE
API_KEY=djgkv43439d90bkckcs
no semicolon, quotes etc
3) Check request URL
check request url where API call will be made , make sure
It doesn't have spaces, braces etc
correct according to URL encoding
correct according to API documentation
4) Debug using dotenv:
to know if you dotenv package is parsing API key correctly use the following code
const result = dotenv.config()
if (result.error) {
throw result.error
}
console.log(result.parsed)
this code checks if .env file variables are being parsed, it will print API_KEY value if its been parsed otherwise will print error which occur while parsing.
Hopefully it helps :)
For a graduate i was helping, he had a correct api key and it was active, but the api was incorrectly 401 when no content type was given
it was a simple as adding a Content-Type: application/json, and hey presto the api started working
curl command
curl --location \
--request GET \
'https://api.openweathermap.org/data/2.5/forecast?lat=55&lon=-3&appid=xxx' \
--header 'Content-Type: application/json'
I also faced the same issue, I have just created an account on open weather map and also verified the email, tried to load the api using several different url , but they replied with 401 , api key not found.
Solution: after 1 hour they all started working, so the reason was for activation it took 1 or some more hours.
The api key not set in your url ! before all you must register in https://openweathermap.org/ then get api key in your pesrsonal account after that do it like this:
http://api.openweathermap.org/data/2.5/weather?q={city}&appid=YOUR_API_KEY_HERE&units=metric
replace you apikey code with {YOUR_API_KEY_HERE}
then run your app.
After registering, you need to verify email.
Related
I am trying to use the python package yagmail to send emails but am having a tough time getting authorization to work.
My issue is getting an Oauth 2 token, but there is a disconnect with yagmail, as specified in a github thread. As stated in this post, https://github.com/kootenpv/yagmail/issues/143, it appears that google does not supply the credential file in the correct format. But I tried a bunch of things and each has its own problem.
When I set up a Client ID in the Google API console, download the
json as credentials.json and let the system create the token.json,
things work to a point: I am brought through google to "pick an
account, do you want to continue" and token is created. I am able to
print labels for the gmail account. But when I issue
yag.send(to='xxx#gmail.com', subject='Testing Yagmail',
contents='Hurray, it worked!'), I get an error "TypeError:
refresh_authorization() got an unexpected keyword argument 'token'."
When I look at the token file, it does contain the key 'token' which
it should not per this github post https://github.com/kootenpv/yagmail/issues/143#issuecomment-527115298][2].
If I go into the token and edit it to reflect the the expected
contents as identified in the above link by removing keys that are
not specified and prefixing the names with 'google_', I get an error
"ValueError: Authorized user info was not in the expected format,
missing fields refresh_token, client_id, client_secret." It doesn't
seem to like the 'google_' prefix.
editing the token file as above without the 'google_' prefix seems to
get further producing a different error "An error occurred:
<HttpError 403 when requesting
https://gmail.googleapis.com/gmail/v1/users/me/labels?alt=json
returned "Request had insufficient authentication scopes"
I am stuck. Relatively new to Oauth2, but it seems others are able to use yagmail. Is there a trick I am missing? I originally posted on Github because I found that other related post, but it seems SO is more geared toward Q&A. Is there a relation betweeen Github and SO? Difference?
Thanks for any assistance,
Brian
I finally found a solution and the answer was hidden in plain sight.
First the Oauth authorization needed to be set up as outlined in this post (which is excellent): Sending email via Gmail & Python
As stated, when yagmail is run the first time the authorization process gives instructions, the final stating to "Navigate to the following URL to auth:" and asks "Enter the localhost URL you were redirected to:"
The problem is the browser window shows what appears to be an error message, a sad face with a message "This site can’t be reached, localhost refused to connect, reload", etc. I never thought this was expected behavior. The url is the one being navigated to in the error screen.
Simply stating the error should be expected, and the url needs to be copied and pasted in the post above would help a lot.
I only want to pull data from a list called dataacq within a group (or site?) called prod within the domain (or root site?) tenant.sharepoint.com (or tenant-my.sharepoint.com ?) and put it into a DataFrame.
I have an issue with the token gotten through app.acquire_token_silent.
Microsoft documentation is not comprehensible because it's too heavy and has little workable cookbooks/working examples (as can be seen by my numerous question marks). Also it seems they want to centralize all their APIs into graph.microsoft.com, yet there is no warning that tenant.sharepoint.com/sites/prod/_api/ is going to be discontinued.
I have gotten the following permissions from the azure portal for my app.
I don't believe I need all of them, but I am not sure. I just want to read a list. So is only Microsoft Graph > Sites.read.All necessary? Or is it Sharepoint > Allsites.Read ?
I know I both have an "app only" permission and a "signed in user" permission.
I did download the "quickstart" examples and I did read https://msal-python.readthedocs.io/en/latest/ . Although a token was successfully pulled using app.acquire_token_silent, using the returned token always throws some error whatever scope ('https://microsoft.sharepoint-df.com/.default' or 'https://graph.microsoft.com/.default') or API domain (graph.microsoft.com or tenant.sharepoint.com) I am using into a request:
{'error_description':
"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
{'error': {'code': 'AccessDenied',
'message': 'Either scp or roles claim need to be present in the token.',
'innerError': {'date': '2021-02-19T08:05:16',
'request-id': '01efc071-18e6-4006-8780-f771419ebe3e',
'client-request-id': '01efc071-18e6-4006-8780-f771419ebe3e'}}}
On the other hand, there is an API developer testing portal. When I am copying the token given in this portal into my python code, both scope/API domains work.
This is e.g. an example that works with copying & pasting the token from the portal, but not working with the token issued by the app.acquire_token_silent method:
r = requests.get( # Use token to call downstream service
fr'https://graph.microsoft.com/v1.0/sites/root:/sites/prod:/lists/{list_id}/items?expand=fields(select=Created))',
headers={'Authorization': 'Bearer ' + result['access_token'],},)
So the issue is with this app.acquire_token_silent method or the configuration file. But the returned response seems alright:
{'token_type': 'Bearer',
'expires_in': 3599,
'ext_expires_in': 3599,
'access_token': '...'}
What am I missing?
According to the code r = requests.get..... you provided in your description, it seems you use the microsoft graph api to implement it. If you use this api, you should use https://graph.microsoft.com/.default as scope to get the access token. And you can copy the access token to this page, decode the token and check if the permissions are included in it.
And according to the screenshot of "API permissions" tab of your registered app, please also do grant admin consent operation for the permission Sites.Read.All although it shows not required admin consent.
================================Update===============================
It seems the method acquire_token_silent() acquire the access token by client credential flow. So we should add the "Application" type permission but not "Delegated" permission in registered app.
Good morning,
I want to query households (my first query and generally first experience with the Sonos API) and have authenticated successfully. I got an access token and query the Control API like this:
headers={"Content-Type" : "application/json",
"Authorization" : "Bearer " + token["access_token"]}
resp = re.get('http://api.ws.sonos.com/control/api/v1/househoulds', headers=headers)
It returns me a response with error code "503: Service unavailable":
Service Unavailable
Service Unavailable - Zero size object
The server is temporarily unable to service your request. Please try again
later.
Reference XXXXX
(I cut out the reference because I am not sure, if it contains credentials). I remember that when I intentionally changed my access token to a wrong one yesterday, I would get an error code back that I am not authorized. But now when I change it to a false one I still just get this same page back (503: Service unavailable).
Does anyone have the same problem? Might it be some security mechanism because I authorized many times in a short time or is the control API just currently down? I tried yesterday and today and don't see a blog post stating a downtime.
I see two issues with the code snippet you provided:
Issue 1: Your API URL has a typo. You used "househoulds" instead of
"households".
Issue 2: Your URL needs to use https://, not http://
If you fix those two issues and are indeed using a valid access token, your request should work.
I am testing MSAL and ROPC flow. When I run sample https://github.com/Azure-Samples/ms-identity-python-desktop I get error:
python username_password_sample.py parameters.json
invalid_client
AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
I was having same problem while following MS documentation and used curl. Please check my other question where SO community helped me to solve problem. After adding application registration secret to curl request, I got valid token and I was able to fetch mails.
What is confusing me is fact that secret is not present in parameters.json file.
You missed the step No.6 from this link: https://github.com/Azure-Samples/ms-identity-python-desktop/tree/master/1-Call-MsGraph-WithUsernamePassword
If the application was set as Public Client, then the secret is not required.
For more details, you can read https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc#authorization-request for reference.
I am trying to implement a button on a web-based dashboard that allows a user to export the current data to a Google Spreadsheet using OAuth and GData API. Currently, I can get the user to a login/grant access page, but if I add the line to convert the request token to an access token, I receive:
"RequestError: Unable to upgrade OAuth request token to access token: 400, parameter_absent
oauth_parameters_absent:oauth_token"
I am following the instructions for OAuth 2 on this page:
https://developers.google.com/gdata/docs/auth/oauth
and have read both PyDocs for the Google APIs and found no details on this issue:
http://gdata-python-client.googlecode.com/hg/pydocs/gdata.docs.client.html#DocsClient
(Won't let me post a this hyperlink but other Pydoc is same URL but replace the piece after pydocs/ with gdata.gauth.html#ClientLoginToken)
This is the code that works:
def createDocsClient(self, oauth_callback_url):
docsClient = gdata.docs.client.DocsClient(source='RiskOps-QualityDashboard')
request_token = docsClient.GetOAuthToken(SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)
domain = None
auth_url = request_token.generate_authorization_url(google_apps_domain=domain)
self.redirect(str(auth_url))
request_token = gdata.gauth.AuthorizeRequestToken(request_token, self.request.uri
With the above code, I get to a grant access page and if you click the grant access page, you get a 404 error because it doesn't know where to go after (as expected), but the page has the proper URL displayed listing an oauth_verifier and oauth_token. The "AuthorizeRequestToken" line is supposed to use that URL to authorize the token so up to this line, everything seems to work.
When I add the following line right after the code above, I get the "RequestError" I wrote about:
access_token = docsClient.GetAccessToken(request_token)
I've tried different combinations of nesting the calls within each other, using the AeSave and AeLoad (as the instructions mention might be needed but I'm not sure if my case calls for it) and many other random and unsuccessful ideas and nothing is really giving me a good idea of what I'm missing or doing wrong.
Would really appreciate and help or any ideas anyone has.(If you can't tell, I'm fairly inexperienced when it comes to real-world code (as opposed to academic code). Thanks so much.