I have a terminal that served in webbrowser with wetty. I want to authenticate the user from gitlab to let user with interaction with the terminal(It is inside docker container. When user authenticated i ll allow him to see the containers terminal).
I am trying to do OAuth 2.0 but couldn't manage to achieve.
That is what i tried.
I created an application on gitlab.
Get the code and secret and make a http call with python script.
Script directed me to login and authentication page.
I tried to get code but failed(Their is no mistake on code i think)
Now the problem starts in here. I need to get the auth code from redirected url to gain access token but couldn't figure out. I used flask library for get the code.
from flask import Flask, abort, request
from uuid import uuid4
import requests
import requests.auth
import urllib2
import urllib
CLIENT_ID = "clientid"
CLIENT_SECRET = "clientsecret"
REDIRECT_URI = "https://UnrelevantFromGitlabLink.com/console"
def user_agent():
raise NotImplementedError()
def base_headers():
return {"User-Agent": user_agent()}
app = Flask(__name__)
#app.route('/')
def homepage():
text = 'Authenticate with gitlab'
return text % make_authorization_url()
def make_authorization_url():
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
state = str(uuid4())
save_created_state(state)
params = {"client_id": CLIENT_ID,
"response_type": "code",
"state": state,
"redirect_uri": REDIRECT_URI,
"scope": "api"}
url = "https://GitlapDomain/oauth/authorize?" + urllib.urlencode(params)
print get_redirected_url(url)
print(url)
return url
# Left as an exercise to the reader.
# You may want to store valid states in a database or memcache.
def save_created_state(state):
pass
def is_valid_state(state):
return True
#app.route('/console')
def reddit_callback():
print("-----------------")
error = request.args.get('error', '')
if error:
return "Error: " + error
state = request.args.get('state', '')
if not is_valid_state(state):
# Uh-oh, this request wasn't started by us!
abort(403)
code = request.args.get('code')
print(code.json())
access_token = get_token(code)
# Note: In most cases, you'll want to store the access token, in, say,
# a session for use in other parts of your web app.
return "Your gitlab username is: %s" % get_username(access_token)
def get_token(code):
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
post_data = {"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI}
headers = base_headers()
response = requests.post("https://MyGitlabDomain/oauth/token",
auth=client_auth,
headers=headers,
data=post_data)
token_json = response.json()
return token_json["access_token"]
if __name__ == '__main__':
app.run(host="0.0.0.0",debug=True, port=65010)
I think my problem is on my redirect url. Because it is just an irrelevant link from GitLab and there is no API the I can make call.
If I can fire
#app.route('/console')
that line on Python my problem will probably will be solved.
I need to make correction on my Python script or different angle to solve my problem. Please help.
I was totally miss understand the concept of auth2. Main aim is to have access_token. When i corrected callback url as localhost it worked like charm.
Related
jwt-flask-extended sends back same access token for any user always. I have integrated Flask with apache. Using Python 2.7.5, Operating System - Red Hat Enterprise Linux Server release 7.3 (Maipo). Find the code below.
app = Flask(__name__)
CORS(app)
#app.before_request
def log_request_info():
app.logger.debug('Headers: %s', request.headers)
app.logger.debug('Body: %s', request.get_data())
mysql = MySQL()
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'user'
app.config['MYSQL_DATABASE_PASSWORD'] = 'password'
app.config['MYSQL_DATABASE_DB'] = 'userdb'
app.config['MYSQL_DATABASE_HOST'] = 'mysql-host'
mysql.init_app(app)
# Setup the Flask-JWT-Extended extension
app.config['JWT_SECRET_KEY'] = 'Changeit' # Change this! if needed
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=28800)
jwt = JWTManager(app)
#app.route('/auth/token', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
uid = request.json.get('uid', None)
username = request.json.get('username', None)
if not uid:
return jsonify({"msg": "Missing required parameter"}), 400
if not username:
return jsonify({"msg": "Missing required parameter"}), 400
# Identity can be any data that is json serializable
access_token = create_access_token(identity=uid)
return jsonify(access_token=access_token), 200
WSGIPassAuthorization On.
I added this directive to Apache mod wsgi config file. It started working as expected .
That's because you're using global variables which aren't thread safe.
Your access token variable should go inside a function or a method.
If you still want it globally accessible, you can use Werkzeug's local package along with Flask's g variable.
I recommend putting it in a method though.
The question is about using webhooks in a Telegram bot using the pyTelegramBotAPI module.
I am using pythonanywhere.com to host the bot.
The following code works fine:
from flask import Flask, request
import telebot
secret = "A_SECRET_NUMBER"
bot = telebot.TeleBot ('YOUR_AUTHORIZATION_TOKEN')
bot.set_webhook("https://YOUR_PYTHONANYWHERE_USERNAME.pythonanywhere.c..
}".format(secret), max_connections=1)
app = Flask(__name__)
#app.route('/{}'.format(secret), methods=["POST"])
def telegram_webhook():
update = request.get_json()
if "message" in update:
text = update["message"]["text"]
chat_id = update["message"]["chat"]["id"]
bot.sendMessage(chat_id, "From the web: you said '{}'".format(text))
return "OK"
But when I use message handlers as shown in the example, I receive no answer from the bot:
# Process webhook calls
#app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_updates([update])
return ''
else:
flask.abort(403)
# Handle '/start' and '/help'
#bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
#bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
I have tried examples from different libraries, but still no answer.
Any ideas?
It would be great if you could share a working example of Telegram "echo-bot" on pythonanywhere.com.
Thanks.
You should disable threading in the TeleBot constructor like this:
bot = telebot.TeleBot('YOUR_AUTHORIZATION_TOKEN', threaded=False)
I had the same issue and found a solution here:
https://www.pythonanywhere.com/forums/topic/9562/#id_post_40177
Threading is unavailable for free PythonAnywhere accounts.
Error in 17th line. return "ok" not in telegram_webhook function.
My goal is to create a persistent cookie on-the-fly by supplying user id & password and use that cookie in POST request using a session object. But below code returns below exception.
('Connection aborted.', error(54, 'Connection reset by peer'))
class CreatePersistentCookie(): """This class is created to generate a persistent cookie that can further be used through out session for all the service requests being executed"""
class CreatePersistentCookie():
"""This class is created to generate a persistent cookie that can further be
used through out session for all the service requests being executed"""
def __init__(self, headers, data, url, params, authserver):
self.headers = headers
self.data = data
self.url = url
self.params = params
self.authserver = authserver
def generateCookie(self):
with requests.session() as s:
reqsessionObj = s.post(self.authserver,params = self.params)
reqCookie = reqsessionObj.request.headers['Cookie'] # this returns the Cookie i need
regexObj = re.compile(r'act-uat=\S+') # this is my app specific pattern search that returns the exact cookie text i need.
matchObj = regexObj.search(reqCookie)
sessionCookie = matchObj.group()
self.headers['Cookie'] = sessionCookie # adding Cookie attribute in headers.
try:
r = s.post(self.url, data=json.dumps(self.data), headers=self.headers)
return r.raise_for_status()
except requests.exceptions.RequestException as err:
print err
def main():
# Defining the params variable. This contains authentication details such as user id,password & App id.
params = {"accountId": "John",
"accountPassword": "password",
"appIdKey": "5c9773e36fd6ea7cc2f9f8ffd9da3e3"
}
# Defining the authserver variable that contains the host details where authentication happens.
authserver = 'https://auth-uat.com/authenticate'
# creating a object cookieObj from class CreatePersistentCookie that returns persistent cookie.
#print cookies
headers = {'Content-Type': 'application/json;charset=UTF-8',
'Host':'service-uat1.com'}
data = {"appName":"abc","appKey":"abc","type":"jdbc","queryName":"xyz","version":"v1.2","useCache":"false","bindVars":[{"bindVarName":"In_dt","bindVarVal":"2014-05-13"},{"bindVarName":"In_Location","bindVarVal":"USA"}]}
url = 'https://uat1.com/gsf/abc/derf/abc/services/xyz'
cookieObj = CreatePersistentCookie(headers, data, url, params, authserver)
cookieObj.generateCookie()
if __name__ == '__main__':
main()
Connection reset by peer indicates that the server you're trying to connect to is refusing the connection. Normally, there is a handshake between your computer and the website's server, but here for some reason, the server is refusing the connection. I would use the urllib, requests, mechanize, and cookielib modules (some of which only work in Python 2.7). Then, using urllib you can attach a user-client header like Firefox, which will trick the browser into accepting the connection because they will think you are a regular person surfing the web, not a robot.
Try the below command in terminal it worked for me
pip install requests[security]
In my case it worked from Postman but not from python script. Restarting the system fixed it.
while using beaker session, i came across to use same session object along the whole application.
I came through this url: Bottle.py session with Beaker
But, still i am getting 'KeyError' when i am trying to access the save session value in one function by another function.
my rest.py file looks like:
import bottle
from bottle import route,default_app
from beaker.middleware import SessionMiddleware
app = bottle.default_app()
#bottle.hook('before_request')
def setup_request():
request.session = request.environ['beaker.session']
#app.route('/login')
def login():
request.session['uname'] = 'user'
#app.route('/logout')
def logout():
print request.session['uname']
# expecting to print user
session_opts = {
'session.type': 'file',
'session.data_dir': '/tmp/',
'session.cookie_expires': True,
}
app = SessionMiddleware(bottle.default_app(),session_opts)
I have mentioned the SessionMiddleware at the end as im getting errors with the help of this link https://groups.google.com/forum/#!topic/bottlepy/m0akSbWRpZg
But when i am accessing request.session in the logout function i am getting
'KeyError': Uname not found
can any one give clear example of how to adjust the code inorder to maintain same session in whole application.
I am trying to set up a basic navigation in pyramid (1.4a1). According to the tutorial given at tutorial groupfinder is called once we remember after login is successful. This works on my local but when I try the same on a server it doesn't call groupfinder at all and keeps looping between the two routes. Here's my code snippet:
from pyramid.security import remember, forget, authenticated_userid
from pyramid.httpexceptions import HTTPFound, HTTPForbidden
from pyramid.threadlocal import get_current_registry
from pyramid.url import route_url
from pyramid.view import view_config, forbidden_view_config
#view_config(route_name='index',
renderer='templates:templates/index.pt',
permission='Authenticated')
def index_view(request):
try:
full_name = (request.user.first_name + ' ' + request.user.last_name)
except:
full_name = "Anonymous"
return {"label": label, "user_name": full_name}
#forbidden_view_config()
def forbidden(request):
if authenticated_userid(request):
return HTTPForbidden()
loc = request.route_url('login.view', _query=(('next', request.path),))
return HTTPFound(location=loc)
#view_config(route_name='login.view')
def login_view(request):
came_from = request.route_url('index')
#perform some authentication
username = 'xyz'
if authenticate(username):
headers = remember(request, username)
#user was authenticated. Must call groupfinder internally and set principal as authenticated.
return HTTPFound(location=came_from, headers=headers)
else:
return HTTPForbidden('Could not authenticate.')
return HTTPForbidden('Could not authenticate.')
Also, my ACL looks like:
__acl__ = [(Allow, Authenticated, 'Authenticated'), DENY_ALL].
Can someone tell my why groupfinder is not being called? Is the request routing happening properly? Also, the same code works on my local setup fine. So there is no problem in groupfinder or ACL authorization settings.
Thanks much!
After lot of debugging and digging up I found out that the issue was very simple. Don't know the reason for the behavior but I had added secure = True attribute when calling AuthTktAuthenticationPolicy(). When I removed this attribute, it started working.