python oath2 example with fastapi - python

I found an example from this web site,
https://blog.hanchon.live/guides/google-login-with-fastapi/
is there a similar example for microsoft AD authentication?
import os
import starlette
from starlette.config import Config
from authlib.integrations.starlette_client import OAuth
# OAuth settings
GOOGLE_CLIENT_ID = os.environ.get('GOOGLE_CLIENT_ID') or None
GOOGLE_CLIENT_SECRET = os.environ.get('GOOGLE_CLIENT_SECRET') or None
if GOOGLE_CLIENT_SECRET is None or GOOGLE_CLIENT_ID is None:
raise BaseException('Missing env variables')
# setup OAuth
config_data = {'GOOGLE_CLIENT_ID': GOOGLE_CLIENT_ID,
'GOOGLE_CLIENT_SECRET': GOOGLE_CLIENT_SECRET}
starlette_config = Config(environ=config_data)
oauth = OAuth(starlette_config)
oauth.register(
name='google',
server_metada_url='https://accounts.google.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid email profile'}
)
The output is:]On instance['id']:
'10'
Given JSON data is InValid
Traceback (most recent call last):
File "sample3.py", line 38, in
invalidjsonData = json.loads(
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/json/init.py", line 357, in loads
return _default_decoder.decode(s)
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 353, in raw_decode]
user_schema is:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "User",
"description": "A user request json",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a user",
"type": "integer"
},
"name": {
"description": "Name of the user",
"type": "string"
},
"contact_number": {
"type": "number"
}
},
"required": ["id", "name", "contact_number"]
}

an example from github:
import json
from fastapi import FastAPI
from starlette.config import Config
from starlette.requests import Request
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import HTMLResponse, RedirectResponse
from authlib.integrations.starlette_client import OAuth, OAuthError
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="!secret")
config = Config('.env')
oauth = OAuth(config)
CONF_URL = 'https://accounts.google.com/.well-known/openid-configuration'
oauth.register(
name='google',
server_metadata_url=CONF_URL,
client_kwargs={
'scope': 'openid email profile'
}
)
#app.get('/')
async def homepage(request: Request):
user = request.session.get('user')
if user:
data = json.dumps(user)
html = (
f'<pre>{data}</pre>'
'logout'
)
return HTMLResponse(html)
return HTMLResponse('login')
#app.get('/login')
async def login(request: Request):
redirect_uri = request.url_for('auth')
return await oauth.google.authorize_redirect(request, redirect_uri)
#app.get('/auth')
async def auth(request: Request):
try:
token = await oauth.google.authorize_access_token(request)
except OAuthError as error:
return HTMLResponse(f'<h1>{error.error}</h1>')
user = token.get('userinfo')
if user:
request.session['user'] = dict(user)
return RedirectResponse(url='/')
#app.get('/logout')
async def logout(request: Request):
request.session.pop('user', None)
return RedirectResponse(url='/')
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='127.0.0.1', port=8000)

Related

FastApi with Redis

im running a Redis server. and im gettig the folowwing error.
ERROR: Exception in ASGI application
what have i done wrong?
This is my code:
``
from fastapi import FastAPI
from models import Parks
import requests
import uvicorn
import json
import redis2
SERVER_URL = 'localhost'
SERVER_PORT = 8000
REDIS_SERVER = 'localhost'
REDIS_PORT = 6379
app = FastAPI()
#app.post("/api/v1/ru")
async def get_data(rub_post: Parks):
token = "**************"
url = "https://********************************/users/?filter=" + rub_post.car_number
headers = {"Content-Type": "application/json; charset=utf-8", "X-Access-Token": token}
response = requests.get(url, headers=headers)
j = response.json()
if not j['users']['count'] == 0:
note: str = j['users']['list'][0]['places'][0]['notes']
else:
return {"Answer": "car not found"}
if rub_post.parked_id in note:
return {"Answer": "found car"}
if "P" in note:
redis_cli = redis2.Redis(host=REDIS_SERVER, port=REDIS_PORT, db=0)
dict_f = {"carId": rub_post.car_number, "parkingTicketId": rub_post.parked_id,
"laneId": "cded89ec403083a31", "transactionId": "Invalid Parking",
"currency": "", "price": "", "userPn": "", "userEmail": "", "userName": "",
"companyName": "", "paymentMethod": [{"type": "", "amount": "", "id": ""}]
}
redis_cli.lpush('terminalToLprIsCarAuthorized', json.dumps(dict_f))
return {"Answer": "invalid car"}
if __name__ == '__main__':
uvicorn.run(app, host=SERVER_URL, port=SERVER_PORT)
``
still new to this and i cant find whats wrong. thanks for the helpers

