How to implement third party authentication in gramex - python

I am trying to build a simple gramex application. where i need to authorize user from linkedin, outlook, Github & gmail.
Please share some code snippet.

url:
auth/github:
pattern: /$YAMLURL/github
handler: OAuth2
kwargs:
# Create app at https://code.gramener.com/admin/applications/
client_id: 'YOUR_APP_CLIENT_ID' # https://github.com/settings/connections/applications/
client_secret: 'YOUR_APP_SECRET_ID'
authorize:
url: 'https://github.com/login/oauth/authorize'
scope: [repo, gist, user]
access_token:
url: 'https://github.com/login/oauth/access_token'
body:
grant_type: 'authorization_code'
user_info:
url: 'https://api.github.com/user'
headers:
Authorization: 'Bearer {access_token}'
redirect:
query: next
header: Referer
url: .
This is the code snippet for Github with OAuth2
https://docs.github.com/en/developers/apps/building-oauth-apps
client_id: Create an app with the OAuth2 provider to get this ID
client_secret: Create an app with the OAuth2 provider to get this ID
authorize: Authorization endpoint configuration
url: Authorization endpoint URL
scope: an optional a list of scopes that determine what you can access
access_token: Access token endpoint configuration
url: Access token endpoint URL
user_info: Optional user information API endpoint
url: API endpoint to fetch URL
headers: optional dict containing HTTP headers to pass to user info URL. e.g.
Authorization: 'Bearer {access_token}'. Default: {User-Agent: Gramex/}

Related

Fast API, test endpoints by Postman

I want to test some endpoints, in particular sign-in endpoint by using Postman. But every time I send request I get en error whether 422 or 401 (the login and password are correct).
Is it pissible to test sign-in with Postman?
router = APIRouter(
prefix='/auth'
)
#router.post('/sign-in', response_model=Token)
def sign_in(form_data: OAuth2PasswordRequestForm = Depends(), service: AuthService = Depends()):
return service.authenticate_user(form_data.username, form_data.password)

How to authorize OpenAPI page from an API

I'm building a FastAPI application with OAuth2 and JWT authentication. I've got two endpoints that create the JWT token. The first is hidden from the OpenAPI page but is used by the page Authorize button. The second does the same functionality but is available to the users as an API endpoint.
If the user uses the page Authorize button and successfully gets authenticated, the rest of the API endpoints on the OpenAPI page become accessible.
If the user uses the API get_token endpoint only, they get a valid JWT token, which can be used with the protected API's, but the OpenAPI page isn't authenticated.
How can I use the token returned by the public get_token API endpoint to authenticate the OpenAPI page as if the user went through OpenAPI provided Authorize functionality?
When using the Authorize button, the Authorization header with the token in it is automatically sent in every subsequent request you make to the FastAPI backend, and hence, the user gets authenticated.
Using your get_token endpoint, users will obtain the token as a response, and have to manually place it in the headers for every request they make. As described in this answer, as Authorization is a reserved header in Swagger UI/OpenAPI specification, you either have to define a Header parameter in your endpoints with a different name, e.g., token (where users will place the token value), or use the Authorize button, which will automatically add it for every request to any endpoint of your server.
Another option would be to create an httponly cookie (using the Set-Cookie header) with the token inside once the user calls the get_token endpoint, and return the cookie with the Response object, as described here and here. The browser will store the cookie sent by the server and will send it back with every request made to the server inside a Cookie HTTP header (read more about cookies here). Inside the endpoint, you can then retrieve the token using the Request object directly, for example, request.cookies.get('token'), or by defining a cookie parameter for it.

Bearer Token extraction from request django

If I have a post request with this JSON :
{
"user_id":230,
"name":"Anthony"
}
I can extract the name by :
name = json.loads(request.body).get("name")
Now I have a GET request in which I am passing bearer token.
How should I extract it in Django?
You can access the authorization header with request.META['HTTP_AUTHORIZATION']

Flask Restful with PyJWT Authentication

