Comments (5)
You can find one approach (it might not be the best) in an example we did with pyOIDC and Flask.
It uses Flask's Blueprint concept to let handle Flask handle the routing.
The Blueprint expects a Provider instance which it then delegates all requests to. Then you can register the Blueprint with the Flask app instance.
Regarding the interface for the object used as cdb
(client db) for the Provider, and for the object used as db
parameter for the SessionDB
: your persistence layer must present a dictionary-like interface, i.e. __getitem__
, __setitem__
, __contains__
.
from pyoidc.
Do I still need to create a Provider instance?
Ya. I essentially have something liek:
myproject/provider.py
class MyProvider(Provider):
# Override some methods like https://github.com/rohe/pyoidc/issues/145
pass
def provider_from_config(config):
# Get `config` from a config file, flags, env variables, settings.py or something
# Using things from config dict (e.g. DATABASE_URL), construct
# issuer, session_db, client_db, authn_broker, UserInfo(users), authz, verify_client, None
# Pro tip: While devving you can use dicts for most of these
return MyProvider(issuer, session_db, client_db, authn_broker, userinfo, authz, verify_client, None)
Now you have a reliable factory for creating a Provider.
And then have my view layer proxy requests through to it?
Ya. The provider instance has methods for each of the logical operations the OP performs (token_endpoint, authorization_endpoint, etc). So you want to map your routes/urlconf/flaskything to those methods.
This is basically what these lines in op2 example do (we used this example as a starting point). My implementation is very similar to that op2 example, even using CherryPy routes even though I never had used that lib before. It's nice to be able to run your server process via a standard python script (if __name__ == '__main__'
) instead of having to use django runserver
. But I digress.
In django you could do something like this in a urls.py
from django.conf import settings
from django.conf.urls import url
from django.http import HttpResponse
from .provider import provider_from_config
provider = provider_from_config(settings.oidc_provider)
def oic_method_to_django_view_function(oic_method):
def view(request):
auth = request.META.get('Authorization')
oic_response = oic_method(request.body, authn=auth)
return HttpResponse(oic_response.message, status=oic_response.status)
return view
urlpatterns = [
url(r'^authorization/$', oic_method_to_django_view_function(provider.authorization_endpoint),
url(r'^token/$', oic_method_to_django_view_function(provider.token_endpoint),
# more that I forget, see op2 `ENDPOINTS`
]
It looks like the SessionDB and ClientDB are designed to be wrappers around a persistence layer? If I want to use an existing database, what interface does it need to present to those classes?
Basically they're identity maps. pyoidc treats them as dictionaries to get sessions-by-id or clients-by-id.
So might as well just use dicts while you're getting up and running. Like this is a valid ClientDB:
client = dict(client_id='my_client_id')
client_db = { client['client_id']: client }
Mongo is good at that type of K/V storage. But I'm using Postgres with something like (abridged)
import collections
class SQLClientDB(collections.MutableMapping):
def __init__(self, execute_sql):
self._execute_sql = execute_sql
def __getitem__(self, key):
result = self._execute_sql("SELECT * from clients where id=%s" % key);
if not result:
raise KeyError(key)
return result_to_client_dict(result)
def __setitem__(self, key, val):
result = self._execute_sql("UPDATE clients set blob=%s where id=%s" % (json.dumps(val), key))
# later
execute_sql = # idk use pycopg2 or something
client_db = SQLClientDB(execute_sql)
provider = MyProvider(client_db, **other_kwargs)
You can similarly create dict-like classes for the Client DB and Session DB that are parameterized not by an 'execute_sql' function in the constructor, but instead by a Django model/manager
import collections
from django.core.exceptions import ObjectDoesNotExist
class DjangoModelClientDB(collections.MutableMapping):
def __init__(self, django_model):
self._model = django_model
def __getitem__(self, key):
try:
model = self._model.objects.get(pk=key)
except ObjectDoesNotExist:
raise KeyError(key)
return model_to_client_dict(model)
def __setitem__(self, key, val):
self._model(pk=key, blob=val).save()
# later
from myapp.models import ClientModel
client_db = DjangoModelClientDB(ClientModel)
provider = MyProvider(client_db, **other_kwargs)
Final Note: I realized all these examples were for ClientDB, which is used with only the dict interface. SessionDB has a much larger interface, but takes a db
kwarg which is used dict-like. We use Redis as persistence for SessionDB, but the built-in SessionDB class isn't very friendly to having multiple processes sharing Redis for persistence (see: .uid2sid
which is an in-memory cache). I can try to share our DistributedSessionDB
and/or RedisSessionStorage
later when it is farther along.
from pyoidc.
I'm using the flask framework and I'm totally lost with this package. Can someone demonstrate how I can implement oidc authentication/authorisation against my OP (internal to my company)? I don't know/understand how to translate the examples into what to do in Flask. Thanks.
from pyoidc.
I've created an example of how to use this library to create a OpenID Connect Client, see https://github.com/its-dirg/Flask-pyoidc. It should provide a starting point which you can build on.
You can find more documentation of the OpenID Connect Client specific stuff in the documentation.
from pyoidc.
Rebecka, thanks. I'll give it a try.
from pyoidc.
Related Issues (20)
- Document release process / pypi upload HOT 2
- Create python 3.11 compatible release for pypi HOT 2
- Client.request_and_return no longer works with NoneResponse HOT 5
- Update conda-forge packages HOT 1
- Update URL references after repo move HOT 2
- AttributeError: 'dict' object has no attribute 'create_cookie' HOT 3
- Allow using different authn_method in Consumer.complete()
- Consumer.backchannel_logout and handling state HOT 11
- Architecture question regardings multiple app instances HOT 3
- Cannot add `scope` to registration request HOT 5
- Release 1.5.1 HOT 4
- Investigate failing readthedocs.io build HOT 1
- pydantic 2 seems to be incompatible with oic currently HOT 1
- Now in seconds vs. milliseconds: IATError: Issued in the future HOT 2
- Multiple matching kid support HOT 1
- Add support for RFC 9207 (?) HOT 1
- Why does `Client.do_access_token_refresh` require `state`? HOT 2
- Use SLSA workflow to create releases for PyPi HOT 1
- Client.parse_response misinterprets success as failure HOT 4
- Fix mypy
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pyoidc.