Using app engine oauth service - python

I'm trying to authenticate a python command line script agains my app engine application using oauth.
I'm following these instructions but I still don't get the "big picture" of how it works.
Is this api "ready to use"? or should I implement the request handlers for the oauth process?.
So far, I have my app deployed and I'm using this oauth library, I'm trying this example with the following values:
SERVER = 'myapp.appspot.com'
PORT = 443 # Also tried 80
REQUEST_TOKEN_URL = '/_ah/OAuthGetRequestToken'
ACCESS_TOKEN_URL = '/_ah/OAuthGetAccessToken'
AUTHORIZATION_URL = '/_ah/OAuthAuthorizeToken'
CALLBACK_URL = 'oob'
RESOURCE_URL = 'http://myapp.appspot.com/'
CONSUMER_KEY = 'myapp.appspot.com'
CONSUMER_SECRET = 'AaB8BtzxM7Dr7wz9Dxc5y6gG'
Do I have to implement any request handler on the server side? Do I have to enable this api somewhere?
Thanks for any clarification.
EDIT: Here is the output of the client script running:
$ python test.py ** OAuth Python Library Example **
* Obtain a request token ...
REQUEST (via headers)
parameters: {'oauth_nonce': '64747931', 'oauth_timestamp': 1325595310, 'oauth_consumer_key': 'myapp.appspot.com', 'oauth_signature_method': 'HMAC-SHA1', 'oauth_version': '1.0', 'oauth_signature': 'rBMJdn8+n0yXei38tDMfHjYKxyM=', 'oauth_callback': 'oob'}
And the response I'm getting is:
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>400 Bad Request</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Bad Request</h1>
<h2>Your client has issued a malformed or illegal request.</h2>
<h2></h2>
</body></html>

You don't need to implement handlers, the framework will do that for you.
All you need to do is to use the oauth.get_current_user() and everything will be handled for you from the server perspective.
Also you don't suppose to put the secret in the client (I don't know even if GAE give you any access to the secret).

Related

How to contact flask-restful api from react native app?

i am new to backend dev. I try to developp a flask restful api. I followed the documentation and made the suggested minimal api, that is just returning a jsonified dict. With postman, curl and in the browser, no problem, the api is running and responds to my requests.
From my react native app however, i always get a Netwrok Error.
I tried lots of things:
- multiple IP addresses for the flask serveur
- differents ways to use axios
- different os : win10, ubuntu
- different endpoints : /, /api, /test
- different ways of writing the api (flask-restful class, flask app functions ...)
- manips from web documentations : dev mode of my device, chrome dev tools (port forwarding)
- i asked a react native developper to check my client-side code, nothing wrong according to him,
precisions :
- python code runs under a conda virtual env
- appli runs under node js and expo
- container folders of my app and my api are at the same level
- the flask server does not respond 404 or whatever, it does not respond at all, the error returned in react native is a network error
- depending on url, the network errors occurs immediately or after a 2 minutes delay
- flask shows requests and status when called by postman, curl, chrome, but does not react when i press my buttons from the react native app
Here is (one of) my python code:
from flask import (Flask, jsonify)
# from flask_restful import Resource, Api
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)
#app.route("/api", methods=["GET"])
def get():
return jsonify(hello='bouh !')
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=True)
and here is the clientside code:
import React, {Component} from 'react';
import { View, Button } from 'react-native';
import axios from 'axios';
import { sharedStyles } from '../../SHARED/_shared';
var url = "http://192.168.1.16:5000/api";
export default class PrevCommune extends Component {
constructor(props){
super(props);
this.navigation=this.props.navigation;
};
getAxios=()=>{
axios.get(`${url}`).then((response)=>{
console.log("succes axios :",response);
}).catch((error)=>{
console.log("fail axios :", error);
});
};
getFetch=()=>{
fetch(url).then((response)=>{
console.log("succes fetch :",response)
}).catch((error)=>{
console.log("fail fetch :",error)
})
}
render(){
return (
<View style={sharedStyles.mainContainer}>
<Button onPress={()=>this.getAxios()} title={"get axios"}></Button>
<Button onPress={()=>this.getFetch()} title={"get fetch"}></Button>
</View>
);
};
};
And the lines returned by requests:
fail axios : [Error: Network Error]
fail fetch : [TypeError: Network request failed]
I saw lots of tutos, videos, articles on flask api but i didn't find where i am wrong. Please tell me if you have any ideas ! I think both client and server codes are ok, the problem seems to be that my requests are blocked by something.
Solved : the probleme was my firewall ... thank you ricardo for the CORS doc =)
What worked for me was to change the IP address of localhost to my network IP in the api call in react native and then starting the flask application using the below command.
flask run --host=0.0.0.0

