Which headers should I provide for authentication in GitHub API? - python

I'm trying to use Basic Authentication in GitHub API. I wrote something like this:
reqURL = "https://api.github.com/repos/user/repo"
pullreqsURL = urllib.request.Request(reqURL)
pullreqsURL.add_header("Authorization", "Basic " + str(base64.urlsafe_b64encode(b'Username:myAuthTokenORpass')) )
pullreqsURL.add_header("Content-Type", "application/json")
pullreqsURL.add_header("Accept", "application/json")
urllib.request.urlopen(pullreqsURL)
However, it keeps throwing HTTPError.
With commented 3rd line it goes well.
Well. I've solved it using personal token instead of user:pass
pullreqsURL.add_header("Authorization", "token >mytoken<" )

It should be possible to authenticate via Basic Authentication with username/password.
Quote from the link:
Via Username and Password
To use Basic Authentication with the GitHub API, simply send the
username and password associated with the account.
However, I don't know Python, so I don't know whether str(base64.urlsafe_b64encode(b'Username:myAuthTokenORpass')) is the proper way to Base64 encode username/password.
As you mentioned personal access tokens, it's also possible to authenticate via Basic Authentication, but with an access token instead of your real password.
This is explained in my first link as well.
Quote:
Via OAuth Tokens
Alternatively, you can use personal access
tokens or OAuth
tokens instead of your password.
curl -u username:token https://api.github.com/user
This approach is useful if your tools only support Basic
Authentication but you want to take advantage of OAuth access token
security features.
I'm using this approach with success in a project of mine.

Related

Bitbucket API connection using token

I'm trying to connect to my bitbucket using API token generated in Bitbucket but the connection is returning HTTP 401 error when using Python requests module.
I need help to facilitate the completion of a task.
make sure that you use basic authentication and then set your username and use the personal token as password.
Your username still required since the token associated with it

How to add login credential via python script?

I am sure this is an answered question somewhere, but I could not find a solution for me (if you know a duplicate feel free to mark it).
My goal is to query a RESTful API. To do that I need to authenticate. The only way available for me for this API is via web-browser.
Basically, I am loading URL which redirects to another URL. In the second URL, there is a form where I need to input username and password to authenticate. Currently, I input the credentials manually via a web browser.
My question is: Can I do this programmatically such that I don't have to manually input the credentials via a web browser?
Note: the webpage is not verified.
Attempt 1
I tried the following commands, but none worked:
curl -k -u username:password https://myurl:port
It did not return anything.
Attempt 2
BASE_URL = 'https://myurl:port'
username = 'username'
password = 'password'
r = requests.get(BASE_URL, auth=(username, password), verify=False)
print(r.status_code, r.reason)
it prints <Response [200]> but it does not authenticate. This is because when I try to query an API endpoint - it says I am unauthorized. When I input the credentials manually in the browser - then the endpoint query works.
Attempt 3
Finally, I thought (but did not do) I need some way to read the login page and input credentials by getting the html elements and then clicking log in (with selenium for example), but this seems too rough and error-prone. Maybe there is a more elegant way.
Any ideas of how I can do this?
Basically, I am loading URL which redirects to another URL. In the
second URL, there is a form where I need to input username and
password to authenticate
From your description it sounds like you are accessing an API using OAuth2 with the authorization code grant flow ?...which by design requires the user (=resource owner) to authorise (via the form) your app (=client) to access his/her data provided by the API (=resource server). in this case, using basic auth (Attempt 1 and 2) will not help you as the API expects a token, not username/password. you'd probably need a refresh token that does not expire and would allow your client to request a fresh access token each time it wants to access the API...
It all depends on the authentication mechanism used by your API...I'd first figure out if your API is indeed using OAuth2, and if so, learn about authentication flows (e.g. https://www.udemy.com/course/learn-oauth-2/) ...client credentials flow is probably what you'd want if the API allows for it...
update: Attempt 3 might be worth a try, i've never done it though. you might be able to send the credentials by submitting the corresponding form data via python requests...then that should in theory provide you with an authorization code which you can use to get a token...
Thanks for showing us your attempts.
If the attempt 2 returns 200 status code. It means it does work which means that basic auth works. Simple solution is to just pass auth=(username, password) to all of your api calls.
Or you can use requests.Session() to authenticate once and keep the session provided that server supports session authentication.
Hope this helps.

