Flask-OpenID

repository·master·Indexed 42 days ago

https://github.com/pallets-eco/flask-openid

An extension providing OpenID support for Flask web applications, allowing users to authenticate using OpenID providers. It includes tools for initializing the OpenID extension, implementing user lookup, and managing login/logout handlers. Note: This library implements an outdated version of the OpenID protocol; OpenID Connect is the current industry standard.

Tokens
1.7K
Snippets
7
Records
10
Agent score
4%

What's inside Flask-OpenID

  1. Overview of Flask-OpenID

    master

    Flask-OpenID is an extension that adds support for the OpenID protocol to Flask applications.

    Warning: This library implements a very old and outdated version of the OpenID protocol. The current industry standard is OpenID Connect. It is highly recommended to use OpenID Connect instead of this library unless you are specifically maintaining legacy systems that require the original OpenID protocol.

  2. Use OpenID extensions

    master
    You can extend the login process by passing a list of instantiated openid.extension.Extension objects to the extensions argument of oid.try_login(). The results of these extensions will be available in the resp.extensions dictionary during the @oid.after_login callback.
  3. Implement user lookup in Flask

    master

    Since Flask-OpenID uses the 'openid' key in the Flask session to track logged-in users, you should implement a before_request function to map the stored OpenID URL to a user object in your application.

    from flask import g, session
    
    @app.before_request
    def lookup_current_user():
        g.user = None
        if 'openid' in session:
            openid = session['openid']
            # Replace User.query with your actual user lookup logic
            g.user = User.query.filter_by(openid=openid).first()
  4. Run the Flask-OpenID basic example

    master

    After installing flask-openid, you can run the provided basic OpenID integration example by executing the example.py script using Python. This serves as a minimal demonstration of how to integrate OpenID into a Flask application.

    python example.py
  5. Handle successful logins with @oid.after_login

    master

    After a successful OpenID authentication, a function decorated with @oid.after_login is called. This function receives an OpenIDResponse object (resp).

    Your responsibility is to:

    1. Store the user's identity URL in the session: session['openid'] = resp.identity_url.
    2. Determine if the user exists in your system.
    3. If the user exists, log them in and redirect.
    4. If the user is new, redirect them to a profile creation page, passing information from the resp object (e.g., resp.fullname, resp.nickname, resp.email).

    Note: Profile information requested via ask_for might be None if the provider does not support it.

    from flask import flash
    
    @oid.after_login
    def create_or_login(resp):
        session['openid'] = resp.identity_url
        user = User.query.filter_by(openid=resp.identity_url).first()
        if user is not None:
            flash(u'Successfully signed in')
            g.user = user
            return redirect(oid.get_next_url())
        
        # Redirect to profile creation for new users
        return redirect(url_for('create_profile', next=oid.get_next_url(),
                                name=resp.fullname or resp.nickname,
                                email=resp.email))
  6. Initialize the OpenID extension

    master

    To integrate Flask-OpenID, create an instance of the OpenID object. You can pass the app instance immediately or instantiate it without an app and use init_app(app) later.

    By default, it uses the filesystem as a store for authentication data. You can specify the store path via the OPENID_FS_STORE_PATH configuration variable or by passing a path to the constructor.

    The safe_roots parameter accepts a list of URL roots that are trusted for redirection. If the next request argument is not in this list, the user is redirected to the app root for security. All local URLs are trusted by default.

    from flask_openid import OpenID
    # Initialize with app and a filesystem store path
    oid = OpenID(app, '/path/to/store', safe_roots=[])
  7. Create a login handler with @oid.loginhandler

    master

    Define a view function to handle the login process. Decorate it with @oid.loginhandler. The handler should:

    1. Check if the user is already logged in using g.user and redirect via oid.get_next_url() if so.
    2. On POST, extract the openid from the form and call oid.try_login(openid, ...).
    3. Use oid.get_next_url() to provide the next value for the template.
    4. Use oid.fetch_error() to display errors in the template.

    When calling try_login, you can use ask_for (required) and ask_for_optional (optional) to request profile information like email, nickname, or fullname from the provider.

    @app.route('/login', methods=['GET', 'POST'])
    @oid.loginhandler
    def login():
        if g.user is not None:
            return redirect(oid.get_next_url())
        if request.method == 'POST':
            openid = request.form.get('openid')
            if openid:
                return oid.try_login(openid, ask_for=['email', 'nickname'],
                                             ask_for_optional=['fullname'])
        return render_template('login.html', next=oid.get_next_url(),
                               error=oid.fetch_error())