Telegram bot does not get updates from webhook

I have faced the following problem after moving my bot to the new server. I use webhook to get updates but now the bot does not get them from telegram servers. I tried to send POST request with curl from the remove server and bot handled it in a normal way. I checked webhook with getWebhookInfo and it returned an object with non-empty url and pending_update_count equal to 74 without errors. I guess, it means that telegram servers are not able to send POST request to my host for some reason.
OS of my server is Arch Linux.
I use pyTelegramBotAP.
CONFIG = ConfigParser()
CONFIG.read(os.path.join('data', 'config.ini'))
# webhook url
URL_BASE = "https://{}:{}".format(CONFIG['server']['ip'], CONFIG.getint('server', 'port'))
URL_PATH = "/{}/".format(CONFIG['telegram bot']['token'])
BOT = telebot.TeleBot(CONFIG['telegram bot']['token'])
# server that will listen for new messages
APP = web.Application()
URL = URL_BASE + URL_PATH
BOT.set_webhook(url=URL, certificate=open(CONFIG['ssl']['certificate'], 'rb'))
# Build ssl context
CONTEXT = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
CONTEXT.load_cert_chain(CONFIG['ssl']['certificate'], CONFIG['ssl']['private key'])
# Start aiohttp server
web.run_app(
APP,
host=CONFIG['server']['listen'],
port=CONFIG['server']['port'],
ssl_context=CONTEXT,
)
Please, help!
Telegram webhook only talks to https endpoints, so I suggest to check your server against https connections.
Also, getWebhookInfo call returns a status object with the latest error infomation of your endpoint. Have a look of that error info and might find the exact problem.
Please check the Firewall on your server, It is quite possible firewall on your server is not passing message to your application.
To check firewall status run $ ufw status
Please show you URL_BASE without real IP.
What operating system is on your server?
You send test request from the CURL to URL of the Telegram or of your server?
Can you getting response from your server if you run simple app?
Example:
from aiohttp import web
async def hello(request):
return web.Response(text='Hello world!')
app = web.Application()
app.add_routes([web.get('/', hello)])
web.run_app(app, host='localhost', port=3003)
Check response:
$ curl localhost:3003
Hello world!
Please provide more detailed information on how you troubleshoot.

Azure Active Directory get token request http error

I'm using Active Directory Authentication library for python following the documentation. Earlier on I managed to get the access_token through the Acquire Token with Client Credentials sample:
import adal
RESOURCE_URI = 'https://<mydomain>.crm.dynamics.com'
AUTHORITY_URL = "https://login.microsoftonline.com/<tenant_id>"
CLIENT_ID = 'xxxx' #application_id
CLIENT_SECRET = 'xxxx'
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_client_credentials(
RESOURCE_URI,
CLIENT_ID,
CLIENT_SECRET)
print token
But I get an error message when I tried the Acquire token and Refresh token sample
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_username_password(
RESOURCE_URI,
USERNAME,
PASSWORD,
CLIENT_ID)
print token
>>> adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
There are two kinds of app we can register on Azure, native or web app. Based on the error message, it seems that you have register a confident app which requires provide its client secret to acquire the access token.
For this issue please register a native app instead of web app. Also the resource owner password credentials flow should be consider used carefully since this may leak the credentials. Refer the flows from link below:
The OAuth 2.0 Authorization Framework - Authorization Grant
I suffered from the same error.
In app registration section in azure active directory I registered the app as web host/api.
When I changed it to native app everything started to work fine.

