Puiterwijk (talk | contribs) (→URLs) |
(Drop references to iddev.) |
||
(49 intermediate revisions by 10 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:// | 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 == | ||
Some basic terminology required to read this page: | Some basic terminology required to read this page: | ||
* OpenID Provider (OP) | * OpenID Provider (OP): the Ipsilon deployment, this is the part that does user authentication and issues tokens | ||
* Identity Provider (IdP): see OpenID Provider | * Identity Provider (IdP): see OpenID Provider | ||
* Relying Party (RP): any application that runs the OpenID Connect protocol. | * Relying Party (RP): any application that runs the OpenID Connect protocol. | ||
* Resource Server: any application that accepts tokens issued by the OpenID Provider. | * Resource Server: any application that accepts tokens issued by the OpenID Provider. | ||
* UserInfo: | * UserInfo: HTTP endpoint provided by Ipsilon to provide information about the user that authorized a token. | ||
== Endpoint URLs == | == Endpoint URLs == | ||
Line 22: | 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. | ||
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 == | ||
{| | {|class="wikitable" | ||
! Field !! Summary !! Scope required | ! Field !! Summary !! Scope required (check table below for the namespace of these scopes) | ||
|- | |- | ||
| groups || List of groups the user is a member of || groups | | groups || List of groups the user is a member of || groups | ||
Line 35: | Line 112: | ||
|} | |} | ||
== 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 <nowiki>https://release-monitoring.org/oidc/upstream</nowiki> 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. | In the Fedora Infrastructure, various applications are defined that specify various possible token scopes. | ||
These scopes are recorded here. | These scopes are recorded here. | ||
Line 43: | Line 125: | ||
To get the full scope to request, append the scope ID to the base namespace. | 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: <nowiki>https://id.fedoraproject.org/scope/groups</nowiki> | So for example, to get the group information, this becomes: <nowiki>https://id.fedoraproject.org/scope/groups</nowiki> | ||
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. | |||
{|class="wikitable" | |||
! 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 === | === Ipsilon === | ||
Base namespace: <nowiki>https://id.fedoraproject.org/scope/</nowiki> | Base namespace: <nowiki>https://id.fedoraproject.org/scope/</nowiki> | ||
{| | Availability: Development, Staging, Production. | ||
{|class="wikitable" | |||
! Scope ID !! Summary | ! Scope ID !! Summary | ||
|- | |- | ||
| groups || Provides the "groups" attribute in the User Info. | | groups || Provides the "groups" attribute in the User Info. | ||
|- | |- | ||
| cla || | | cla || Provides the "cla" attribute in the User Info. | ||
|} | |||
=== release-monitoring.org === | |||
Base namespace: <nowiki>https://release-monitoring.org/oidc/</nowiki> | |||
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 | |||
{|class="wikitable" | |||
! 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: <nowiki>https://mbs.fedoraproject.org/oidc/</nowiki> | |||
Availability: Staging, Production | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| submit-build || Permission to submit new module builds | |||
|} | |||
=== waiverdb.fedoraproject.org === | |||
Base namespace: <nowiki>https://waiverdb.fedoraproject.org/oidc/</nowiki> | |||
Availability: Development, Staging | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| create-waiver || Permission to create new waivers | |||
|} | |||
=== beaker.qa.fedoraproject.org === | |||
Base namespace: <nowiki>https://beaker-project.org/oidc/</nowiki> | |||
Availability: Staging, Production | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| scope || Full access to your beaker account. | |||
|} | |||
=== pagure.io/odcs === | |||
Base namespace: <nowiki>https://pagure.io/odcs/</nowiki> | |||
Availability: Development,Staging,Production | |||
{|class="wikitable" | |||
! 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: <nowiki>https://github.com/fedora-infra/bodhi/</nowiki> | |||
Availability: | |||
{|class="wikitable" | |||
! 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: <nowiki>https://fedoraproject.org/wiki/</nowiki> | |||
Availability: Staging, Production | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| api || Full API access | |||
|} | |||
=== pagure.io/freshmaker === | |||
Base namespace: <nowiki>https://pagure.io/freshmaker/</nowiki> | |||
Availability: Staging,Production | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| submit-build || Permission to trigger manual rebuilds | |||
|} | |||
=== src.fedoraproject.org === | |||
Base namespace: <nowiki>https://src.fedoraproject.org/</nowiki> | |||
Availability: Staging,Production | |||
{|class="wikitable" | |||
! Scope ID !! Summary | |||
|- | |||
| push || Perform git pushes | |||
|} | |||
=== pagure.io === | |||
Base namespace: <nowiki>https://pagure.io/oidc/</nowiki> | |||
Availability: Development | |||
{| class="wikitable" | |||
|- | |||
! 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: <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
- Configuration URL for dynamic configuration: https://id.fedoraproject.org/openidc/.well-known/openid-configuration
- Authorization Endpoint: https://id.fedoraproject.org/openidc/Authorization
- Token Endpoint: https://id.fedoraproject.org/openidc/Token
- UserInfo Endpoint: https://id.fedoraproject.org/openidc/UserInfo
- Token Introspection URL: https://id.fedoraproject.org/openidc/TokenInfo
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:
- Patrick Uiterwjk FAS Flask OpenID Auth Plugin
- Matt Makai, How to Add User Authentication to Flask Apps with Okta
- Randall Degges Flask Tutorial: Simple User Registration and Login
- Pierre-Yves Chibon FPDC User guide: Authentication
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 |
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 |