Background:
I'm trying to prototype a quick token-based authentication using Flask-Restful and PyJWT. The idea is that I will have a form with email and password and when user clicks submit, it will generate a token and save it in client side browser and use it in any subsequent requests until the token expires.
Trouble
In my prototype, I was able to create a token using JWT but I don't have an idea of how to pass the JWT into a subsequent request. When I do it in the Postman, it works because I can specify the Authorization header with token in there. But when I login in through UI and token is generated, I do not know how to pass the token generated into a subsequent request (/protected) by making the token persists in the header until it expires. Currently when I login from UI and go to /protected, the Authorization header is missing in /protected header.
Code
class LoginAPI(Resource):
# added as /login
def get(self):
"""
renders a simple HTML with email and password in a form.
"""
headers = {'Content-Type': 'text/html'}
return make_response(render_template('login.html'), 200, headers)
def post(self):
email = request.form.get('email')
password = request.form.get('password')
# assuming the validation has passed.
payload = {
'user_id': query_user.id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=10)
}
token = jwt\
.encode(payload, current_app.config['JWT_SECRET'], current_app.config['JWT_ALGORITHM'])\
.decode('utf-8')
# Is below the right way to set the token into header to be used in subsequent request?
# request.headers.authorization = token
# when {'authorization': token} below as a header, the header only shows up for /login not for any subsequent request.
return make_response({'result': 'success', 'token': token}, 200, {'authorization': token} )
class ProtectedAPI(Resource):
#check_auth
def get(self):
return jsonify({'result': 'success', 'message': 'this is a protected view.'})
# decorator to check auth and give access to /protected
def check_auth(f):
#wraps(f)
def authentication(*args, **kws):
# always get a None here.
jwt_token = request.headers.get('authorization', None)
payload = jwt.decode(jwt_token, 'secret_key', algorithms='HS512'])
# other validation below skipped.
return f(*args, **kws)
return authentication
To persist the access_token you have to store on the client and pass it into your header every time you call your backend and check the authenticity of the token every time.

How to use TokenAuthentication for API in django-rest-framework

I have a django project, using django-rest-framework to create api.
Want to use token base authentication system so api call for (put, post, delete) will only execute for authorized user.
I installed 'rest_framework.authtoken' and created token for each users.
So, now from django.contrib.auth.backends authenticate, it returns user, with auth_token as attribute. (when loged in successfully).
Now my question is how can I send the token with post request to my api and
at api side how can I verify if token is valid and belongs to the correct user?
Are there any methods in app rest_framework.authtoken to validate given user and its token?
not found this very useful!
Update (changes I made):
Added this in my settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
Also sending Token in my header but its still not working:
if new_form.is_valid:
payload= {"createNewUser":
{ "users": request.POST["newusers"],
"email": request.POST["newemail"]
}
}
headers = {'content-type' : 'application/json',
'Authorization': 'Token 6b929e47f278068fe6ac8235cda09707a3aa7ba1'}
r = requests.post('http://localhost:8000/api/v1.0/user_list',
data=json.dumps(payload),
headers=headers, verify=False)
"how can I send the token with post request to my api"
From the docs...
For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
"at api side how can I verify if token is valid and belongs to the correct user?"
You don't need to do anything, just access request.user to return the authenticated user - REST framework will deal with returning a '401 Unauthorized' response to any incorrect authentication.
To answer the first half of your question:
how can I send the token with post request to my api
You can use the Python requests library. For the django-rest-framework TokenAuthentication, the token needs to be passed in the header and prefixed by the string Token (see here):
import requests
mytoken = "4652400bd6c3df8eaa360d26560ab59c81e0a164"
myurl = "http://localhost:8000/api/user_list"
# A get request (json example):
response = requests.get(myurl, headers={'Authorization': 'Token {}'.format(mytoken)})
data = response.json()
# A post request:
data = { < your post data >}
requests.post(myurl, data=data, headers={'Authorization': 'Token {}'.format(mytoken)})
I finally have the django "rest-auth" package working for token authentication.
If this helps, here is the client-side jQuery code that worked for me, after you successfully log in and receive the "auth_token":
var user_url = {API URL}/rest-auth/login
var auth_headers = {
Authorization: 'Token ' + auth_token
}
var user_ajax_obj = {
url : user_url,
dataType : 'json',
headers: auth_headers,
success : function(data) {
console.log('authorized user returned');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log('error returned from ' + user_url);
}
};
$.ajax(
user_ajax_obj
);
If you are using coreapi. To add the Authorisation you do
import coreapi
auth = coreapi.auth.TokenAuthentication(scheme='Token', token=token_key)
Then you can do
client = coreapi.Client(auth=auth)
response = client.get(my_url)

Categories

Resources