Is it possible to use OAuth 2.0 without a redirect_uri or without setting up a complex server?

I got to transfer some files to a remote server for which I have to perform OAuth2.0 to get access token and then simply perform a POST request to upload the files.
Now I am too lazy to setup a Django project on cloud and then perform OAuth2 while there are not "too good" lib for that though.
So, I am thinking to perform OAuth2 using rauth lib as a simple python script without really setting up a server that accepts requests and all..
However, on the remote server profile, I need to provide a redirect_url and of course in the rauth client lib.
Are there any possible ways to do this authorization without really setting up a project on cloud..A simply python script is what I am looking for.
I'm the author and maintainer of rauth.
Rauth no longer enforces a redirect_uri, so if your provider allows it then you can forgo using it. However if you ultimate goal is not to setup a server, this should be doable even with a redirect_uri required by the provider. You can, for example, redirect to localhost where you could setup a minimal server using Flask or if the provider allows it, some other, arbitrary URL, e.g. Facebook provides https://www.facebook.com/connect/login_success.html for this purpose. And the provider you're using might have a similar scheme. Here's an example with rauth.
Another option is to use Bearer Auth with grant_type=password. All OAuth 2.0 providers are supposed to support Bearer Auth, but may not implement the password grant_type. This does not require a redirect_uri, instead you end up passing the server your user credentials and it should return an access token to you. If your provider allows Bearer Auth with grant_type of password, this is probably the ideal for you. Rauth 0.5.3 attempts to use Bearer Auth by default so all you have to do is pass in the grant_type. Be sure to update before giving this a go.
Here's a simple example:
# assume you have constructed an OAuth2Service object and bound it to `serv`
params = {'grant_type': 'password',
'username': 'foo',
'password': 'hunter2'}
s = service.get_auth_session(params=params)
r = s.get('https://example.com/api/some/endpoint')
Depending on the provider and what you want to do, it may require a little more investigation. However, hopefully this gives you something to start with.
Edit
I think my comment about password grant_type is a little confusing: I seem to be implying you have to use it with Bearer Auth (here by Bearer Auth I mean affixing the access token in the Authorization header in the Bearer format), but actually you don't. It's acceptable, although discouraged, to send the credentials along in the entity method[1]. If you're using rauth and find that authentication is not working as expected, you may need to disable Bearer Auth like this:
s = service.get_auth_session('/some/resource',
data={'code': code},
bearer_auth=False)
From the spec:
[1] "Clients SHOULD make authenticated requests with a bearer token using the Authorization request header field with the Bearer HTTP authorization scheme. Resource servers MUST support this method."

How to get username with CherryPy digest authentication