How safe is my Flask REST API?

My website is on http protocol. My flask API is secured via flask-httpauth (https://github.com/miguelgrinberg/Flask-HTTPAuth).
There is a Tornado web server in front of my Flask API which listens on a private port 5000. Client API requests first go to Tornado server which then calls the Flask API
This is the flow I've got going:
My website (on http) ---> corpauthentication (on https) --> back to my website (http) --> client calls Tornado server --> Tornado calls Flask API and returns results
How safe is my API and website? I was reading this link Security of python flask REST API using HTTP Basic Authentication and it seems to me that the API is secure but I can never be sure.
If its not safe, what else do you think I can do to make it more secure? Since corpauthentication is required to get in, I feel on the UI side it is pretty safe. But lets say someone is listening on my port 80, will they be able to track any API requests made even when there is tornado + httpbasic auth in place?
This is my Tornado Server code:
from tornado.wsgi import WSGIContainer
from tornado.ioloop import IOLoop
from tornado.web import FallbackHandler, RequestHandler, Application
from flaskfile import app
class MainHandler(RequestHandler):
def get(self):
self.write("This message comes from Tornado ^_^")
tr = WSGIContainer(app)
application = Application([
(r"/tornado", MainHandler),
(r".*", FallbackHandler, dict(fallback=tr)),
])
if __name__ == "__main__":
application.listen(5000)
IOLoop.instance().start()
This is how I'm calling the API from my Javascript:
$.ajax({
url: 'http://x.x.x:5000/data',
type: 'GET',
dataType: 'json',
async: false,
headers: {
"Authorization": "Basic " + btoa("username" + ":" + "password")
},
data: {start: startdate, end: enddate},
success: function(result) {
data = result.results;
}
});
No, this is not secure - the comments in the other question you linked to are entirely correct. (BTW your question is really a duplicate of that).
Authentication over regular unencrypted HTTP is never secure - the username and password will be visible to any device between the user and the webserver, in plain text. As a first step you should implement SSL/TLS to encrypt the authentication information.
Tornado really needs to sit behind a web proxy of some sort. You could use either Apache or Nginx to fulfil this role. There are instructions for setting up Tornado+Nginx in this related question.

OneDrive API does not send the auth code to program

I have this easy code sample for the OneDrive API on Python:
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
redirect_uri = "https://login.live.com/oauth20_desktop.srf"
client_secret = "client-secret-code1234"
client = onedrivesdk.get_default_client(client_id='00000000123456F',
scopes=['wl.signin',
'wl.offline_access',
'onedrive.readwrite'])
auth_url = client.auth_provider.get_auth_url(redirect_uri)
#this will block until we have the code
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
client.auth_provider.authenticate(code, redirect_uri, client_secret)
returned_item = client.item(drive="me", id="root").children["newfile.txt"].upload("./newfile.txt")
So, when I run this my browser opens and I can choose Yes or No for the permissions of my App. When I choose Yes it should send the auth code back to my python program and upload the file in returned_item.
But it does not come back.
Any ideas how to solve it?
In the oauth authentication flow, after successful authentication of your app the authentication token needs to be sent somewhere. The redirect_uri is where the browser is heading after the authentication.
The case here is that a server listening on http://localhost:8080 is created by the call to GetAuthCodeServer.get_auth_code(auth_url, redirect_uri), waiting for the token.
So you need to use this url as redirect_uri.
Also in order to allow this redirect, you need to add it as 'trusted' in your App Settings under 'API Settings'.
And make sure 'Mobile or desktop client app' is set to 'yes'.

Categories

Resources