Using Keycloak with python and flask for identity and access management.
here's the part of the code where the issue occurs:
from keycloak import Client
app = flask(__name__)
kc=Client()
.
.
.
app.route('/login')
def login():
.
.
.
access_token = kc.access_token
userinfo = kc.fetch_userinfo(access_token) #the main issue
session['user'] = userinfo
return jsonify(userinfo)
if __name__ == "__main__":
app.run()
so with the "userinfo" part, the error occurs saying:
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: http://localhost:8080/auth/realms/linkedin_login/protocol/openid-connect/userinfo
if you have experience with keycloak, do you know if anything has to be altered to authorize in the use of userinfo in keycloak?
Thank you!
if your Client() from Keycloak is a KeycloakAdmin instance
(i'm using https://pypi.org/project/python-keycloak/ )
then the error probably comes from trying to access user information using administration credentials.
if your Client() is a KeycloakOpenID again from (https://pypi.org/project/python-keycloak/ ) then it might be a permission problem. You can check in the keycloak interface that the User you set up has Role Mapping>realm-management>realm-admin set (or something equivalent depending of the rights you want to give him).
in any case, a very usefull documentation can be found at https://www.keycloak.org/docs/latest/server_admin/index.html
last and this might be off-topic but if you plain to access specific custom fields from the user infos, the Client Scopes panel will help you add them.
Related
I am trying to get my google authentication working on a Django app that is requesting Gmail and Calendar data. I have set up the oAuth API in the Google developer console and linked it with my project, and I've triple-checked that my redirect URI perfectly matches that in the code (No errors with HTTP vs. HTTPS nor any inconsistencies with the slashes). I made sure that my key, secret key, ClientID, and Client Secret are all configured and identical in my Django app's admin page. I have followed many youtube tutorials and searched other questions on stack overflow but Authentication is still not working. I am getting an Error 400: redirect_uri_mismatch. Even though I have checked many times to confirm that they are the same.
From all the tutorials, I have learned that there are two main origins for this error:
Server sided (can be fixed in the cloud hosting developer console)
Client sided (can be fixed by altering the code)
Both of these errors have their own individualized messages saying what type of mismatch it is.
Mine, however, says this: You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy. \n\nIf you're the app developer, register the redirect URI in the Google Cloud Console.
Here is a photo of the error
[![Google Authentication error message][1]][1]
from django.shortcuts import render, redirect
from django.http import HttpRequest
from google_auth_oauthlib.flow import Flow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from .models import CredentialsModel
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
#Scopes are what we should be allowed to access
SCOPES = ['https://mail.google.com/', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'openid']
"""
IF HAVING ISSUES WITH ANON USER:
Make sure you are on 127.0.0.1:8000, not localhost, both from the test-page and
the callback page. For some reason they are treated as different sessions and thus will have
issues maintaining a logged in user
"""
def oauth2callback(request):
activeUser = request.user
#URL is what we need to use for authentication
authorization_response = request.build_absolute_uri()
flow = Flow.from_client_secrets_file(
settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
scopes=SCOPES,
#This is where we are redirected after authentication
redirect_uri='http://127.0.0.1:8000/google/oauth2callback')
#Now get proper token
flow.fetch_token(authorization_response = authorization_response)
#print(request.user)
#Now save in our database
#print(flow.credentials)
try :
my_credential = CredentialsModel.objects.get(pk = activeUser)
except ObjectDoesNotExist:
CredentialsModel.objects.create(id = activeUser, credential = flow.credentials)
else:
my_credential.credential = flow.credentials
my_credential.save()
return redirect(flow.redirect_uri) #activeUser.get_absolute_url())
[1]: https://i.stack.imgur.com/2HXGP.png
google's documentation is not clear on this part (probably a bug on google's end too):
go to your GCP console, under OAuth consent screen, when the Publishing status is In production, we can still put http://localhost:8080/oauth-authorized/google under the Authorized redirect URIs without triggering the red error message saying Invalid Redirect. However, it doesn't work unless the app is in Testing status.
so in order to test your app at http://127.0.0.1:8000, you need to bring your GCP app to Testing status
hey i was dealing with this problem in ASP.Net MVC,
i think the reason would be the same in php but anyways,
Make sure to copy that url in ur below img to Authorized redirect URIs in OAuth 2.0 Client IDs in Google cloud console.
Check if you are logged in to your google account.
I was using google chrome browser and turns out I was logged out of Gmail as the session expired and when I logged into Gmail and the issue was resolved
In my case, it working in development environment and not in production environment. Enabling API KEY for production resolved the issue.
Copy the url that comes with the error message you get and add it to the authorize redirect uris in your google cloud console
In my case I needed to change my redirect URI from
https://{{my-url}}/google/endpoint
To
https://www.{{my-url}}/google/endpoint
So, I am trying to understand the digest authentication implementation with Python- Flask.
I did a simple test, I took the below code from the documentation,
from flask import Flask
from flask_httpauth import HTTPDigestAuth
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth()
users = {
"john": "hello",
"susan": "bye"
}
#auth.get_password
def get_pw(username):
if username in users:
return users.get(username)
return None
#app.route('/', methods=['HEAD'])
#auth.login_required
def index():
return "Hello, %s!" % auth.username()
if __name__ == '__main__':
app.run()
The code runs.
I paste this URL(host:port) in same in POSTMAN(head method), it always returns 401.
I am lost and am trying to get it work.
What am I doing wrong here?
OK so here is what the problem is, the URL works fine in the browser but not in POSTMAN.
This is happening due to the name resolution in your case, e.g. 9mxlhm2
You need to make sure that it resolved that name, try and see if you can ping that name mentioned or else easiest fix just use **0.0.0.0**, if this is local.
Make sure the authorization info is mentioned when you are doing a HTTP request via postman. Under the request section there will be a Authorization section. See this image as an example.
To reproduce the problem i used localhost but it didn't work and it gives me an error with 401, as soon as i try 0.0.0.0 in the GET request via postman, it starts to work again. Hope this fixes your problem. Although the hostname for me works(as in my own hostname, e.g rajlocal)
I'm trying to create a webhook for a folder on Box such that when the file is uploaded I get a notification.
from boxsdk import OAuth2, Client
auth = OAuth2(
client_id='xxxxxxxxxxxxo',
client_secret='xxxxxxxxxxxxxxxxh',
access_token='xxxxxxxxxMj2',
)
client = Client(auth)
folder = client.folder(folder_id='1')
webhook = client.create_webhook(folder, ['FILE.UPLOADED'], <HTTPS_URL>)
print('Webhook ID is {0} and the address is {1}'.format(webhook.id, webhook.address))
The Error:
Status: 403 Code: access_denied_insufficient_permissions
I also tried using the JWTAuth method and generated a Public/Private key pair
from boxsdk import JWTAuth, Client
config = JWTAuth.from_settings_file('./config_box_demo.json')
client = Client(config)
folder = client.folder(folder_id='1')
webhook = client.create_webhook(folder, ['FILE.UPLOADED'], <HTTPS_URL>)
print('Webhook ID is {0} and the address is {1}'.format(webhook.id, webhook.address))
But it displays the same error.
Things I have already done:
Enabled all application scopes (include 'Manage Webhooks')
Activated 'Perform Actions As Users' and 'Generate User Access Token'
Authorised the App from Admin Console
Any help/tips would be appreciated.
Also, does it show the same error if theres an issue with the HTTPS URL?
Two things might be causing an issue here. Firstly, make sure you application is configured to have the scope enabled to create webhooks.
Webhook configuration screen
Secondly, it is important that the user who the access token belongs to actually has access to the folder you are trying to add a webhook to. In the case of a JWT authenticated app, the user is actually a service account that does not actually have access to your (a regular user) files and folders. You can read more on our user model here.
https://developer.box.com/en/guides/authentication/user-types/
The App is public and it has been granted the appropriate permissions:
Display of app permissions
My logged in user is an administrator to the App: Display of user permissions
The code is as follows:
import facebook
import warnings
# Hide deprecation warnings. The facebook module isn't that up-to-date (facebook.GraphAPIError).
warnings.filterwarnings('ignore', category=DeprecationWarning)
# Parameters of your app and the id of the profile you want to mess with.
FACEBOOK_APP_ID = 'SECRET'
FACEBOOK_APP_SECRET = 'SECRET'
FACEBOOK_PROFILE_ID = 'SECRET'
fb_api=facebook.GraphAPI()
api_token=fb_api.get_app_access_token(app_id=FACEBOOK_APP_ID, app_secret=FACEBOOK_APP_SECRET, offline=True)
graph = facebook.GraphAPI(api_token)
# Try to post something on the wall.
try:
fb_response = graph.put_object(parent_object=FACEBOOK_PROFILE_ID, connection_name='feed',
message='Hello, world')
print(fb_response)
except facebook.GraphAPIError as e:
print('Something went wrong:', e.type, e.message)
This code fails with the error message:
OAuthException (#200) Requires either publish_actions permission, or manage_pages and publish_pages as an admin with sufficient administrative permission
I am certain at this point I have followed all the things I've read in any other post. The docs they have for the sdk are here.
A bunch of stuff is just not working so here's what I did. I created a link and then I just click on it:
https://developers.facebook.com/docs/php/howto/example_facebook_login
This is super duper easy with something like laravel or lumen. You just make a controller and a route that points to it.
I upload the token to a local consul instance so I can access it across a variety of micro services.
I use puppeteer to login to facebook via my stub site and then I have a token and login cookies too.
we found facebook change the permission requirements for posting to pages from just manage_pages to require both manage_pages and publish_pages. by granting both permissions we solved our problem
in essence we had to pass the client to
https://www.facebook.com/dialog/oauth?client_id=client_id&redirect_uri=redirect_uri&scope=manage_pages,publish_pages&response_type=code%20token&enable_profile_selector=1&profile_selector_ids=pageid
I am trying to obtain a token from Azure AD from Python client application. I want users to seamlessly authenticate with just a username and password (client_id / secret will be embedded in the app). I registered my app and given it all permissions and hit the "grant permissions" button in the new portal according to this post:
The user or administrator has not consented to use the application - Send an interactive authorization request for this user and resource
I am sending an http post to:
https://login.microsoftonline.com/{tenant_id}/oauth2/token
with the following data:
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
body = "resource={0}&grant_type=password&username={1}&password={2}&client_id={3}&client_secret={4}&scope=openid".format(app_id_uri,user,password,client_id,client_secret)
I cannot seem to get past this error no matter what I try:
b'{"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID \'078c1175-e384-4ac7-9116-efbebda7ccc2\'. Send an interactive authorization request for this user and resource.
Again, my goal:
User enters user / pass and nothing else. App sends user / pass / client_id / client_secret, obtains token.
According to your comment:
The message I'm receiving says to do an interactive request but that is exactly what I'm trying to avoid because this is a python app with no web browser and I'm trying to avoid complexity.
I think you want to build a daemon app or an app only application integrating with Azure AD. You can refer to https://graph.microsoft.io/en-us/docs/authorization/app_only for the general introduction.
Furthermore, you can leverage the ADAL for Python to implement this functionality with a ease. Also, you can refer to client_credentials_sample.py for a quick start.
You should try logging in as an admin to be able to give consent to use the application on your tenant at all.