Parameter passing in Oauth1 - google API - python

I have authenticated the the user with scope of Google mail and Google contacts using Oauth1. Fetching mail is working perfectly fine with imaplib
While calling contacts API I'm getting the responds but when I make parametrized call i'm getting an error like "Authorization required"
eg:The user is authenticated for the API(scope) " https://www.google.com/m8/feeds/contacts/default/full" and I like to get responds it in json format so the API will look like " https://www.google.com/m8/feeds/contacts/default/full?alt=json " -- this API will give me error

I have identified the problem:
The problem was I was not including the parameters of the URL before generating signature for oAuth 1.0

Related

How to do google Sign In with the help of idToken in Django

This is the code I use to retrieve idToken in my flutter app
Future<void> _handleSignIn() async {
try {
final result = await _googleSignIn.signIn();
final ggAuth = await result!.authentication;
print(ggAuth.idToken); // this is the one that I use as token value
print(ggAuth.accessToken);
} catch (error) {
print(error);
}
}
And this is the code I use to access user info in my backend.
from google.oauth2 import id_token
from google.auth.transport import requests
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
userid = idinfo['sub']
print(userid)
except ValueError:
print('Invalid token)
But after replacing the token variable with the token received from flutter app and replacing the CLIENT_ID with the id generated for my app (available in the console) , it still throws the error of invalid token. What am I doing wrong?
EDIT- When I use https://jwt.io/ to decode the token it works as expected and I get all the details.
Authentication Think of the id token as your birth certificate. It just identifies you as a person.
Authorization Think of the access token as your drivers license its what contains the permissions that you have to drive a car.
An Id token does not out write give you permission to access any data on google servers. With an access token you have been authorized to access some data in this case some profile information.
The issue you are having is that you are using sign-in in. Sign in is Open id connect think of it as a birth certificate (Id token). There is a user their who is signing in to your app. They are in fount of their computer. By default with Google signin gives you get basic profile information. What you are doing with Jwt.io is checking the claims that are returned in the Id token. Id tokens are just the token that allows your application to identify that the user is logged in. There should also be a sub claim there you should use this id to map the user to your integral user system. There may be a user name and email address in the claims but you can not guarantee that they will be there every time google has stated they do not always return these claims.
To get user profile information after the user has logged in you should be using the people api the people.get method when passed the access token will return to you the profile information of the currently authenticated user.
beyond that you should IMO not be passing tokens to your backend if you want the token in the backend you should log the user in using your backend language.
Okay so the idToken that I had was correct but flutter terminal was not able to print its full length and because of which I was copying only half the token and was getting a signature error when checking manually.

401 error when using API from CPanel for first time

I have used API data from websites like Microsoft, Knowbe4, ninja, ITglue, twitch, etc. However I am having trouble understanding the authentication for Cpanel.
I have an API key that I obtained from the cpanel website.
Cpanel authorization: https://api.docs.cpanel.net/cpanel/tokens/
It says:
Using an API token
To call a UAPI function with an API token, run the following command from the command line:
curl -H'Authorization: cpanel username:APITOKEN' 'https://example.com:2083/execute/Module/function?parameter=value'
So I tried using python but I am getting a 401 error which relates to the password or api key.
Here is my code:
import requests
bluehostapi = "ANAPIKEY"
bluehosturl = "https://cpanel-box5504.bluehost.com:2083/cpsess4830273370/"
header = {"Authorization": "cpanel", "username":bluehostapi}
buuserrequest = requests.get(bluehosturl+"execute/email",headers=header)
print(buuserrequest)
But I always get back:
<Response [401]>
I also tried putting https://cpanel-box5504.bluehost.com:2083/cpsess4830273370/execute/mail into google chrome's address bar directly as the docs said that you can go to the api url directly. However when I did I received an error saying:
{"warnings":null,"status":0,"data":null,"messages":null,"errors":["Failed to load module “”: “Cpanel::API::” is not a valid name for a Perl module."],"metadata":{}}
My main goal is to test connecting to cpanel's api so I can retrieve all the usernames and emails of my clients programmably.

How to decode Firebase JWT token in Python

I have added Firebase to allow clients to authenticate directly from the web app client (browser). I am using the firebase-web JS package and it works great. I can see in my browser that I receive a user object with information about the user, including an idToken.
I need to then authenticate this user on my server backend, which is python django. In the Firebase docs I found a how-to for exactly what I am trying to do, which is to verify the id token.
Since they don't have the supported Firebase sdk for python, I need to use a third party solution. I have come to the python-jose package after finding it listed on the jwt.io site. The example looks simple enough:
jwt.decode(token, 'secret', algorithms=['RS256'])
This is my first time using JWT. I don't know what to use for the 'secret'. I tried pasting my id token as token, and the web API key from the Firebase console for secret, but got this error:
jose.exceptions.JWKError: RSA key format is not supported
I also tried the JWT debugger, which seems to be reading most of my id token correctly, but the signature verification is looking for a public and/or a private keys, which like the 'secret' are escaping me.
I am really at a loss for how to find this secret, and how to verify the JWT id token in general. The information on the Firebase docs (third-party section) is:
Finally, ensure that the ID token was signed by the private key
corresponding to the token's kid claim. Grab the public key from
https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com
and use a JWT library to verify the signature. Use the value of
max-age in the Cache-Control header of the response from that endpoint
to know when to refresh the public keys.
I have tried pasting the whole json blob from that googleapis url into the JWT debugger, but still getting an "invalid signature" alert. I don't understand how to use that public key.
Should python-jose work for this approach? If so, what should I use for the secret? If not, can someone point me in the right direction?
Thanks.
I finally found the answer I was looking for in this post: Migrating Python backend from Gitkit to to Firebase-Auth with python-jose for token verification
Since the time of the post there have been updates made to the python-jose package, which gives better support for firebase id tokens. Here is some working code ( jose version 1.3.1 ) on how to use python to decode the firebase id token:
import urllib, json
from jose import jwt
idtoken = "<id token passed to server from firebase auth>"
target_audience = "<firebase app id>"
certificate_url = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com'
response = urllib.urlopen(certificate_url)
certs = response.read()
certs = json.loads(certs)
#will throw error if not valid
user = jwt.decode(idtoken, certs, algorithms='RS256', audience=target_audience)
print user

YouTube API without user OAuth process

I am trying to fetch captions from YouTube video using YouTube Data API (v3)
https://developers.google.com/youtube/v3/guides/implementation/captions
So, first I tried to retrieve a captions list using this url:
https://www.googleapis.com/youtube/v3/captions?part=snippet&videoId=KK9bwTlAvgo&key={My API KEY}
I could retrieve the caption id that I'd like to download (jEDP-pmNCIqoB8QGlXWQf4Rh3faalD_l) from the above link.
Then, I followed this instruction to download the caption:
https://developers.google.com/youtube/v3/docs/captions/download
However, even though I input the caption id and my api key correctly, it shows "Login Required" error.
I suppose I need OAuth authentication, but what I am trying to do is not related to my users's account, but simply downloading public caption data automatically.
My question is: Is there any way to process OAuth authentication just once to get an access token of my own YouTube account and then reuse it whenever I need it in my application?
I can't speak to the permissions needed for the captions API in particular, but in general, yes, you can OAuth to your app once using your own account and use the access and refresh tokens to make subsequent OAuth'd requests to the API. You can find the details of generating tokens here:
https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#Obtaining_Access_Tokens
To perform the steps manually (fortunately, you only need to do this once):
If access has already been granted for an app, it needs to be removed so that new auth credentials can be established. Go to https://security.google.com/settings/security/permissions (while logged into your account) and remove access to the app. If the client ID or secret change (or you need to create one), find them at https://console.developers.google.com under API Manager.
To grant access and receive a temporary code, enter this URL in a browser:
https://accounts.google.com/o/oauth2/auth?
client_id=<client_id>&
redirect_uri=http://www.google.com&
scope=https://www.googleapis.com/auth/youtube.force-ssl&
response_type=code&
access_type=offline&
approval_prompt=force
Follow the prompt to grant access to the app.
This will redirect to google.com with a code parameter (e.g.,
https://www.google.com/?code=4/ux5gNj-_mIu4DOD_gNZdjX9EtOFf&gws_rd=ssl#). Save the code.
Send a POST request (e.g., via Postman Chrome plugin) to https://accounts.google.com/o/oauth2/token with the following in the request body:
code=<code>&
client_id=<client_id>&
client_secret=<client_secret>&
redirect_uri=http://www.google.com&
grant_type=authorization_code
The response will contain both an access token and refresh token. Save both, but particularly the refresh token (because the access token will expire in 1 hour).
You can then use the access token to send an OAuth'd request manually, following one of the options here, essentially:
curl -H "Authorization: Bearer ACCESS_TOKEN" https://www.googleapis.com/youtube/v3/captions/<id>
or
curl https://www.googleapis.com/youtube/v3/captions/<id>?access_token=ACCESS_TOKEN
(When I tried the second option for captions, however, I got the message: "The OAuth token was received in the query string, which this API forbids for response formats other than JSON or XML. If possible, try sending the OAuth token in the Authorization header instead.")
You can also use the refresh token in your code to create the credential needed when building your YouTube object. In Java, this looks like the following:
String clientId = <your client ID>
String clientSecret = <your client secret>
String refreshToken = <refresh token>
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setRefreshToken(refreshToken);
try {
credential.refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
youtube = new YouTube.Builder(transport, jsonFactory, credential).build();
I imagine you can do something similar in Python with the API Client Libraries, although I haven't tried Python.

Authentication with the Google Docs List API, Python and OAuth 2

I'm trying to use the Google Docs API with Python+Django and OAuth 2. I've got the OAuth access token, etc. via google-api-python-client, with the code essentially copied from http://code.google.com/p/google-api-python-client/source/browse/samples/django_sample/plus/views.py
Now, I assume I should be using the google gdata API, v 2.0.17. If so, I'm unable to find exactly how to authorize queries made using the gdata client. The docs at http://packages.python.org/gdata/docs/auth.html#upgrading-to-an-access-token (which appear outdated anyway), say to set the auth_token attribute on the client to an instance of gdata.oauth.OAuthToken. If that's the case, what parameters should I pass to OAuthToken?
In short, I'm looking for a brief example on how to authorize queries made using the gdata API, given an OAuth access token.
The OAuth 2.0 sequence is something like the following (given suitably defined application constants for your registered app).
Generate the request token.
token = gdata.gauth.OAuth2Token(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
scope=" ".join(SCOPES),
user_agent=USER_AGENT)
Authorise the request token. For a simple command-line app, you can do something like:
print 'Visit the following URL in your browser to authorise this app:'
print str(token.generate_authorize_url(redirect_url=REDIRECT_URI))
print 'After agreeing to authorise the app, copy the verification code from the browser.'
access_code = raw_input('Please enter the verification code: ')
Get the access token.
token.get_access_token(access_code)
Create a gdata client.
client = gdata.docs.client.DocsClient(source=APP_NAME)
Authorize the client.
client = token.authorize(client)
You can save the access token for later use (and so avoid having to do the manual auth step until the token expires again) by doing:
f = open(tokenfile, 'w')
blob = gdata.gauth.token_to_blob(token)
f.write(blob)
f.close()
The next time you start, you can reuse the saved token by doing:
f = open(tokenfile, 'r')
blob = f.read()
f.close()
if blob:
token = gdata.gauth.token_from_blob(blob)
Then, the only change to the authentication sequence is that you pass this token to OAuth2Token by specifying a refresh_token argument:
token = gdata.gauth.OAuth2Token(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
scope=" ".join(SCOPES),
user_agent=USER_AGENT,
refresh_token=token.refresh_token)
Hope this helps. It took a while to work it out :-).
This is from https://developers.google.com/gdata/docs/auth/overview:
Warning: Most newer Google APIs are not Google Data APIs. The Google Data APIs documentation applies only to the older APIs that are listed in the Google Data APIs directory. For information about a specific new API, see that API's documentation. For information about authorizing requests with a newer API, see Google Accounts Authentication and Authorization.
You should either use OAuth for both authorization and access or OAuth 2.0 for both.
For OAuth 2.0 API are now at https://developers.google.com/gdata/docs/directory.

Categories

Resources