{"id":16748649,"url":"https://github.com/honeyryderchuck/rodauth-oauth","last_synced_at":"2025-03-21T22:31:54.981Z","repository":{"id":37534958,"uuid":"283898037","full_name":"HoneyryderChuck/rodauth-oauth","owner":"HoneyryderChuck","description":"(Mirror) Roda OAuth and OpenID provider plugin","archived":false,"fork":false,"pushed_at":"2025-03-17T09:12:46.000Z","size":4690,"stargazers_count":16,"open_issues_count":2,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-17T10:28:51.828Z","etag":null,"topics":["oauth2","openid-connect","rodauth","ruby"],"latest_commit_sha":null,"homepage":"https://gitlab.com/os85/rodauth-oauth","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HoneyryderChuck.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-30T23:36:16.000Z","updated_at":"2025-03-17T09:12:49.000Z","dependencies_parsed_at":"2023-10-03T18:30:00.007Z","dependency_job_id":"4a08608d-a9e5-4195-a05d-50d0f69b950c","html_url":"https://github.com/HoneyryderChuck/rodauth-oauth","commit_stats":null,"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoneyryderChuck%2Frodauth-oauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoneyryderChuck%2Frodauth-oauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoneyryderChuck%2Frodauth-oauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoneyryderChuck%2Frodauth-oauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HoneyryderChuck","download_url":"https://codeload.github.com/HoneyryderChuck/rodauth-oauth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244880364,"owners_count":20525507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["oauth2","openid-connect","rodauth","ruby"],"created_at":"2024-10-13T02:13:17.622Z","updated_at":"2025-03-21T22:31:54.975Z","avatar_url":"https://github.com/HoneyryderChuck.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rodauth::Oauth\n\n[![Gem Version](https://badge.fury.io/rb/rodauth-oauth.svg)](http://rubygems.org/gems/rodauth-oauth)\n[![pipeline status](https://gitlab.com/os85/rodauth-oauth/badges/master/pipeline.svg)](https://gitlab.com/os85/rodauth-oauth/pipelines?page=1\u0026scope=all\u0026ref=master)\n[![coverage report](https://gitlab.com/os85/rodauth-oauth/badges/master/coverage.svg?job=coverage)](https://os85.gitlab.io/rodauth-oauth/coverage/#_AllFiles)\n\nThis is an extension to the `rodauth` gem which implements the [OAuth 2.0 framework](https://tools.ietf.org/html/rfc6749) for an authorization server.\n\n## Certification\n[\u003cimg width=\"184\" height=\"96\" align=\"right\" src=\"/openid-certified.jpg\" alt=\"OpenID Certification\"\u003e](https://openid.net/certification/)\n\n`rodauth-oauth` is [certified](https://openid.net/certification/) for the following profiles of the OpenID Connect™ protocol:\n\n* Basic OP\n* Implicit OP\n* Hybrid OP\n* Config OP\n* Dynamic OP\n* Form Post OP\n* 3rd Party-Init OP\n* Session Management OP\n* RP-Initiated Logout OP\n* Front-Channel Logout OP\n* Back-Channel Logout OP\n\nThe certifications were obtained using the [example OIDC server](/examples/oidc/authentication_server.rb) deployed [here](https://rodauth-oauth-oidc.onrender.com/).\n\n## Features\n\nThis gem implements the following RFCs and features of OAuth:\n\n* `oauth` - [The OAuth 2.0 protocol framework](-/wikis/home#oauth-20-protocol-framework):\n  * [Access Token generation](https://tools.ietf.org/html/rfc6749#section-1.4);\n  * [Access Token refresh token grant](https://tools.ietf.org/html/rfc6749#section-1.5);\n  * `oauth_authorization_code_grant` - [Authorization code grant](https://tools.ietf.org/html/rfc6749#section-1.3);\n  * `oauth_implicit_grant` - [Implicit grant (off by default)](https://tools.ietf.org/html/rfc6749#section-4.2);\n  * `oauth_client_credentials_grant` - [Client credentials grant (off by default)](https://tools.ietf.org/html/rfc6749#section-4.4);\n  * `oauth_device_code_grant` - [Device code grant (off by default)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-device-flow-15);\n  * `oauth_token_revocation` - [Token revocation](https://tools.ietf.org/html/rfc7009);\n  * `oauth_token_introspection` - [Token introspection](https://tools.ietf.org/html/rfc7662);\n  * `oauth_pushed_authorization_request` - [Pushed Authorization Request](https://datatracker.ietf.org/doc/html/rfc9126);\n  * [Authorization Server Metadata](https://tools.ietf.org/html/rfc8414);\n  * `oauth_pkce` - [PKCE](https://tools.ietf.org/html/rfc7636);\n  * `oauth_tls_client_auth` - [Mutual-TLS Client Authentication](https://datatracker.ietf.org/doc/html/rfc8705);\n  * `oauth_jwt` - [JWT Access Tokens](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-07);\n  * `oauth_jwt_secured_authorization_request` - [JWT Secured Authorization Request](https://tools.ietf.org/html/draft-ietf-oauth-jwsreq-20);\n  * `oauth_jwt_secured_authorization_response_mode` - [JWT Secured Authorization Response_mode](https://openid.net/specs/openid-financial-api-jarm.html);\n  * `oauth_resource_indicators` - [Resource Indicators](https://datatracker.ietf.org/doc/html/rfc8707);\n  * Access Type (Token refresh online and offline);\n* `oauth_assertion_base` - [Assertion Framework](https://datatracker.ietf.org/doc/html/rfc7521);\n  * `oauth_saml_bearer_grant` - [SAML 2.0 Bearer Assertion](https://datatracker.ietf.org/doc/html/rfc7522);\n  * `oauth_jwt_bearer_grant` - [JWT Bearer Assertion](https://datatracker.ietf.org/doc/html/rfc7523);\n* `oauth_dpop` - [OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://datatracker.ietf.org/doc/rfc9449/);\n\n* `oauth_dynamic_client_registration` - [Dynamic Client Registration Protocol](https://datatracker.ietf.org/doc/html/rfc7591) and [Dynamic Client Registration Management](https://www.rfc-editor.org/rfc/rfc7592);\n* OAuth application and token management dashboards;\n*  The recommendations for [Native Apps](https://www.rfc-editor.org/rfc/rfc8252);\n\nIt also implements several components of [OpenID Connect](https://openid.net/connect/) on top of the OAuth features it provides, including:\n\n* `oidc` - [OpenID Connect Core](https://gitlab.com/os85/rodauth-oauth/-/wikis/Id-Token-Authentication);\n  * `oidc_self_issued` - [Self-Issued OpenID Provider](https://openid.net/specs/openid-connect-core-1_0.html#SelfIssued)\n  * [OpenID Multiple Response Types](https://gitlab.com/os85/rodauth-oauth/-/wikis/Hybrid-flow);\n  * [OpenID Connect Discovery](https://gitlab.com/os85/rodauth-oauth/-/wikis/OIDC-Dynamic-Client-Registration);\n* `oidc_dynamic_client_registration` - [OpenID Connect Dynamic Client Registration](https://gitlab.com/os85/rodauth-oauth/-/wikis/OIDC-Dynamic-Client-Registration);\n* `oidc_session_management` - [Session Management](https://gitlab.com/os85/rodauth-oauth/-/wikis/Session-Management);\n* `oidc_rp_initiated_logout` - [RP Initiated Logout](https://gitlab.com/os85/rodauth-oauth/-/wikis/RP-Initiated-Logout);\n* `oidc_frontchannel_logout` - [Frontchannel Logout](https://gitlab.com/os85/rodauth-oauth/-/wikis/Frontchannel-Logout);\n* `oidc_backchannel_logout` - [Backchannel Logout](https://gitlab.com/os85/rodauth-oauth/-/wikis/Backchannel-Logout);\n\nThis gem supports also rails (via [rodauth-rails]((https://github.com/janko/rodauth-rails)), which also dictates the versioning policy).\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'rodauth-oauth'\n```\n\nAnd then execute:\n\n    $ bundle install\n\nOr install it yourself as:\n\n    $ gem install rodauth-oauth\n\n\n## Resources\n|               |                                                             |\n| ------------- | ----------------------------------------------------------- |\n| Website       | https://honeyryderchuck.gitlab.io/rodauth-oauth/            |\n| Documentation | https://honeyryderchuck.gitlab.io/rodauth-oauth/rdoc/       |\n| Wiki          | https://gitlab.com/os85/rodauth-oauth/wikis/home |\n| CI            | https://gitlab.com/os85/rodauth-oauth/pipelines  |\n\n## Articles\n\n* [How to use rodauth-oauth with rails and rodauth](https://honeyryderchuck.gitlab.io/2021/03/15/oidc-provider-on-rails-using-rodauth-oauth.html)\n* [How to use rodauth-oauth with rails and without rodauth](https://honeyryderchuck.gitlab.io/2021/09/08/using-rodauth-oauth-in-rails-without-rodauth-based-auth.html)\n\n## Usage\n\nThis tutorial assumes you already read the documentation and know how to set up `rodauth`. After that, integrating `rodauth-oauth` will look like:\n\n```ruby\nplugin :rodauth do\n  # enable it in the plugin\n  enable :login, :oauth_authorization_code_grant\n  oauth_application_scopes %w[profile.read profile.write]\nend\n\n# then, inside roda\n\nroute do |r|\n  r.rodauth\n\n  # public routes go here\n  # ...\n  # here you do your thing\n  # authenticated section is here\n\n  rodauth.require_authentication\n\n  # oauth will only kick in on ce you call #require_oauth_authorization\n\n  r.is \"users\" do\n    rodauth.require_oauth_authorization # defaults to profile.read\n    r.post do\n      rodauth.require_oauth_authorization(\"profile.write\")\n    end\n    # ...\n  end\n\n  r.is \"books\" do\n    rodauth.require_oauth_authorization(\"books.read\", \"books.research\")\n    r.get do\n      @books = Book.where(user_id: rodauth.current_oauth_account[:id]).all\n      # ...\n    end\n  end\nend\n```\n\n\nFor OpenID, it's very similar to the example above:\n\n```ruby\nplugin :rodauth do\n  # enable it in the plugin\n  enable :login, :oidc\n  oauth_application_scopes %w[openid email profile]\nend\n```\n\n\n### Example (TL;DR)\n\nJust [check our example applications](https://gitlab.com/os85/rodauth-oauth/-/tree/master/examples/).\n\n\n### Database migrations\n\nYou have to generate database tables for accounts, oauth applications, grants and tokens. In order for you to hit the ground running, [here's a set of migrations (using `sequel`) to generate the needed tables](https://gitlab.com/os85/rodauth-oauth/-/tree/master/test/migrate) (omit the first 2 if you already have account tables, and [follow recommendations from rodauth accordingly](https://github.com/jeremyevans/rodauth)).\n\nYou can change column names or even use existing tables, however, be aware that you'll have to define new column accessors at the `rodauth` plugin declaration level. Let's say, for instance, you'd like to change the `oauth_grants` table name to `access_grants`, and it's `code` column to `authorization_code`; then, you'd have to do the following:\n\n```ruby\nplugin :rodauth do\n  # enable it in the plugin\n  enable :login, :oauth_authorization_code_grant\n  # ...\n  oauth_grants_table :access_grants\n  oauth_grants_code_column :authorization_code\nend\n```\n\nIf you're starting from scratch though, the recommendation is to stick to the defaults.\n\n### HTML views\n\nYou'll have to generate HTML templates for the Oauth Authorization form.\n\nThe rodauth default setup expects the roda `render` plugin to be activated; by default, it expects a `views` directory to be defined in the project root folder. The Oauth Authorization template must be therefore defined there, and it should be called `oauth_authorize.(erb|str|...)` (read the [roda `render` plugin documentation](http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/Render.html) for more info about HTML templating).\n\n### OAuth applications management\n\nThis feature is **optional**, as not all authorization servers will want a full oauth applications dashboard. However, if you do and you don't want to do the work yourself, you can set it up in your roda app like this:\n\n```ruby\nroute do |r|\n  r.rodauth\n  # don't forget to authenticate to access the dashboard\n  rodauth.require_authentication\n  rodauth.oauth_applications\n  # ...\nend\n```\n\nNavigate to `\"http://your-app/oauth-applications\"` and click around.\n\n## Rails\n\nSupport for `rails` is achieved thanks to [rodauth-rails](https://github.com/janko/rodauth-rails). Therefore, the first step you'll have to take is to add it to your dependencies.\n\nYou'll have to run the generator task to create the necessary migrations and views:\n\n```\n\u003e bundle exec rails generate rodauth:oauth:install\n# create a migration file, db/migrate(*_create_rodauth_oauth.rb);\n# Oauth Application, Grant and Token models into app/models;\n\u003e bundle exec rails generate rodauth:oauth:views\n# copies default view files into app/views/rodauth\n```\n\nYou are encouraged to check the output and adapt it to your needs.\n\nYou can then enable this feature in `lib/rodauth_app.rb` and set up any options you want:\n\n```ruby\n# lib/roudauth_app.rb\nenable :oauth_authorization_code_grant\n# OAuth\noauth_application_scopes %w[profile.read profile.write books.read books.write]\n```\n\nNow that you're set up, you can use the `rodauth` object to deny access to certain subsets of your app/API:\n\n```ruby\nclass BooksController \u003c ApplicationController\n  before_action :allow_read_access, only: %i[index show]\n  before_action :allow_write_access, only: %i[create update]\n\n  def index\n    # ...\n  end\n\n  def show\n    # ...\n  end\n\n  def create\n    # ...\n  end\n\n  def update\n    # ...\n  end\n\n  private\n\n  def allow_read_access\n    rodauth.require_oauth_authorization(\"books.read\")\n  end\n\n  def allow_write_access\n    rodauth.require_oauth_authorization(\"books.write\")\n  end\nend\n```\n\n## Features\n\nIn this section, the non-standard features are going to be described in more detail.\n\n### Token / Secrets Hashing\n\nAccess tokens, refresh tokens and client secrets are hashed before being stored in the database (using `bcrypt`), by default.\n\nDisabling this behaviour is a matter of nullifying the hash column option:\n\n```ruby\nplugin :rodauth do\n  enable :oauth_authorization_code_grant\n\n  # storing access token, refresh token and client secret in plaintext:\n  oauth_grants_token_hash_column nil\n  oauth_grants_refresh_token_hash_column nil\n  oauth_applications_client_secret_hash_column nil\n```\n\nIf you'd like to replace the hashing function (for, let's say, [argon2](https://github.com/technion/ruby-argon2)), you'll need to perform the following overrides:\n\n```ruby\nplugin :rodauth do\n  enable :oauth_authorization_code_grant\n\n  secret_matches? { |oauth_application, secret| Argon2::Password.verify_password(secret, oauth_application[oauth_applications_client_secret_hash_column]) }\n  secret_hash { |secret| Argon2::Password.create(secret) }\nend\n```\n\n#### Internationalization (i18n)\n\n`rodauth-oauth` supports translating all user-facing text found in all pages and forms, by integrating with [rodauth-i18n](https://github.com/janko/rodauth-i18n). Just set it up in your application and `rodauth` configuration.\n\nDefault translations shipping with `rodauth-oauth` can be found [in this directory](https://gitlab.com/os85/rodauth-oauth/-/tree/master/locales). If they're not available for the languages you'd like to support, consider getting them translated from the english text, and contributing them to this repository via a Merge Request.\n\n(This feature is available since `v0.7`.)\n\n\n## Ruby support policy\n\nThe minimum Ruby version required to run `rodauth-oauth` is 2.5 . Besides that, it should support all rubies that rodauth and roda support, including JRuby and truffleruby.\n\n### Rails\n\nIf you're interested in using this library with rails, be sure to check `rodauth-rails` policy, as it supports rails 5.2 upwards.\n\n## Development\n\nAfter checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests, and `rake rubocop` to run the linter.\n\n## Contributing\n\nBug reports and pull requests are welcome on Gitlab at https://gitlab.com/os85/rodauth-oauth.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoneyryderchuck%2Frodauth-oauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoneyryderchuck%2Frodauth-oauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoneyryderchuck%2Frodauth-oauth/lists"}