From Fedora Project Wiki
(use wikitable style)
(Drop references to iddev.)
 
(16 intermediate revisions by 5 users not shown)
Line 1: Line 1:
= OpenID Connect Authentication =
= OpenID Connect Authentication =
Fedora Infrastructure is using OpenID Connect authentication, and this page is used to document the implementation details.
Fedora Infrastructure is using [https://openid.net/connect/ OpenID Connect] authentication, and this page is used to document the implementation details.


For development purposes, there is https://iddev.fedorainfracloud.org/. For staging and production client secrets please file an Infrastructure ticket.
For development purposes, there is https://github.com/fedora-infra/tiny-stage For staging and production client secrets please file an Infrastructure ticket.


== Terminology ==
== Terminology ==
Line 20: Line 20:


== Suggested implementations ==
== Suggested implementations ==
For Flask, the suggested client is Flask-OIDC, for both clients and resource servers.
For Flask, the suggested client is [https://github.com/puiterwijk/flask-oidc Flask-OIDC], for both clients and resource servers.
For other clients, no clients have been suggested at this point, please get in touch if you have suggestions.
Examples of other clients (including [https://github.com/openid/AppAuth-JS Javascript], [https://github.com/openid/AppAuth-Android Android] and [https://github.com/openid/AppAuth-iOS iOS]), and servers (including [https://github.com/openid/ruby-openid Ruby] and [https://github.com/openid/php-openid PHP] can be found on the OpenID Github page, https://github.com/openid/ . For other clients, please get in touch if you have suggestions.


== Example Tutorials ==
Apart from the official documentation, there are also useful tutorials available online. Some are:
* [https://patrick.uiterwijk.org/ Patrick Uiterwjk] [https://pythonhosted.org/python-fedora/flask_fas_openid.html FAS Flask OpenID Auth Plugin]
* [http://www.mattmakai.com/ Matt Makai], [https://www.fullstackpython.com/blog/add-user-authentication-flask-apps-okta.html How to Add User Authentication to Flask Apps with Okta]
* [https://developer.okta.com/blog/authors/randall-degges/ Randall Degges] [https://developer.okta.com/blog/2018/07/12/flask-tutorial-simple-user-registration-and-login Flask Tutorial: Simple User Registration and Login]
* [https://fedoraproject.org/wiki/User:Pingou Pierre-Yves Chibon] [https://fpdc-client.readthedocs.io/en/latest/userguide.html#authentication FPDC User guide: Authentication]
An example authentication page is:
<nowiki>
# An simple demonstration application to use Fedora OpenID
# authentication system
# setup a client secrets file by doing
#
# pip3 install oidc-register
#
# Then run the application, (save it as app.py)
# flask run
#
# then open your browser at http://localhost:5000
#imports for Flask
import flask
from fedora.client import AuthError, AppError
from flask_oidc import OpenIDConnect
import munch
# Set up Flask application
app = flask.Flask(__name__)
# Application configuration (add secret key of your choice)
app.config["OIDC_CLIENT_SECRETS"] = "client_secrets.json"
app.config["SECRET_KEY"] = "secretkey"
# Set up FAS extension
OIDC = OpenIDConnect(app, credentials_store=flask.session)
@app.before_request
def before_request():
    """Set the flask session as permanent."""
    flask.session.permanent = True
    # Check if already logged in
    if OIDC.user_loggedin:
        if not hasattr(flask.session, 'fas_user') or not flask.session.fas_user:
            flask.session.fas_user = munch.Munch({
                'username': OIDC.user_getfield('nickname'),
                'email': OIDC.user_getfield('email') or '',
                'cla_done':
                  'http://admin.fedoraproject.org/accounts/cla/done'
                  in (OIDC.user_getfield('cla') or []),
                  })
        flask.g.user = flask.session.fas_user
    else:
        flask.g.fas_user = None
        flask.session.fas_user = None
@app.route("/logged_in")
@OIDC.require_login
def logged_in():
    return flask.Response("You are now logged in. Try to logout by going to http://localhost:5000/logout")
@app.route("/")
def landing_page():
    return flask.Response("Landing page, try to go to http://localhost:5000/login")
@app.route("/login")
def login():
    return flask.redirect(flask.url_for('.logged_in'))
@app.route("/logout")
def logout():
    if hasattr(flask.g, 'fas_user') and flask.g.fas_user is not None:
        OIDC.logout()
        flask.g.fas_user = None
        flask.session.fas_user = None
        flask.flash('You have been logged out')
    return flask.redirect(flask.url_for('.landing_page'))
</nowiki>


== Custom UserInfo fields ==
== Custom UserInfo fields ==
Line 83: Line 162:
| groups || Provides the "groups" attribute in the User Info.
| groups || Provides the "groups" attribute in the User Info.
|-
|-
| cla || Providees the "cla" attribute in the User Info.
| cla || Provides the "cla" attribute in the User Info.
|}
|}


Line 265: Line 344:
|-
|-
| commit_flag || Permission to flag a commit with a CI results
| commit_flag || Permission to flag a commit with a CI results
|}
=== fpdc.fedoraproject.org ===
Base namespace: <nowiki>https://fpdc.fedoraproject.org/oidc/</nowiki>
Availability: Development,Staging,Production
{| class="wikitable"
|-
! Scope ID !! Summary
|-
| create-release || Create a Release record
|-
| update-release || Edit a Release record
|-
| delete-release || Delete a Release record
|}
=== github.com/jmflinuxtx/kerneltest-harness ===
Base namespace: <nowiki>https://github.com/jmflinuxtx/kerneltest-harness/oidc/</nowiki>
Availability:
{|class="wikitable"
! Scope ID !! Summary
|-
| upload_test_run || Upload the results of a test run
|}
|}

Latest revision as of 23:01, 6 May 2024

OpenID Connect Authentication

Fedora Infrastructure is using OpenID Connect authentication, and this page is used to document the implementation details.

For development purposes, there is https://github.com/fedora-infra/tiny-stage For staging and production client secrets please file an Infrastructure ticket.

Terminology

Some basic terminology required to read this page:

  • OpenID Provider (OP): the Ipsilon deployment, this is the part that does user authentication and issues tokens
  • Identity Provider (IdP): see OpenID Provider
  • Relying Party (RP): any application that runs the OpenID Connect protocol.
  • Resource Server: any application that accepts tokens issued by the OpenID Provider.
  • UserInfo: HTTP endpoint provided by Ipsilon to provide information about the user that authorized a token.

Endpoint URLs

Suggested implementations

For Flask, the suggested client is Flask-OIDC, for both clients and resource servers. Examples of other clients (including Javascript, Android and iOS), and servers (including Ruby and PHP can be found on the OpenID Github page, https://github.com/openid/ . For other clients, please get in touch if you have suggestions.

Example Tutorials

Apart from the official documentation, there are also useful tutorials available online. Some are:


An example authentication page is:


# An simple demonstration application to use Fedora OpenID
# authentication system
# setup a client secrets file by doing
#
# pip3 install oidc-register
#
# Then run the application, (save it as app.py)
# flask run
#
# then open your browser at http://localhost:5000

#imports for Flask
import flask
from fedora.client import AuthError, AppError
from flask_oidc import OpenIDConnect
import munch

# Set up Flask application
app = flask.Flask(__name__)
# Application configuration (add secret key of your choice)
app.config["OIDC_CLIENT_SECRETS"] = "client_secrets.json"
app.config["SECRET_KEY"] = "secretkey"

# Set up FAS extension
OIDC = OpenIDConnect(app, credentials_store=flask.session)

@app.before_request
def before_request():
    """Set the flask session as permanent."""
    flask.session.permanent = True
    # Check if already logged in
    if OIDC.user_loggedin:
        if not hasattr(flask.session, 'fas_user') or not flask.session.fas_user:
            flask.session.fas_user = munch.Munch({
                'username': OIDC.user_getfield('nickname'),
                'email': OIDC.user_getfield('email') or '',
                'cla_done':
                  'http://admin.fedoraproject.org/accounts/cla/done'
                  in (OIDC.user_getfield('cla') or []),
                  })
        flask.g.user = flask.session.fas_user
    else:
        flask.g.fas_user = None
        flask.session.fas_user = None

@app.route("/logged_in")
@OIDC.require_login
def logged_in():
    return flask.Response("You are now logged in. Try to logout by going to http://localhost:5000/logout")

@app.route("/")
def landing_page():
    return flask.Response("Landing page, try to go to http://localhost:5000/login")

@app.route("/login")
def login():
    return flask.redirect(flask.url_for('.logged_in'))

@app.route("/logout")
def logout():
    if hasattr(flask.g, 'fas_user') and flask.g.fas_user is not None:
        OIDC.logout()
        flask.g.fas_user = None
        flask.session.fas_user = None
        flask.flash('You have been logged out')
    return flask.redirect(flask.url_for('.landing_page'))

Custom UserInfo fields

Field Summary Scope required (check table below for the namespace of these scopes)
groups List of groups the user is a member of groups
cla List of CLA URIs the user hs signed cla

Scopes

OAuth2/OpenID Connect scopes are specific strings that indicate for what use a particular token was requested. When a token is issued, the user was asked whether or not they consented to the particular set of permissions indicated by the token. For example, only tokens that were requested containing the scope https://release-monitoring.org/oidc/upstream can be used at Anitya for updating upstream project information. A token can contain many possible scopes, all of which have been authorized by the user.

In the Fedora Infrastructure, various applications are defined that specify various possible token scopes. These scopes are recorded here.

Every service will first list it's base namespace, and then the scope ID and a short summary of the scopes. To get the full scope to request, append the scope ID to the base namespace. So for example, to get the group information, this becomes: https://id.fedoraproject.org/scope/groups

The "Availability" line indicates whether this scope is live on the development, staging and production identity provider. A scope might not have progressed further because the application implementing it is only in a certain stage of development. This should only be edited by the infrastructure member that progresses the scope out further.

Registering new scopes

To register a new set of scopes, please feel free to just create a new section and then file a ticket on https://pagure.io/fedora-infrastructure/ to get them added to the development instance.

Also, once the scopes are finalized, please open a second ticket on https://pagure.io/fedora-infrastructure/ to request the scopes be added to the staging/production systems.

To add new scopes to an existing project, add a second table with the new scopes to the relevant section, follow the above process, and then merge the two tables back into one after the scopes are fully deployed.

Standard

These scopes are standardized, and not namespaced.

Availability: Development, Staging, Production.

Scope ID Claims provided
openid - This one is *required* for OpenID Connect requests
profile name, nickname, preferred_nickname, profile, zoneinfo, locale, updated_at
email email

Ipsilon

Base namespace: https://id.fedoraproject.org/scope/

Availability: Development, Staging, Production.

Scope ID Summary
groups Provides the "groups" attribute in the User Info.
cla Provides the "cla" attribute in the User Info.

release-monitoring.org

Base namespace: https://release-monitoring.org/oidc/

Note: release-monitoring.org is used here in the sense of "the upstream project that maintains the Anitya software", and hence these scope names are used regardless of where any given Anitya instance is deployed

Availability: Development

Scope ID Summary
upstream Permission to register new upstream projects for monitoring
downstream Permission to register new distros and new upstream/downstream mappings

mbs.fedoraproject.org

Base namespace: https://mbs.fedoraproject.org/oidc/

Availability: Staging, Production

Scope ID Summary
submit-build Permission to submit new module builds

waiverdb.fedoraproject.org

Base namespace: https://waiverdb.fedoraproject.org/oidc/

Availability: Development, Staging

Scope ID Summary
create-waiver Permission to create new waivers

beaker.qa.fedoraproject.org

Base namespace: https://beaker-project.org/oidc/

Availability: Staging, Production

Scope ID Summary
scope Full access to your beaker account.


pagure.io/odcs

Base namespace: https://pagure.io/odcs/

Availability: Development,Staging,Production

Scope ID Summary
new-compose Permission to create a new compose
renew-compose Permission to renew a compose
delete-compose Permission to delete a compose


github.com/fedora-infra/bodhi

Base namespace: https://github.com/fedora-infra/bodhi/

Availability:

Scope ID Summary
comment Post new comments and votes
create-update Submit new updates
edit-update Edit updates
request-update Request batched or stable
revoke-update Revoke an update
create-override Submit new override
edit-override Edit override
expire-override Expire an override


fedoraproject.org/wiki

Base namespace: https://fedoraproject.org/wiki/

Availability: Staging, Production

Scope ID Summary
api Full API access

pagure.io/freshmaker

Base namespace: https://pagure.io/freshmaker/

Availability: Staging,Production

Scope ID Summary
submit-build Permission to trigger manual rebuilds

src.fedoraproject.org

Base namespace: https://src.fedoraproject.org/

Availability: Staging,Production

Scope ID Summary
push Perform git pushes

pagure.io

Base namespace: https://pagure.io/oidc/

Availability: Development

Scope ID Summary
pull_request_merge Permission to merge a pull-request
pull_request_close Permission to close a pull-request
pull_request_comment Permission to comment a pull-request
pull_request_flag Permission to flag a pull-request with a CI status
pull_request_subscribe Permission to subscribe a user to a pull-request
pull_request_create Permission to create a pull-request
issue_create Permission to create an issue
issue_update Permission to update an issue
issue_change_status Permission to change the status of an issue
issue_update_milestone Permission to update the milestone of an issue
issue_comment Permission to comment on an issue
issue_assign Permission to assign an issue to a user
issue_subscribe Permission to subscribe a user to an issue
issue_update_custom_fields Permission to update an issue custom fields
create_project Permission to create a project
modify_project Permission to modify a project
fork_project Permission to fork a project
generate_acls_project Permission to generate the gitolite ACLs of a project
commit_flag Permission to flag a commit with a CI results

fpdc.fedoraproject.org

Base namespace: https://fpdc.fedoraproject.org/oidc/

Availability: Development,Staging,Production

Scope ID Summary
create-release Create a Release record
update-release Edit a Release record
delete-release Delete a Release record


github.com/jmflinuxtx/kerneltest-harness

Base namespace: https://github.com/jmflinuxtx/kerneltest-harness/oidc/

Availability:

Scope ID Summary
upload_test_run Upload the results of a test run