Apidoc for Flask-JWT's authentication url - python

I have started using apidoc for generating REST api documentation. I have tried different things with it.
In my flask based api application, I use JWT (flask-jwt in particular) for authentication. The doc gets generated properly, but the request from the doc doesn't happen properly.
This is where I have put the docsting for generating the doc
def authenticate(username, password):
"""
#api {post} /auth Authentication url
#apiName Authentication
#apiGroup Login
#apiParam {String} username Username of the user
#apiParam {String} password Password of the user
#apiSuccess {String} access_code JWT
#apiSuccessExample Success Response
HTTP/1.1 200 OK
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6IjM5MDA4MGExLWY0ZjctMTFlNS04NTRkLTI4ZDI0NDQyZDNlNyIsImlhdCI6MTQ1OTE3ODE0NSwibmJmIjoxNDU5MTc4MTQ1LCJleHAiOjE0NTkxNzg0NDV9.nx_1a4RmvJ7Vlf1CvnMzqoTfzChcuJnDb1Tjy1_FnXw"
}
#apiErrorExample Invalid Credentials
{
"description": "Invalid credentials",
"error": "Bad Request",
"status_code": 401
}
"""
user = session.query(User).filter_by(username=username).first()
if user and user.is_correct_password(password):
return user
return False
And when I generate the doc, it get's generated properly
$ apidoc -i onehop/ -o doc
But when I pass credentials from the generated doc, the request fails. The request data I get in flask's request is '' (empty)
It also fails even after including the Content-Type header in the docstring. The request data I get in flask's request is username=test#example.com&password=test123
I have confirmed above by putting debug points in Flask-JWT's code
def _default_auth_request_handler():
data = request.get_json() # My debug poing
username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)
password = data.get(current_app.config.get('JWT_AUTH_PASSWORD_KEY'), None)
But when I make the same request using postman it happens properly.
Postman headers
Apidoc headers
What did I miss?

Related

How can I test AWS Cognito protected APIs in Python?

I'm trying to test out some AWS APIs that are protected by Cognito. I found the first part on how to get the Json token but I can't figure out how to use the token correctly so I can authenticate on the API.
Here's my code :
import boto3 as boto3;
import requests
username='test#gmail.com'
password='test1234567'
client = boto3.client('cognito-idp')
response = client.initiate_auth(
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
"USERNAME": username,
"PASSWORD": password,
},
ClientId='12121212121212',
)
token = response['AuthenticationResult']['AccessToken']
#print("Log in success")
#print("Access token:", response['AuthenticationResult']['AccessToken'])
#print("ID token:", response['AuthenticationResult']['IdToken'])
url = 'https://XXXXXXXX.execute-api.eu-west-1.amazonaws.com/Prod/incidents'
#print('url:', url)
#response = requests.get(url, headers={'authorization': token })
#print('GET:', response.status_code)
head = {'Authorization': token}
response = requests.get(url, headers=head)
print(response.content)
I'm getting the following error message :
b'{"message":"Authorization header requires \'Credential\' parameter. Authorization header requires \'Signature\' parameter. Authorization header requires \'SignedHeaders\' parameter. Authorization header requires existence of either a \'X-Amz-Date\' or a \'Date\' header. Authorization=
Ok so I found the problem and it's working fine now, 2 things were wrong :
The endpoint was wrong - AWS doesn't send a correct error message (!)
The request has to be sent with response['AuthenticationResult']['IdToken']
Please make sure you have selected Cognito or IAM in your API Gateway. From the error message it seems you have selected IAM for protecting the API.
Check the Authorization header's name which you configured for your Cognito Authorizer. You need to use same header name while passing the Cognito token.
If you have configured OAuth scopes in API Gateway side, then you must use access token. And no scope is configured then you can use ID token for authorization.
That said, you can try from Postman application for testing purpose.

What Headers and Data to Send With My Post Request

Very beginner to web. I'm trying to login my router's configuration page which resides at 192.168.1.1 address. There is an authorization process and I inspected the post request being sent when logged in, via dev-tools of the browser. The "Form Data" includes these arguments:
Username: admin
Password: pass
action: login
Response code is 301 (Moved Temporarily) however, when I try to send a post request with python, the response code is 200 and the returned html prints the login layout. Also there are no cookies returned back except this "_TESTCOOKIESUPPORT=1". My code below:
import requests
data = {
"Username": 'admin',
"Password": 'pass',
"action": 'login'
}
session = requests.session()
response = session.post("http://192.168.1.1", data=data)
print(response)
print(response.cookies)
Also when I run my code and refresh the login page from browser I get "wrong credentials" error from the page. What's wrong with my post request?

How to replace token(bearer) with username, password in Cherwell REST API request

I am trying to create RFC in cherwell using REST API in Python. I tried first in Swegger UI. I got it working there. I am able to create RFC successfully. Then by following that Curl Request, in python, using request module, I tried and got 401. I found it why i am getting 401. It's because of in Authorization i am using Bearer which is a temporary token. It will live only for 10 minutes. If i do request after 10 minutes i got a 401. Bearer is a compulsory field. I can't make a request without it. I tried to pass username and password instead of Bearer, it didn't work. below is my request,
with open('C:\Cherwell\payload.json') as file:
Data = json.load(file)
payload = Data
header = {"Authorization":"Bearer XXXXXXXX"}
r = requests.post("https:/URL/CherwellAPI/api/V1/savebusinessobject?
api_key=XXXX-XXXX-XXXX-XXXX", auth=('user','pass'), headers = header,
data=json.dumps(payload))
print r
It will be great, if anyone can help who have done this before! Please Advice
Appreciate any help!
Found this solution that I used to address a similar problem. It's a function that requests a token from /CherwellAPI/token and returns a properly formatted Bearer token. You need to pass this Bearer token along in API requests as a Authorization parameter in the API header. Should look like token=bearer_token.
import json
import requests
configFile = 'config.json'
with open(configFile) as cf:
config_data = json.load(cf)
def getCherwellToken():
params = {'apikey' : config_data['cherwell']['client_id']}
data = {'grant_type' : 'password',
'client_id' : config_data['cherwell']['client_id'],
'username' : config_data['cherwell']['username'],
'password' : config_data['cherwell']['password']}
url = 'https://.cherwellondemand.com/CherwellAPI/token'
session = requests.post(url=url, data=data)
if session:
token = json.loads(session.text)
else:
token = None
return 'Bearer ' + token['access_token']
using another call Get Token You can get access token and using that you can request to create a new ticket. This worked for me.