I have a CherryPy application running successfully using the built-in digest authentication tool and no session support. Now, I would like to expose additional features to certain users. Is it possible to obtain the currently-authenticated user from the authorization system?
You can use: cherrypy.request.login.
To quote:
When authentication is used during the request processing this is set
to ‘False’ if it failed and to the ‘username’ value if it succeeded.
The default ‘None’ implies that no authentication happened.
The whole HTTP Basic / Digest authentication in CherryPy is very nicely explained here (unfortunately the original blog no longer features this page, at least I couldn't find it - WayBack Machine to the rescue).
Found the user name encoded in the HTTP request header Authorization. I am able to parse it from there. If there's a "better" place to obtain the username, I'm open to improvements!
How about this...
params = auth_header.split(" ", 1)
items = parse_http_list(params)
paramsd = parse_keqv_list(items)
username = paramsd.get('username')
http://www.gitorious.org/forban/forban/blobs/1f9aff12551675f7cd8395f8bd0733cfc4c40784/lib/ext/cherrypy/lib/auth_digest.py
As I looked at it more this approach still uses auth header...
Andrew

gdata-python-api + Analytics with simple auth

I'm working on converting a Python script using the Google gdata API client + user/pass authentication to something more suitable for production (an API key). I am pretty frustrated with the muddled state of their documentation on authentication. I admittedly don't have a great grasp of OAuth2, but it seems like it's way more complicated for my usage case, which is: Hit Google Analytics every 24 hours to get the X most popular articles on our site.
In this scenario, we're not dealing with modifying someone's personal data, and all activity is centered on one account. It doesn't seem like OAuth2 is worth the complexity for something so simple.
I see that on the Google API Console (https://code.google.com/apis/console/), I've registered there and notice that there's a "Simple API Access" section with one key beneath the "Client ID for web applications" (which appears to be OAuth2). There's also the Google domain update page, https://www.google.com/accounts/UpdateDomain, but that appears to be OAuth related.
Is there any way to use this Simple API Access key (not OAuth) for retrieving analytics data with the Python gdata client, and if so, does anyone have any authentication examples? I already have the data retrieval stuff working once authenticated, but I'm using the user/pass approach, which is not appropriate for production.
Greg,
If you are already using the library gdata-python-client, this is relatively easy to do if you are the only user that your application will be authorizing.
The general mechanisms were detailed in a blog post in September, 2011, but I'll describe them here for completeness.
Part 1: Go to the APIs console and start a new project.
Part 2: From the project, go to "Services" and enable "Analytics API"
Part 3: From the project, go to "API Access" and click "Create an OAuth 2.0 client ID..." (you'll need to provide a product name, though the value you provide won't matter). When asked for the application type, select "Installed Application" and then "Create client ID". Since you will be the only user, you will only need one refresh token, and you can get this by authorizing from a desktop application a single time.
Part 4: Get your client id and client secret from the APIs console and then create an empty token:
import gdata.gauth
CLIENT_ID = 'id-from-apis-console'
CLIENT_SECRET = 'secret-from-apis-console'
SCOPE = 'https://www.google.com/analytics/feeds/' # Default scope for analytics
token = gdata.gauth.OAuth2Token(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
scope=SCOPE,
user_agent='application-name-goes-here')
I got the scope from GData FAQ, though I'm not sure if it is correct.
Part 5: Use the token to create authorization URL for you to visit:
url = token.generate_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')
Since your application is an "Installed Application", your redirect URI is the default 'urn:ietf:wg:oauth:2.0:oob'. (Also note, the blog post had a typo and used the keyword argument redirect_url.)
Part 6: Visit the url and authorize your application to make requests on behalf of your account. After authorizing, you'll be redirected to a page with a code on it. This code will be used to exchange for an access token and a long-lived refresh token. The code has a life of 10 minutes and the access token has a life of an hour. The refresh token will allow you to get new access tokens for signing requests in perpetuity (or until you revoke the permission from your account).
Part 7: Use the code to get an access token:
code = 'random-string-from-redirected-page'
token.get_access_token(code) # This returns the token, but also changes the state
This again differs slightly from the blog post, because we are using an installed application.
Part 8: With the token you can now make all requests you want to make to the analytics client:
import gdata.analytics.client
client = gdata.analytics.client.AnalyticsClient()
token.authorize(client)
This is the big money right here. When an access token expires, the API requests signed with that token are rejected. However, by authorizing the client as above, when the said requests fail, the token attempts to use the refresh token to obtain a new access token. If it successfully obtains a new access token, the client resends the original API request, signed with the new access token.
I don't know anything about the Analytics API so I won't provide any more details there.
Future Use Note 1: Saving information for future use. You can re-use this from different places and after this use very easily. There are methods called token_to_blob and token_from_blob provided by the library that allow turning a token into a string and converting out of a string:
saved_blob_string = gdata.gauth.token_to_blob(token)
Once you have done this, you can store the string in a file and kill your running Python process. When you'd like to use it again:
saved_blob_string = retrieve_string_from_file() # You'll need to implement this
token = gdata.gauth.token_from_blob(saved_blob_string)
Future Use Note 2: This token will be able to be used to authorize a client and perform all your magic again and again, so long as you have the refresh token around. If for some reason you would like to get an access token again without calling token.generate_authorize_url, you'll need to manually set this on the object:
token.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
Future Use Note 3: Also, if you lose your refresh token and would like to get another one without having to go to the browser to revoke the original, you can use the approval_prompt parameter to get a new refresh token by visiting the url generated by:
url = token.generate_authorize_url(
redirect_uri='urn:ietf:wg:oauth:2.0:oob',
approval_prompt='force')

Categories