How to catch HTTPException with this logging module?

I'm use the fastapi_log library( https://pypi.org/project/fastapi-log/ ) ( https://github.com/12345k/fastapi-log ) in my FastAPI project.
It works great to log request and responses(return statements), but it does not log HTTPExceptions(which I used in some parts of the program instead of return statements).
How can I edit the source code for log_request.py ( https://github.com/12345k/fastapi-log/blob/main/fastapi_log/log_request.py ) to be able to log responses from HTTPExceptions as well ?
The log_request.py source code :
import re
import time
from starlette.requests import Request
from typing import Callable
from fastapi import HTTPException, Request, Response
import time
import os
import uuid
import json
from user_agents import parse
from urllib.parse import parse_qs
from datetime import datetime
from fastapi.routing import APIRoute
import sqlite3
path = os.path.abspath(os.path.dirname(__file__))
path = path.replace("__init__.py","")
conn = sqlite3.connect(path+'/database/test.db')
conn.execute('''CREATE TABLE IF NOT EXISTS REQUEST
(ENDPOINT TEXT NOT NULL,
TYPE INT NOT NULL,
BODY CHAR(50),
UUID REAL,
TIME TEXT NOT NULL);''')
class LoggingRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
try:
uuid_str = str(uuid.uuid4())
header = dict(request.headers)
if "uuid" in header.keys():
uuid_str = header["uuid"]
user_agent = parse(request.headers["user-agent"])
browser=user_agent.browser.version
if len(browser) >=2:
browser_major,browser_minor = browser[0],browser[1]
else:
browser_major,browser_minor =0,0
user_os=user_agent.os.version
if len(user_os) >=2:
os_major,os_minor = user_os[0],user_os[1]
else:
os_major,os_minor =0,0
# Request json
body = await request.body()
if len(body)!=0:
body=json.loads(body)
else:
body=""
request_json = {
"type":"request",
"uuid":uuid_str,
"env": os.environ.get("ENV"),
"region": os.environ.get("REGION"),
"name": os.environ.get("NAME"),
"method": request.method,
"useragent":
{
"family": user_agent.browser.family,
"major": browser_major,
"minor": browser_minor,
"patch": user_agent.browser.version_string,
"device": {
"family": user_agent.device.family,
"brand": user_agent.device.brand,
"model": user_agent.device.model,
"major": "0",
"minor": "0",
"patch": "0"
},
"os": {
"family": user_agent.os.family,
"major": os_major,
"minor": os_minor,
"patch": user_agent.os.version_string
},
},
"url": request.url.path,
"query": parse_qs(str(request.query_params)),
"body":body,
"length": request.get("content-length"),
'ts': f'{datetime.now():%Y-%m-%d %H:%M:%S%z}'
}
print(json.dumps(request_json,indent=4))
start_time = time.time()
response = await original_route_handler(request)
process_time = (time.time() - start_time) * 1000
formatted_process_time = '{0:.2f}'.format(process_time)
metrics_json = {
"type": "metrics",
"uuid": uuid_str,
"env": os.environ.get("ENV"),
"region": os.environ.get("REGION"),
"name": os.environ.get("NAME"),
"method": request.method,
"status_code": response.status_code,
"url": request.url.path,
"query": parse_qs(str(request.query_params)),
"length": response.headers["content-length"],
"latency": formatted_process_time,
"ts": f'{datetime.now():%Y-%m-%d %H:%M:%S%z}'
}
print(json.dumps(metrics_json,indent=4))
try:
if len(request_json) !=0:
url = str(request_json["url"]).replace("/","")
method=request_json["method"]
body=str(request_json["body"])
uuid_str=request_json["uuid"]
time_value = request_json["ts"]
# print(body)
conn.execute(f"INSERT INTO REQUEST VALUES (?,?,?,?,?)",( url , method, body, uuid_str,time_value ))
# VALUES ({request_json["url"].replace("/","")}, {request_json["method"]},"str(request_json[body])", {request_json["uuid"]} )""");
conn.commit()
except Exception as exc:
print(exc)
pass
return response
except Exception as exc:
body = await request.body()
detail = {"errors": str(exc), "body": body.decode("utf-8")}
print(detail)
raise HTTPException(status_code=422, detail=detail)
return custom_route_handler

In FastAPI Getting 'Not authenticated' Error after authenticate

File dir
fastapi_jwt
.env
main.py
app
api.py
model.py
auth
auth_bearer.py
auth_handler.py
fastapi_jwt/.env
secret=please_please_update_me_please
algorithm=HS256
fastapi_jwt/main.py
import uvicorn
if __name__ == "__main__":
uvicorn.run("app.api:app", host="127.0.0.1", port=8000, reload=True)
fastapi_jwt/app/api.py
from fastapi import FastAPI, Body, Depends
from starlette.responses import HTMLResponse
from app.model import PostSchema, UserSchema, UserLoginSchema
from app.auth.auth_bearer import JWTBearer
from app.auth.auth_handler import signJWT
app = FastAPI()
#app.get("/", tags=["root"])
async def read_root():
return {"message": "Welcome to your blog!."}
from app.model import PostSchema
posts = [
{
"id": 1,
"title": "Pancake",
"content": "Lorem Ipsum ..."
}
]
users = []
#app.get("/posts", tags=["posts"])
async def get_posts() -> dict:
return { "data": posts }
#app.get("/posts/{id}", tags=["posts"])
async def get_single_post(id: int) -> dict:
if id > len(posts):
return {
"error": "No such post with the supplied ID."
}
for post in posts:
if post["id"] == id:
return {
"data": post
}
#app.get("/post", dependencies=[Depends(JWTBearer())], tags=["posts"])
#app.post("/post", dependencies=[Depends(JWTBearer())], tags=["posts"])
async def add_post(post: PostSchema) -> dict:
post.id = len(posts) + 1
posts.append(post.dict())
return {"result":"Post added successfully"}
#app.post("/user/signup", tags=["user"])
async def create_user(user: UserSchema = Body(...)):
users.append(user) # replace with db call, making sure to hash the password first
return signJWT(user.email)
def check_user(data: UserLoginSchema):
for user in users:
if user.email == data.email and user.password == data.password:
return True
return False
#app.post("/user/login", tags=["user"])
async def user_login(user: UserLoginSchema = Body(...)):
if check_user(user):
return signJWT(user.email)
return {
"error": "Wrong login details!"
}
fastapi_jwt/app/model.py
from pydantic import BaseModel, Field, EmailStr
class PostSchema(BaseModel):
id: int = Field(default=None)
title: str = Field(...)
content: str = Field(...)
class Config:
schema_extra = {
"example": {
"title": "Securing FastAPI applications with JWT.",
"content": "In this tutorial, you'll learn how to secure your application by enabling authentication using JWT. We'll be using PyJWT to sign, encode and decode JWT tokens...."
}
}
class UserSchema(BaseModel):
fullname: str = Field(...)
email: EmailStr = Field(...)
password: str = Field(...)
class Config:
schema_extra = {
"example": {
"fullname": "Abdulazeez Abdulazeez Adeshina",
"email": "abdulazeez#x.com",
"password": "weakpassword"
}
}
class UserLoginSchema(BaseModel):
email: EmailStr = Field(...)
password: str = Field(...)
class Config:
schema_extra = {
"example": {
"email": "abdulazeez#x.com",
"password": "weakpassword"
}
}
fastapi_jwt/app/auth/auth_bearer.py
from fastapi import Request, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from .auth_handler import decodeJWT
class JWTBearer(HTTPBearer):
def __init__(self, auto_error: bool = True):
super(JWTBearer, self).__init__(auto_error=auto_error)
async def __call__(self, request: Request):
credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
if credentials:
if not credentials.scheme == "Bearer":
raise HTTPException(status_code=403, detail="Invalid authentication scheme.")
if not self.verify_jwt(credentials.credentials):
raise HTTPException(status_code=403, detail="Invalid token or expired token.")
return credentials.credentials
else:
raise HTTPException(status_code=403, detail="Invalid authorization code.")
def verify_jwt(self, jwtoken: str) -> bool:
isTokenValid: bool = False
try:
payload = decodeJWT(jwtoken)
except:
payload = None
if payload:
isTokenValid = True
return isTokenValid
fastapi_jwt/app/auth/auth_handler.py
import time
from typing import Dict
import jwt
from decouple import config
JWT_SECRET = config("secret")
JWT_ALGORITHM = config("algorithm")
def token_response(token: str):
return {
"access_token": token
}
def signJWT(user_id: str) -> Dict[str, str]:
payload = {
"user_id": user_id,
"expires": time.time() + 600
}
token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
return token_response(token)
def decodeJWT(token: str) -> dict:
try:
decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
return decoded_token if decoded_token["expires"] >= time.time() else None
except:
return {}
I run 'main.py', the url
" http://127.0.0.1:8000/post " shows the output "{"detail":"Not authenticated"}".
So go to the url " http://127.0.0.1:8000/docs " for FastAPI -Swagger UI interface like
this.
Then I signup and login to get the jwt token and use that token to authenticate, then go to url
" /post " in FastAPI -Swagger UI and execute to get the output {"result": "Post added successfully"}.
But in " http://127.0.0.1:8000/post " got an error and show the same ouput "{"detail":"Not authenticated"}"

Able to get response but not in display

I wrote a python code for the dialog flow using the flask and webhook. I am able to get the response but it not displayed in the dialog flow. This code running perfectly.
CODE:
# import os
import json
# import urllib
import datetime
from config import Configuration
from swe_commands import SweCommands
from flask import Flask, request, make_response
# Flask application should start in global layout
app = Flask(__name__)
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
print "Request:"
print json.dumps(req, indent=1)
res = make_webhook_result(req)
res = json.dumps(res, indent=1)
print "Response:"
print res
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
def make_webhook_result(req):
# if req.get("queryResult").get("action") != "nakshatra":
# return {}
swe_path = Configuration.swe_path()
date_and_time = str(datetime.datetime.now())[:19]
panchang_dictionary = SweCommands.find_panchang(swe_path, date_and_time)
result = req.get("queryResult")
parameters = result.get("parameters")
angam = parameters.get("nakshatra")
nakshatra = panchang_dictionary[angam]
speech = "Current nakshatra is %s" % nakshatra
source = "Panchangam"
output = {'speech': speech, "displayText": speech, "source": source}
return output
if __name__ == '__main__':
port = 5000
print "Starting app in port %s" % port
app.run(debug=True, port=port, host='127.0.0.1')
REQUEST:
**{
"queryResult": {
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"allRequiredParamsPresent": true,
"parameters": {
"nakshatra": "nakshatra"
},
"languageCode": "en",
"intentDetectionConfidence": 0.6725314,
"action": "nakshatra",
"intent": {
"displayName": "PanchangFind",
"name": "projects/my-project-1536557558293/agent/intents/6d1d46bf-3787-48cd-9b45-0766d5f2b107"
},
"queryText": "What is nakshatra"
},
"originalDetectIntentRequest": {
"payload": {}
},
"session": "projects/my-project-1536557558293/agent/sessions/08857865-1d08-2eef-5d4f-83b92107f09b",
"responseId": "2137da9d-23a9-4735-aec2-7adb7ae52d85-9cc28bb4"
}**
RESPONSE:
**{
"displayText": "Current nakshatra is Shravana",
"speech": "Current nakshatra is Shravana",
"source": "Panchangam"
}**
But it not get displayed in the dialog flow panel? Whether I have to set any parameters for dialog flow panel to receive the response in a dialog flow. Please let me know.
I got an answer to this. When we use V1 in dialog flow, the response key is displayText. But in V2 the response key is fulfillmentText. When I added the response key in this name it able to detect the output.

Change JSON-RPC RESPONSE

I am using ODOO 11.0
how to return simple JSON object without JSON-RPC additional parameters
Here is my odoo controller code:
#http.route('/userappoint/webhook_test/',type='json', auth='public',method=['POST'], csrf=False,website=True)
def webhook_test(self,**kw):
response = {
'speech' : 'hello my name is shubham',
'displayText' : 'hello testing',
'source' : 'webhook'
}
return response
And I am getting this result :
{
"result": {
"displayText": "hello testing",
"source": "webhook",
"speech": "hello my name is shubham"
},
"id": "6eaced3e-6b0d-4518-9710-de91eaf16dd9",
"jsonrpc": "2.0"
}
But I need this :
{
"speech": "hello my name is shubham",
"displayText": "hello testing",
"source": "webhook"
}
Any help to point me in the right direction?
Thanks
Works on Odoo11. Just edit below portion of the function _json_response defined at odoo/odoo11/odoo/http.py near about line no : 621-630 as below & Restart the odoo service.
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
to new:
def _json_response(self, result=None, error=None):
response = {}
if error is not None:
response = error
if result is not None:
response = result
Then, restart the odoo service
Place the following code in any of your controller before you initialize the controller class
from odoo import http
from odoo.http import request, Response, JsonRequest
from odoo.tools import date_utils
class JsonRequestNew(JsonRequest):
def _json_response(self, result=None, error=None):
# response = {
# 'jsonrpc': '2.0',
# 'id': self.jsonrequest.get('id')
# }
# if error is not None:
# response['error'] = error
# if result is not None:
# response['result'] = result
responseData = super(JsonRequestNew, self)._json_response(result=result,error=error)
response = {}
if error is not None:
response = error
if result is not None:
response = result
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
class RootNew(http.Root):
def get_request(self, httprequest):
# deduce type of request
jsonResponse = super(RootNew, self).get_request(httprequest=httprequest)
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequestNew(httprequest)
else:
return jsonResponse
http.root = RootNew()
class MyController(http.Controller):

Categories

Resources