Giter Site home page Giter Site logo

Comments (5)

zamzterz avatar zamzterz commented on August 28, 2024

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.

gobengo avatar gobengo commented on August 28, 2024

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.

okyere avatar okyere commented on August 28, 2024

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.

zamzterz avatar zamzterz commented on August 28, 2024

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.

okyere avatar okyere commented on August 28, 2024

Rebecka, thanks. I'll give it a try.

from pyoidc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.