Firebase DB HTTP API Auth: When and how to refresh JWT token?

I'm trying to make a Python webapp write to Firebase DB using HTTP API (I'm using the new version of Firebase presented at Google I/O 2016).
My understanding so far is that the specific type of write I'd like to accomplish is made with a POST request to a URL of this type:
https://my-project-id.firebaseio.com/{path-to-resource}.json
What I'm missing is the auth part: if I got it correctly a JWT should be passed in the HTTP Authorization header as Authorization : Bearer {token}.
So I created a service account, downloaded its private key and used it to generate the JWT, added it to the request headers and the request successfully wrote to Firebase DB.
Now the JWT has expired and any similar request to the firebase DB are failing.
Of course I should generate a new token but the question is: I wasn't expecting to handle token generation and refresh myself, most HTTP APIs I'm used to require just a static api key to be passed in the request so my webapps could be kept relatively simple by just adding the stati api key string to the request.
If I have to take care of token generation and expiration the webapp logic needs to become more complex (because I'd have to store the token, check if it is still valid and generate a new one when not), or I could just generate a new token for every request (but does this really make sense?).
I'd like to know if there's a best practice to follow in this respect or if I'm missing something from the documentation regarding this topic.
Thanks,
Marco
ADDENDUM
This is the code I'm currently running:
import requests
import json
from oauth2client.service_account import ServiceAccountCredentials
_BASE_URL = 'https://my-app-id.firebaseio.com'
_SCOPES = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database'
]
def _get_credentials():
credentials = ServiceAccountCredentials.from_json_keyfile_name('my_service_account_key.json', scopes=_SCOPES)
return credentials.get_access_token().access_token
def post_object():
url = _BASE_URL + '/path/to/write/to.json'
headers = {
'Authorization': 'Bearer '+ _get_credentials(),
'Content-Type': 'application/json'
}
payload = {
'title': title,
'message': alert
}
return requests.post(url,
data=json.dumps(payload),
headers=headers)
Currently for every request a new JWT is generated. It doesn't seem optimal to me. Is it possible to generate a token that doesn't expire?
Thanks for the code example. I got it working better by using the credentials.authorize function which creates an authenticated wrapper for http.
from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
import json
_BASE_URL = 'https://my-app-id.firebaseio.com'
_SCOPES = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database'
]
# Get the credentials to make an authorized call to firebase
credentials = ServiceAccountCredentials.from_json_keyfile_name(
_KEY_FILE_PATH, scopes=_SCOPES)
# Wrap the http in the credentials. All subsequent calls are authenticated
http_auth = credentials.authorize(Http())
def post_object(path, objectToSave):
url = _BASE_URL + path
resp, content = http_auth.request(
uri=url,
method='POST',
headers={'Content-Type': 'application/json'},
body=json.dumps(objectToSave),
)
return content
objectToPost = {
'title': "title",
'message': "alert"
}
print post_object('/path/to/write/to.json', objectToPost)

facebook graph Api: Posting on page: permission issue

I am trying to develop a app which will post on user's Facebook page.
Steps I followed are:
1.Created a fb App, with permission : manage_pages and publish_actions
2.Redirected user to 'https://www.facebook.com/dialog/oauth
With parameters:
client_id=FACEBOOK_APP_ID
redirect_uri=FACEBOOK_REDIRECT_URL
scope=manage_pages,publish_actions
Where user allowed app against each permissions
3.On call back url (FACEBOOK_REDIRECT_URL), cought CODE sent by facebook api
4.Now I sent get request to url = https://graph.facebook.com/oauth/access_token with parameters:
'client_id':FACEBOOK_APP_ID
'redirect_uri':FACEBOOK_REDIRECT_URL
'client_secret':FACEBOOK_SECRET_KEY,
'code':CODE
from respose sent by facebook, I filtered TOKEN
5.sent get request to url = https://graph.facebook.com/me/accounts. with parameters:
'access_token':TOKEN
from response I received, I saved page id as PAGE_ID, page_token as PAGE_TOKEN
6.I tried to post something on user's facebook page, I sent post request to url = https://graph.facebook.com/PAGE_ID/feed , with parameters:
'access_token':TOKEN'
'message': MESSAGE_TEXT,
Snap! in response I received:
{
"error": {
"message": "(#200) The user hasn't authorized the application to perform this action",
"type": "OAuthException",
"code": 200
}
}
I couldn't figure out What mistake I am committing, Do I need to get my app reviewed before posting ? If yes, How can I test my app?
I also tried this by creating a test user. I got the same error.
Thanks to #dhana,
In order to Post on a facebook page, App need manage_pages and publish_action app centre permission, and manage_pages , publish_action and status_update scope while requesting
url = https://www.facebook.com/dialog/oauth?\
client_id='+FACEBOOK_APP_ID+'&\
redirect_uri=' +FACEBOOK_REDIRECT_URL+'&\
scope=manage_pages,publish_actions,status_update

Categories

Resources