pax_global_header 0000666 0000000 0000000 00000000064 13542416054 0014516 g ustar 00root root 0000000 0000000 52 comment=24f36c7b7006785ab2cafd61b5543312501b5206 doorkeeper-openid_connect-1.6.3/ 0000775 0000000 0000000 00000000000 13542416054 0016651 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/.gitignore 0000664 0000000 0000000 00000000243 13542416054 0020640 0 ustar 00root root 0000000 0000000 /.bundle /Gemfile.lock /spec/dummy/db/*.sqlite3* /spec/dummy/db/migrate/*doorkeeper_openid_connect* /spec/dummy/log/*.log /spec/dummy/tmp/ /spec/examples.txt /pkg doorkeeper-openid_connect-1.6.3/.ruby-version 0000664 0000000 0000000 00000000006 13542416054 0021312 0 ustar 00root root 0000000 0000000 2.6.3 doorkeeper-openid_connect-1.6.3/.travis.yml 0000664 0000000 0000000 00000001152 13542416054 0020761 0 ustar 00root root 0000000 0000000 language: ruby cache: bundler sudo: false before_install: - gem update --system # Bundler 2.0 is not compatible with Rails 4.2 # https://docs.travis-ci.com/user/languages/ruby/#bundler-20 - "find /home/travis/.rvm/rubies -wholename '*default/bundler-*.gemspec' -delete" - rvm @global do gem uninstall bundler -a -x -I || true - gem install bundler -v '< 2' before_script: - bundle update - bundle exec rake migrate script: - bundle exec rake spec env: - rails=4.2.0 - rails=5.0.0 - rails=5.2.0 rvm: - 2.3 - 2.4 - 2.5 - 2.6 matrix: exclude: - env: rails=4.2.0 rvm: 2.6 doorkeeper-openid_connect-1.6.3/CHANGELOG.md 0000664 0000000 0000000 00000011632 13542416054 0020465 0 ustar 00root root 0000000 0000000 ## Unreleased No changes yet. ## v1.6.3 (2019-09-24) ### Changes - [#81] Allow silent authentication without user consent (thanks to @jarosan) - Don't support Doorkeeper >= 5.2 due to breaking changes ## v1.6.2 (2019-08-09) ### Bugfixes - [#80] Check for client presence in controller, fixes a 500 error when `client_id` is missing (thanks to @cincospenguinos @urnf @isabellechalhoub) ## v1.6.1 (2019-06-07) ### Bugfixes - [#75] Fix return value for `after_successful_response` (thanks to @daveed) ### Changes - [#72] Add `revocation_endpoint` and `introspection_endpoint` to discovery response (thanks to @scarfacedeb) ## v1.6.0 (2019-03-06) ### Changes - [#70] This gem now requires Doorkeeper 5.0, and actually has done so since v1.5.4 (thanks to @michaelglass) ## v1.5.5 (2019-03-03) - [#69] Return `crv` parameter for EC keys (thanks to @marco-nicola) ## v1.5.4 (2019-02-15) ### Bugfixes - [#66] Fix an open redirect vulnerability ([CVE-2019-9837](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9837), thanks to @meagar) - [#67] Don't delete existing tokens with `prompt=consent` (thanks to @nov) ### Changes - [#62] Support customization of redirect params in `id_token` and `id_token token` responses (thanks to @meagar) ## v1.5.3 (2019-01-19) ### Bugfixes - [#60] Don't break native authorization in Doorkeeper 5.x ### Changes - [#58] Use versioned migrations for Rails 5.x (thanks to @tvongaza) ## v1.5.2 (2018-09-04) ### Changes - [#56] The previous release was a bit premature, this fixes some compatibility issues with Doorkeeper 5.x ## v1.5.1 (2018-09-04) ### Changes - [#55] This gem is now compatible with Doorkeeper 5.x ## v1.5.0 (2018-06-27) ### Features - [#52] Custom claims can now also be returned directly in the ID token, see the updated README for usage instructions ## v1.4.0 (2018-05-31) ### Upgrading - Support for Ruby versions older than 2.3 was dropped ### Features - Redirect errors per Section 3.1.2.6 of OpenID Connect 1.0 (by @ryands) - Set `id_token` when it's nil in token response (it's used in `refresh_token` requests) (by @Miouge1) ## v1.3.0 (2018-03-05) ### Features - Support for Implicit Flow (`response_type=id_token` and `response_type=id_token token`), see the updated README for usage instructions (by @nashby, @nhance and @stevenvegt) ## v1.2.0 (2017-08-31) ### Upgrading - The configuration setting `jws_private_key` was renamed to `signing_key`, you can still use the old name until it's removed in the next major release ### Features - Support for pairwise subject identifiers (by @travisofthenorth) - Support for EC and HMAC signing algorithms (by @110y) - Claims now receive an optional third `access_token` argument which allow you to dynamically adjust claim values based on the client's token (by @gigr) ### Bugfixes ## v1.1.2 (2017-01-18) ### Bugfixes - Fixes the `undefined local variable or method 'pre_auth'` error ## v1.1.1 (2017-01-18) #### Upgrading - The configuration setting `jws_public_key` wasn't actually used, it's deprecated now and will be removed in the next major release - The undocumented shorthand `to_proc` syntax for defining claims (`claim :user, &:name`) is not supported anymore #### Features - Claims now receive an optional second `scopes` argument which allow you to dynamically adjust claim values based on the requesting applications' scopes (by @nbibler) - The `prompt` parameter values `login` and `consent` are now supported - The configuration setting `protocol` was added (by @gigr) #### Bugfixes - Standard Claims are now mapped correctly to their default scopes (by @tylerhunt) - Blank `nonce` parameters are now ignored #### Changes - `nil` values and empty strings are now removed from the UserInfo and IdToken responses - Allow `json-jwt` dependency at ~> 1.6. (by @nbibler) - Configuration blocks no longer internally use `instance_eval` which previously gave undocumented and unexpected `self` access to the caller (by @nbibler) ## v1.1.0 (2016-11-30) This release is a general clean-up and adds support for some advanced OpenID Connect features. #### Upgrading - This version adds a table to store temporary nonces, use the generator `doorkeeper:openid_connect:migration` to create a migration - Implement the new configuration callbacks `auth_time_from_resource_owner` and `reauthenticate_resource_owner` to support advanced features #### Features - Add discovery endpoint ([a16caa8](/../../commit/a16caa8)) - Add webfinger and keys endpoints for discovery ([f70898b](/../../commit/f70898b)) - Add supported claims to discovery response ([1d8f9ea](/../../commit/1d8f9ea)) - Support prompt=none parameter ([c775d8b](/../../commit/c775d8b)) - Store and return nonces in IdToken responses ([d28ca8c](/../../commit/d28ca8c)) - Add generator for initializer ([80399fd](/../../commit/80399fd)) - Support max_age parameter ([aabe3aa](/../../commit/aabe3aa)) - Respect scope grants in UserInfo response ([25f2170](/../../commit/25f2170)) doorkeeper-openid_connect-1.6.3/CONTRIBUTING.md 0000664 0000000 0000000 00000003131 13542416054 0021100 0 ustar 00root root 0000000 0000000 # Contributing ## Workflow We are using the [Feature Branch Workflow (also known as GitHub Flow)](https://guides.github.com/introduction/flow/), and prefer delivery as pull requests. Our first line of defense is the [Travis CI](https://travis-ci.org/doorkeeper-gem/doorkeeper-openid_connect) build defined within [.travis.yml](.travis.yml) and triggered for every pull request. Create a feature branch: ```sh git checkout -B feature/contributing ``` ## Creating Good Commits The cardinal rule for creating good commits is to ensure there is only one "logical change" per commit. Why is this an important rule? * The smaller the amount of code being changed, the quicker & easier it is to review & identify potential flaws. * If a change is found to be flawed later, it may be necessary to revert the broken commit. This is much easier to do if there are not other unrelated code changes entangled with the original commit. * When troubleshooting problems using Git's bisect capability, small well defined changes will aid in isolating exactly where the code problem was introduced. * When browsing history using Git annotate/blame, small well defined changes also aid in isolating exactly where & why a piece of code came from. Things to avoid when creating commits: * Mixing whitespace changes with functional code changes. * Mixing two unrelated functional changes. * Sending large new features in a single giant commit. ## Release process - Bump version in `lib/doorkeeper/openid_connect/version.rb` - Update `CHANGELOG.md` - Commit all changes - Tag release and publish gem with `rake release` doorkeeper-openid_connect-1.6.3/Gemfile 0000664 0000000 0000000 00000000317 13542416054 0020145 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org' # use Rails version specified by environment ENV['rails'] ||= '5.2.0' gem 'rails', "~> #{ENV['rails']}" if ENV['rails'] =~ /^5./ gem 'rails-controller-testing' end gemspec doorkeeper-openid_connect-1.6.3/LICENSE.txt 0000664 0000000 0000000 00000002057 13542416054 0020500 0 ustar 00root root 0000000 0000000 MIT License Copyright (c) 2014 PlayOn! Sports Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. doorkeeper-openid_connect-1.6.3/README.md 0000664 0000000 0000000 00000031213 13542416054 0020130 0 ustar 00root root 0000000 0000000 # Doorkeeper::OpenidConnect [](https://travis-ci.org/doorkeeper-gem/doorkeeper-openid_connect) [](https://codeclimate.com/github/doorkeeper-gem/doorkeeper-openid_connect) [](https://rubygems.org/gems/doorkeeper-openid_connect) This library implements an [OpenID Connect](http://openid.net/connect/) authentication provider for Rails applications on top of the [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) OAuth 2.0 framework. OpenID Connect is a single-sign-on and identity layer with a [growing list of server and client implementations](http://openid.net/developers/libraries/). If you're looking for a client in Ruby check out [omniauth_openid_connect](https://github.com/m0n9oose/omniauth_openid_connect/). ## Table of Contents - [Status](#status) - [Known Issues](#known-issues) - [Example Applications](#example-applications) - [Installation](#installation) - [Configuration](#configuration) - [Scopes](#scopes) - [Claims](#claims) - [Routes](#routes) - [Nonces](#nonces) - [Internationalization (I18n)](#internationalization-i18n) - [Development](#development) - [License](#license) - [Sponsors](#sponsors) ## Status The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) are currently supported: - [Authentication using the Authorization Code Flow](http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) - [Authentication using the Implicit Flow](http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth) - [Requesting Claims using Scope Values](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) - [UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo) - [Normal Claims](http://openid.net/specs/openid-connect-core-1_0.html#NormalClaims) In addition we also support most of [OpenID Connect Discovery 1.0](http://openid.net/specs/openid-connect-discovery-1_0.html) for automatic configuration discovery. Take a look at the [DiscoveryController](app/controllers/doorkeeper/openid_connect/discovery_controller.rb) for more details on supported features. ### Known Issues - Doorkeeper's API mode (`Doorkeeper.configuration.api_only`) is not properly supported yet ### Example Applications - [GitLab](https://gitlab.com/gitlab-org/gitlab-ce) ([original MR](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8018)) - [Testing app for this gem](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/tree/master/spec/dummy) ## Installation Make sure your application is already set up with [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper#installation). Add this line to your application's `Gemfile` and run `bundle install`: ```ruby gem 'doorkeeper-openid_connect' ``` Run the installation generator to update routes and create the initializer: ```sh rails generate doorkeeper:openid_connect:install ``` Generate a migration for Active Record (other ORMs are currently not supported): ```sh rails generate doorkeeper:openid_connect:migration rake db:migrate ``` If you're upgrading from an earlier version, check [CHANGELOG.md](CHANGELOG.md) for upgrade instructions. ## Configuration Make sure you've [configured Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper#configuration) before continuing. Verify your settings in `config/initializers/doorkeeper.rb`: - `resource_owner_authenticator` - This callback needs to returns a falsey value if the current user can't be determined: ```ruby resource_owner_authenticator do if current_user current_user else redirect_to(new_user_session_url) nil end end ``` - `grant_flows` - If you want to use `id_token` or `id_token token` response types you need to add `implicit_oidc` to `grant_flows`: ```ruby grant_flows %w(authorization_code implicit_oidc) ``` The following settings are required in `config/initializers/doorkeeper_openid_connect.rb`: - `issuer` - Identifier for the issuer of the response (i.e. your application URL). The value is a case sensitive URL using the `https` scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components. - `subject` - Identifier for the resource owner (i.e. the authenticated user). A locally unique and never reassigned identifier within the issuer for the end-user, which is intended to be consumed by the client. The value is a case-sensitive string and must not exceed 255 ASCII characters in length. - The database ID of the user is an acceptable choice if you don't mind leaking that information. - If you want to provide a different subject identifier to each client, use [pairwise subject identifier](http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes) with configurations like below. ```ruby # config/initializers/doorkeeper_openid_connect.rb Doorkeeper::OpenidConnect.configure do # ... subject_types_supported [:pairwise] subject do |resource_owner, application| Digest::SHA256.hexdigest("#{resource_owner.id}#{URI.parse(application.redirect_uri).host}#{'your_secret_salt'}") end # ... end ``` - `signing_key` - Private key to be used for [JSON Web Signature](https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31). - You can generate a private key with the `openssl` command, see e.g. [Generate an RSA keypair using OpenSSL](https://en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL). - You should not commit the key to your repository, but use an external file (in combination with `File.read`) and/or the [dotenv-rails](https://github.com/bkeepers/dotenv) gem (in combination with `ENV[...]`). - `signing_algorithm` - The encryption type of the private key which defaults to `:rs256`. The list of supported algorithms can be found [here](https://github.com/nov/json-jwt/wiki/JWE#supported-algorithms) - `resource_owner_from_access_token` - Defines how to translate the Doorkeeper access token to a resource owner model. The following settings are optional, but recommended for better client compatibility: - `auth_time_from_resource_owner` - Returns the time of the user's last login, this can be a `Time`, `DateTime`, or any other class that responds to `to_i` - Required to support the `max_age` parameter and the `auth_time` claim. - `reauthenticate_resource_owner` - Defines how to trigger reauthentication for the current user (e.g. display a password prompt, or sign-out the user and redirect to the login form). - Required to support the `max_age` and `prompt=login` parameters. - The block is executed in the controller's scope, so you have access to methods like `params`, `redirect_to` etc. The following settings are optional: - `expiration` - Expiration time after which the ID Token must not be accepted for processing by clients. - The default is 120 seconds - `protocol` - The protocol to use when generating URIs for the discovery endpoints. - The default is `https` for production, and `http` for all other environments - Note that the OIDC specification mandates HTTPS, so you shouldn't change this for production environments unless you have a really good reason! ### Scopes To perform authentication over OpenID Connect, an OAuth client needs to request the `openid` scope. This scope needs to be enabled using either `optional_scopes` in the global Doorkeeper configuration in `config/initializers/doorkeeper.rb`, or by adding it to any OAuth application's `scope` attribute. > Note that any application defining its own scopes won't inherit the scopes defined in the initializer, so you might have to update existing applications as well. > > See [Using Scopes](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes) in the Doorkeeper wiki for more information. ### Claims Claims can be defined in a `claims` block inside `config/initializers/doorkeeper_openid_connect.rb`: ```ruby Doorkeeper::OpenidConnect.configure do claims do claim :email do |resource_owner| resource_owner.email end claim :full_name do |resource_owner| "#{resource_owner.first_name} #{resource_owner.last_name}" end claim :preferred_username, scope: :openid do |resource_owner, scopes, access_token| # Pass the resource_owner's preferred_username if the application has # `profile` scope access. Otherwise, provide a more generic alternative. scopes.exists?(:profile) ? resource_owner.preferred_username : "summer-sun-9449" end claim :groups, response: [:id_token, :user_info] do |resource_owner| resource_owner.groups end end end ``` Each claim block will be passed: - the `resource_owner`, which is the return value of `resource_owner_authenticator` in your initializer - the `scopes` granted by the access token, which is an instance of `Doorkeeper::OAuth::Scopes` - the `access_token` itself, which is an instance of `Doorkeeper::AccessToken` By default all custom claims are only returned from the `UserInfo` endpoint and not included in the ID token. You can optionally pass a `response:` keyword with one or both of the symbols `:id_token` or `:user_info` to specify where the claim should be returned. You can also pass a `scope:` keyword argument on each claim to specify which OAuth scope should be required to access the claim. If you define any of the defined [Standard Claims](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) they will by default use their [corresponding scopes](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) (`profile`, `email`, `address` and `phone`), and any other claims will by default use the `profile` scope. Again, to use any of these scopes you need to enable them as described above. ### Routes The installation generator will update your `config/routes.rb` to define all required routes: ``` ruby Rails.application.routes.draw do use_doorkeeper_openid_connect # your routes end ``` This will mount the following routes: ``` GET /oauth/userinfo POST /oauth/userinfo GET /oauth/discovery/keys GET /.well-known/openid-configuration GET /.well-known/webfinger ``` With the exception of the hard-coded `/.well-known` paths (see [RFC 5785](https://tools.ietf.org/html/rfc5785)) you can customize routes in the same way as with Doorkeeper, please refer to [this page on their wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes#version--05-1). ### Nonces To support clients who send nonces you have to tweak Doorkeeper's authorization view so the parameter is passed on. If you don't already have custom templates, run this generator in your Rails application to add them: ```sh rails generate doorkeeper:views ``` Then tweak the template as follows: ```patch --- i/app/views/doorkeeper/authorizations/new.html.erb +++ w/app/views/doorkeeper/authorizations/new.html.erb @@ -26,6 +26,7 @@ <%= hidden_field_tag :state, @pre_auth.state %> <%= hidden_field_tag :response_type, @pre_auth.response_type %> <%= hidden_field_tag :scope, @pre_auth.scope %> + <%= hidden_field_tag :nonce, @pre_auth.nonce %> <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %> <% end %> <%= form_tag oauth_authorization_path, method: :delete do %> @@ -34,6 +35,7 @@ <%= hidden_field_tag :state, @pre_auth.state %> <%= hidden_field_tag :response_type, @pre_auth.response_type %> <%= hidden_field_tag :scope, @pre_auth.scope %> + <%= hidden_field_tag :nonce, @pre_auth.nonce %> <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %> <% end %> ``` ### Internationalization (I18n) We use Rails locale files for error messages and scope descriptions, see [config/locales/en.yml](config/locales/en.yml). You can override these by adding them to your own translations in `config/locale`. ## Development Run `bundle install` to setup all development dependencies. To run all specs: ```sh bundle exec rake spec ``` To generate and run migrations in the test application: ```sh bundle exec rake migrate ``` To run the local engine server: ```sh bundle exec rake server ``` By default, the latest Rails version is used. To use a specific version run: ``` rails=4.2.0 bundle update ``` ## License Doorkeeper::OpenidConnect is released under the [MIT License](http://www.opensource.org/licenses/MIT). ## Sponsors Initial development of this project was sponsored by [PlayOn! Sports](https://github.com/playon). doorkeeper-openid_connect-1.6.3/Rakefile 0000664 0000000 0000000 00000000765 13542416054 0020326 0 ustar 00root root 0000000 0000000 ENV['RAILS_ENV'] ||= 'test' require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new task default: :spec task test: :spec desc 'Generate and run migrations in the test application' task :migrate do Dir.chdir('spec/dummy') do system('bin/rails generate doorkeeper:openid_connect:migration') system('bin/rake db:migrate') end end desc 'Run server in the test application' task :server do Dir.chdir('spec/dummy') do system('bin/rails server') end end doorkeeper-openid_connect-1.6.3/app/ 0000775 0000000 0000000 00000000000 13542416054 0017431 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/app/controllers/ 0000775 0000000 0000000 00000000000 13542416054 0021777 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/app/controllers/doorkeeper/ 0000775 0000000 0000000 00000000000 13542416054 0024136 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/app/controllers/doorkeeper/openid_connect/ 0000775 0000000 0000000 00000000000 13542416054 0027125 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/app/controllers/doorkeeper/openid_connect/discovery_controller.rb 0000664 0000000 0000000 00000005331 13542416054 0033726 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class DiscoveryController < ::Doorkeeper::ApplicationController include Doorkeeper::Helpers::Controller WEBFINGER_RELATION = 'http://openid.net/specs/connect/1.0/issuer'.freeze def provider render json: provider_response end def webfinger render json: webfinger_response end def keys render json: keys_response end private def provider_response doorkeeper = ::Doorkeeper.configuration openid_connect = ::Doorkeeper::OpenidConnect.configuration { issuer: openid_connect.issuer, authorization_endpoint: oauth_authorization_url(protocol: protocol), token_endpoint: oauth_token_url(protocol: protocol), revocation_endpoint: oauth_revoke_url(protocol: protocol), introspection_endpoint: oauth_introspect_url(protocol: protocol), userinfo_endpoint: oauth_userinfo_url(protocol: protocol), jwks_uri: oauth_discovery_keys_url(protocol: protocol), scopes_supported: doorkeeper.scopes, # TODO: support id_token response type response_types_supported: doorkeeper.authorization_response_types, response_modes_supported: [ 'query', 'fragment' ], token_endpoint_auth_methods_supported: [ 'client_secret_basic', 'client_secret_post', # TODO: look into doorkeeper-jwt_assertion for these #'client_secret_jwt', #'private_key_jwt' ], subject_types_supported: openid_connect.subject_types_supported, id_token_signing_alg_values_supported: [ ::Doorkeeper::OpenidConnect.signing_algorithm ], claim_types_supported: [ 'normal', # TODO: support these #'aggregated', #'distributed', ], claims_supported: [ 'iss', 'sub', 'aud', 'exp', 'iat', ] | openid_connect.claims.to_h.keys, } end def webfinger_response { subject: params.require(:resource), links: [ { rel: WEBFINGER_RELATION, href: root_url(protocol: protocol), } ] } end def keys_response signing_key = Doorkeeper::OpenidConnect.signing_key_normalized { keys: [ signing_key.merge( use: 'sig', alg: Doorkeeper::OpenidConnect.signing_algorithm ) ] } end def protocol Doorkeeper::OpenidConnect.configuration.protocol.call end end end end doorkeeper-openid_connect-1.6.3/app/controllers/doorkeeper/openid_connect/userinfo_controller.rb 0000664 0000000 0000000 00000000541 13542416054 0033547 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class UserinfoController < ::Doorkeeper::ApplicationController skip_before_action :verify_authenticity_token before_action -> { doorkeeper_authorize! :openid } def show render json: Doorkeeper::OpenidConnect::UserInfo.new(doorkeeper_token), status: :ok end end end end doorkeeper-openid_connect-1.6.3/bin/ 0000775 0000000 0000000 00000000000 13542416054 0017421 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/bin/console 0000775 0000000 0000000 00000000204 13542416054 0021005 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require 'bundler/setup' Bundler.require :default require 'doorkeeper/openid_connect' require 'pry' Pry.start doorkeeper-openid_connect-1.6.3/bin/setup 0000775 0000000 0000000 00000000203 13542416054 0020502 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install # Do any other automated setup that you need to do here doorkeeper-openid_connect-1.6.3/config/ 0000775 0000000 0000000 00000000000 13542416054 0020116 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/config/locales/ 0000775 0000000 0000000 00000000000 13542416054 0021540 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/config/locales/en.yml 0000664 0000000 0000000 00000002473 13542416054 0022673 0 ustar 00root root 0000000 0000000 en: doorkeeper: scopes: openid: 'Authenticate your account' profile: 'View your profile information' email: 'View your email address' address: 'View your physical address' phone: 'View your phone number' errors: messages: login_required: 'The authorization server requires end-user authentication' consent_required: 'The authorization server requires end-user consent' interaction_required: 'The authorization server requires end-user interaction' account_selection_required: 'The authorization server requires end-user account selection' openid_connect: errors: messages: # Configuration error messages resource_owner_from_access_token_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.resource_owner_from_access_token missing configuration.' auth_time_from_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.auth_time_from_resource_owner missing configuration.' reauthenticate_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.reauthenticate_resource_owner missing configuration.' subject_not_configured: 'ID Token generation failed due to Doorkeeper::OpenidConnect.configure.subject missing configuration.' doorkeeper-openid_connect-1.6.3/doorkeeper-openid_connect.gemspec 0000664 0000000 0000000 00000002365 13542416054 0025350 0 ustar 00root root 0000000 0000000 $:.push File.expand_path('../lib', __FILE__) require 'doorkeeper/openid_connect/version' Gem::Specification.new do |spec| spec.name = 'doorkeeper-openid_connect' spec.version = Doorkeeper::OpenidConnect::VERSION spec.authors = ['Sam Dengler', 'Markus Koller'] spec.email = ['sam.dengler@playonsports.com', 'markus-koller@gmx.ch'] spec.homepage = 'https://github.com/doorkeeper-gem/doorkeeper-openid_connect' spec.summary = %q{OpenID Connect extension for Doorkeeper.} spec.description = %q{OpenID Connect extension for Doorkeeper.} spec.license = %q{MIT} spec.files = `git ls-files -z`.split("\x0").reject do |f| f.match(%r{^(test|spec|features)/}) end spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] spec.required_ruby_version = ">= 2.3" spec.add_runtime_dependency 'doorkeeper', '>= 5.0', '< 5.2' spec.add_runtime_dependency 'json-jwt', '~> 1.6' spec.add_development_dependency 'rspec-rails' spec.add_development_dependency 'factory_bot' spec.add_development_dependency 'sqlite3', '~> 1.3.6' spec.add_development_dependency 'pry-byebug' spec.add_development_dependency 'conventional-changelog', '~> 1.2' end doorkeeper-openid_connect-1.6.3/lib/ 0000775 0000000 0000000 00000000000 13542416054 0017417 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/ 0000775 0000000 0000000 00000000000 13542416054 0021556 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/oauth/ 0000775 0000000 0000000 00000000000 13542416054 0022676 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/oauth/id_token_request.rb 0000664 0000000 0000000 00000001761 13542416054 0026574 0 ustar 00root root 0000000 0000000 module Doorkeeper module OAuth class IdTokenRequest attr_accessor :pre_auth, :auth, :resource_owner def initialize(pre_auth, resource_owner) @pre_auth = pre_auth @resource_owner = resource_owner end def authorize if pre_auth.authorizable? @auth = Authorization::Token.new(pre_auth, resource_owner) @auth.issue_token @response = response else @response = error_response end end def deny pre_auth.error = :access_denied error_response end private def response id_token = Doorkeeper::OpenidConnect::IdToken.new(auth.token, pre_auth.nonce) IdTokenResponse.new(pre_auth, auth, id_token) end def error_response ErrorResponse.from_request pre_auth, redirect_uri: pre_auth.redirect_uri, response_on_fragment: true end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/oauth/id_token_response.rb 0000664 0000000 0000000 00000001261 13542416054 0026735 0 ustar 00root root 0000000 0000000 module Doorkeeper module OAuth class IdTokenResponse < BaseResponse include OAuth::Helpers attr_accessor :pre_auth, :auth, :id_token def initialize(pre_auth, auth, id_token) @pre_auth = pre_auth @auth = auth @id_token = id_token end def redirectable? true end def redirect_uri Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, redirect_uri_params) end private def redirect_uri_params { expires_in: auth.token.expires_in_seconds, state: pre_auth.state, id_token: id_token.as_jws_token } end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/oauth/id_token_token_request.rb 0000664 0000000 0000000 00000000461 13542416054 0027770 0 ustar 00root root 0000000 0000000 module Doorkeeper module OAuth class IdTokenTokenRequest < IdTokenRequest private def response id_token_token = Doorkeeper::OpenidConnect::IdTokenToken.new(auth.token, pre_auth.nonce) IdTokenTokenResponse.new(pre_auth, auth, id_token_token) end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/oauth/id_token_token_response.rb 0000664 0000000 0000000 00000000422 13542416054 0030133 0 ustar 00root root 0000000 0000000 module Doorkeeper module OAuth class IdTokenTokenResponse < IdTokenResponse private def redirect_uri_params super.merge({ access_token: auth.token.token, token_type: auth.token.token_type }) end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect.rb 0000664 0000000 0000000 00000003772 13542416054 0025103 0 ustar 00root root 0000000 0000000 require 'doorkeeper' require 'active_model' require 'json/jwt' require 'doorkeeper/request' require 'doorkeeper/request/id_token' require 'doorkeeper/request/id_token_token' require 'doorkeeper/oauth/id_token_request' require 'doorkeeper/oauth/id_token_token_request' require 'doorkeeper/oauth/id_token_response' require 'doorkeeper/oauth/id_token_token_response' require 'doorkeeper/openid_connect/claims_builder' require 'doorkeeper/openid_connect/claims/claim' require 'doorkeeper/openid_connect/claims/normal_claim' require 'doorkeeper/openid_connect/config' require 'doorkeeper/openid_connect/response_types_config' require 'doorkeeper/openid_connect/engine' require 'doorkeeper/openid_connect/errors' require 'doorkeeper/openid_connect/id_token' require 'doorkeeper/openid_connect/id_token_token' require 'doorkeeper/openid_connect/user_info' require 'doorkeeper/openid_connect/version' require 'doorkeeper/openid_connect/helpers/controller' require 'doorkeeper/openid_connect/oauth/authorization/code' require 'doorkeeper/openid_connect/oauth/authorization_code_request' require 'doorkeeper/openid_connect/oauth/password_access_token_request' require 'doorkeeper/openid_connect/oauth/pre_authorization' require 'doorkeeper/openid_connect/oauth/token_response' require 'doorkeeper/openid_connect/orm/active_record' require 'doorkeeper/openid_connect/rails/routes' module Doorkeeper module OpenidConnect def self.signing_algorithm configuration.signing_algorithm.to_s.upcase.to_sym end def self.signing_key key = if [:HS256, :HS384, :HS512].include?(signing_algorithm) configuration.signing_key else OpenSSL::PKey.read(configuration.signing_key) end JSON::JWK.new(key) end def self.signing_key_normalized key = signing_key case key[:kty].to_sym when :RSA key.slice(:kty, :kid, :e, :n) when :EC key.slice(:kty, :kid, :crv, :x, :y) when :oct key.slice(:kty, :kid) end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/ 0000775 0000000 0000000 00000000000 13542416054 0024545 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims/ 0000775 0000000 0000000 00000000000 13542416054 0026015 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims/aggregated_claim.rb 0000664 0000000 0000000 00000000226 13542416054 0031601 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Claims class AggregatedClaim < Claim attr_accessor :jwt end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims/claim.rb 0000664 0000000 0000000 00000002160 13542416054 0027426 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Claims class Claim attr_accessor :name, :response, :scope # http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims # http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims STANDARD_CLAIMS = { profile: %i[ name family_name given_name middle_name nickname preferred_username profile picture website gender birthdate zoneinfo locale updated_at ], email: %i[ email email_verified ], address: %i[ address ], phone: %i[ phone_number phone_number_verified ], } def initialize(options = {}) @name = options[:name].to_sym @response = Array.wrap(options[:response]) @scope = options[:scope].to_sym if options[:scope] # use default scope for Standard Claims @scope ||= STANDARD_CLAIMS.find do |_scope, claims| claims.include? @name end.try(:first) # use profile scope as default fallback @scope ||= :profile end end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims/distributed_claim.rb 0000664 0000000 0000000 00000000253 13542416054 0032031 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Claims class DistributedClaim < Claim attr_accessor :endpoint, :access_token end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims/normal_claim.rb 0000664 0000000 0000000 00000000474 13542416054 0031004 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Claims class NormalClaim < Claim attr_reader :generator def initialize(options = {}) super(options) @generator = options[:generator] end def type :normal end end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/claims_builder.rb 0000664 0000000 0000000 00000002012 13542416054 0030043 0 ustar 00root root 0000000 0000000 require 'ostruct' module Doorkeeper module OpenidConnect class ClaimsBuilder def self.generate(access_token, response) resource_owner = Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token.call(access_token) Doorkeeper::OpenidConnect.configuration.claims.to_h.map do |name, claim| if access_token.scopes.exists?(claim.scope) && claim.response.include?(response) [name, claim.generator.call(resource_owner, access_token.scopes, access_token)] end end.compact.to_h end def initialize(&block) @claims = OpenStruct.new instance_eval(&block) end def build @claims end def normal_claim(name, response: [:user_info], scope: nil, &block) @claims[name] = Claims::NormalClaim.new( name: name, response: response, scope: scope, generator: block ) end alias_method :claim, :normal_claim end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/config.rb 0000664 0000000 0000000 00000010667 13542416054 0026351 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect def self.configure(&block) if Doorkeeper.configuration.orm != :active_record fail Errors::InvalidConfiguration, 'Doorkeeper OpenID Connect currently only supports the ActiveRecord ORM adapter' end @config = Config::Builder.new(&block).build end def self.configuration @config || (fail Errors::MissingConfiguration) end class Config class Builder def initialize(&block) @config = Config.new instance_eval(&block) end def build @config end def jws_public_key(*args) puts "DEPRECATION WARNING: `jws_public_key` is not needed anymore and will be removed in a future version, please remove it from config/initializers/doorkeeper_openid_connect.rb" end def jws_private_key(*args) puts "DEPRECATION WARNING: `jws_private_key` has been replaced by `signing_key` and will be removed in a future version, please remove it from config/initializers/doorkeeper_openid_connect.rb" signing_key(*args) end end module Option # Defines configuration option # # When you call option, it defines two methods. One method will take place # in the +Config+ class and the other method will take place in the # +Builder+ class. # # The +name+ parameter will set both builder method and config attribute. # If the +:as+ option is defined, the builder method will be the specified # option while the config attribute will be the +name+ parameter. # # If you want to introduce another level of config DSL you can # define +builder_class+ parameter. # Builder should take a block as the initializer parameter and respond to function +build+ # that returns the value of the config attribute. # # ==== Options # # * [:+as+] Set the builder method that goes inside +configure+ block # * [+:default+] The default value in case no option was set # # ==== Examples # # option :name # option :name, as: :set_name # option :name, default: 'My Name' # option :scopes builder_class: ScopesBuilder # def option(name, options = {}) attribute = options[:as] || name attribute_builder = options[:builder_class] Builder.instance_eval do define_method name do |*args, &block| # TODO: is builder_class option being used? value = if attribute_builder attribute_builder.new(&block).build else block ? block : args.first end @config.instance_variable_set(:"@#{attribute}", value) end end define_method attribute do |*_| if instance_variable_defined?(:"@#{attribute}") instance_variable_get(:"@#{attribute}") else options[:default] end end public attribute end def extended(base) base.send(:private, :option) end end extend Option option :issuer option :signing_key option :signing_algorithm, default: :rs256 option :subject_types_supported, default: [:public] option :resource_owner_from_access_token, default: lambda { |*_| fail Errors::InvalidConfiguration, I18n.translate('doorkeeper.openid_connect.errors.messages.resource_owner_from_access_token_not_configured') } option :auth_time_from_resource_owner, default: lambda { |*_| fail Errors::InvalidConfiguration, I18n.translate('doorkeeper.openid_connect.errors.messages.auth_time_from_resource_owner_not_configured') } option :reauthenticate_resource_owner, default: lambda { |*_| fail Errors::InvalidConfiguration, I18n.translate('doorkeeper.openid_connect.errors.messages.reauthenticate_resource_owner_not_configured') } option :subject, default: lambda { |*_| fail Errors::InvalidConfiguration, I18n.translate('doorkeeper.openid_connect.errors.messages.subject_not_configured') } option :expiration, default: 120 option :claims, builder_class: ClaimsBuilder option :protocol, default: lambda { |*_| ::Rails.env.production? ? :https : :http } end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/engine.rb 0000664 0000000 0000000 00000000332 13542416054 0026335 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class Engine < ::Rails::Engine initializer 'doorkeeper.openid_connect.routes' do Doorkeeper::OpenidConnect::Rails::Routes.install! end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/errors.rb 0000664 0000000 0000000 00000001743 13542416054 0026413 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Errors class OpenidConnectError < StandardError def error_name self.class.name.demodulize.underscore end end # internal errors class InvalidConfiguration < OpenidConnectError; end class MissingConfiguration < OpenidConnectError def initialize super('Configuration for Doorkeeper OpenID Connect missing. Do you have doorkeeper_openid_connect initializer?') end end # OAuth 2.0 errors # https://tools.ietf.org/html/rfc6749#section-4.1.2.1 class InvalidRequest < OpenidConnectError; end # OpenID Connect 1.0 errors # http://openid.net/specs/openid-connect-core-1_0.html#AuthError class LoginRequired < OpenidConnectError; end class ConsentRequired < OpenidConnectError; end class InteractionRequired < OpenidConnectError; end class AccountSelectionRequired < OpenidConnectError; end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/helpers/ 0000775 0000000 0000000 00000000000 13542416054 0026207 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/helpers/controller.rb 0000664 0000000 0000000 00000007527 13542416054 0030732 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Helpers module Controller private def authenticate_resource_owner! super.tap do |owner| next unless oidc_authorization_request? handle_oidc_prompt_param!(owner) handle_oidc_max_age_param!(owner) end rescue Errors::OpenidConnectError => exception handle_oidc_error!(exception) end def oidc_authorization_request? controller_path == Doorkeeper::Rails::Routes.mapping[:authorizations][:controllers] && action_name == 'new' && pre_auth.client && pre_auth.scopes.include?('openid') end def handle_oidc_error!(exception) # clear the previous response body to avoid a DoubleRenderError self.response_body = nil # FIXME: workaround for Rails 5, see https://github.com/rails/rails/issues/25106 @_response_body = nil error_response = if pre_auth.valid? ::Doorkeeper::OAuth::ErrorResponse.new( name: exception.error_name, state: params[:state], redirect_uri: params[:redirect_uri] ) else pre_auth.error_response end response.headers.merge!(error_response.headers) if error_response.redirectable? render json: error_response.body, status: :found, location: error_response.redirect_uri else render json: error_response.body, status: error_response.status end end def handle_oidc_prompt_param!(owner) prompt_values ||= params[:prompt].to_s.split(/ +/).uniq prompt_values.each do |prompt| case prompt when 'none' then raise Errors::InvalidRequest if (prompt_values - [ 'none' ]).any? raise Errors::LoginRequired unless owner raise Errors::ConsentRequired if oidc_consent_required?(owner) when 'login' then reauthenticate_oidc_resource_owner(owner) if owner when 'consent' then render :new when 'select_account' then # TODO: let the user implement this raise Errors::AccountSelectionRequired else raise Errors::InvalidRequest end end end def handle_oidc_max_age_param!(owner) max_age = params[:max_age].to_i return unless max_age > 0 && owner auth_time = instance_exec owner, &Doorkeeper::OpenidConnect.configuration.auth_time_from_resource_owner if !auth_time || (Time.zone.now - auth_time) > max_age reauthenticate_oidc_resource_owner(owner) end end def reauthenticate_oidc_resource_owner(owner) return_to = URI.parse(request.path) return_to.query = request.query_parameters.tap do |params| params['prompt'] = params['prompt'].to_s.sub(/\blogin\s*\b/, '').strip params.delete('prompt') if params['prompt'].blank? end.to_query instance_exec owner, return_to.to_s, &Doorkeeper::OpenidConnect.configuration.reauthenticate_resource_owner raise Errors::LoginRequired unless performed? end def matching_tokens_for_oidc_resource_owner(owner) Doorkeeper::AccessToken.authorized_tokens_for(pre_auth.client.id, owner.id).select do |token| Doorkeeper::AccessToken.scopes_match?(token.scopes, pre_auth.scopes, pre_auth.client.scopes) end end def oidc_consent_required?(owner) return false if skip_authorization? matching_tokens_for_oidc_resource_owner(owner).blank? end end end end Helpers::Controller.send :prepend, OpenidConnect::Helpers::Controller end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/id_token.rb 0000664 0000000 0000000 00000003076 13542416054 0026674 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class IdToken include ActiveModel::Validations attr_reader :nonce def initialize(access_token, nonce = nil) @access_token = access_token @nonce = nonce @resource_owner = Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token.call(access_token) @issued_at = Time.now end def claims { iss: issuer, sub: subject, aud: audience, exp: expiration, iat: issued_at, nonce: nonce, auth_time: auth_time }.merge ClaimsBuilder.generate(@access_token, :id_token) end def as_json(*_) claims.reject { |_, value| value.nil? || value == '' } end def as_jws_token JSON::JWT.new(as_json).sign( Doorkeeper::OpenidConnect.signing_key, Doorkeeper::OpenidConnect.signing_algorithm ).to_s end private def issuer Doorkeeper::OpenidConnect.configuration.issuer end def subject Doorkeeper::OpenidConnect.configuration.subject.call(@resource_owner, @access_token.application).to_s end def audience @access_token.application.uid end def expiration (@issued_at.utc + Doorkeeper::OpenidConnect.configuration.expiration).to_i end def issued_at @issued_at.utc.to_i end def auth_time Doorkeeper::OpenidConnect.configuration.auth_time_from_resource_owner.call(@resource_owner).try(:to_i) end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/id_token_token.rb 0000664 0000000 0000000 00000002436 13542416054 0030073 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class IdTokenToken < IdToken def claims super.merge(at_hash: at_hash) end private # The at_hash is build according to the following standard: # # http://openid.net/specs/openid-connect-implicit-1_0.html#IDToken # # at_hash: # REQUIRED. Access Token hash value. If the ID Token is issued with an # access_token in an Implicit Flow, this is REQUIRED, which is the case # for this subset of OpenID Connect. Its value is the base64url encoding # of the left-most half of the hash of the octets of the ASCII # representation of the access_token value, where the hash algorithm # used is the hash algorithm used in the alg Header Parameter of the # ID Token's JOSE Header. For instance, if the alg is RS256, hash the # access_token value with SHA-256, then take the left-most 128 bits and # base64url-encode them. The at_hash value is a case-sensitive string. def at_hash sha256 = Digest::SHA256.new token = @access_token.token hashed_token = sha256.digest(token) first_half = hashed_token[0...hashed_token.length / 2] Base64.urlsafe_encode64(first_half).tr('=', '') end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/ 0000775 0000000 0000000 00000000000 13542416054 0025665 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/authorization/ 0000775 0000000 0000000 00000000000 13542416054 0030565 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/authorization/code.rb 0000664 0000000 0000000 00000001051 13542416054 0032021 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module OAuth module Authorization module Code def issue_token super.tap do |access_grant| if pre_auth.nonce.present? ::Doorkeeper::OpenidConnect::Request.create!( access_grant: access_grant, nonce: pre_auth.nonce ) end end end end end end end OAuth::Authorization::Code.send :prepend, OpenidConnect::OAuth::Authorization::Code end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/authorization_code_request.rb 0000664 0000000 0000000 00000001113 13542416054 0033650 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module OAuth module AuthorizationCodeRequest private def after_successful_response super nonce = if openid_request = grant.openid_request openid_request.destroy! openid_request.nonce end id_token = Doorkeeper::OpenidConnect::IdToken.new(access_token, nonce) @response.id_token = id_token end end end end OAuth::AuthorizationCodeRequest.send :prepend, OpenidConnect::OAuth::AuthorizationCodeRequest end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/password_access_token_request.rb0000664 0000000 0000000 00000001126 13542416054 0034345 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module OAuth module PasswordAccessTokenRequest attr_reader :nonce def initialize(server, client, resource_owner, parameters = {}) super @nonce = parameters[:nonce] end private def after_successful_response id_token = Doorkeeper::OpenidConnect::IdToken.new(access_token, nonce) @response.id_token = id_token super end end end end OAuth::PasswordAccessTokenRequest.send :prepend, OpenidConnect::OAuth::PasswordAccessTokenRequest end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/pre_authorization.rb 0000664 0000000 0000000 00000000521 13542416054 0031756 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module OAuth module PreAuthorization attr_reader :nonce def initialize(server, client, attrs = {}) super @nonce = attrs[:nonce] end end end end OAuth::PreAuthorization.send :prepend, OpenidConnect::OAuth::PreAuthorization end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/oauth/token_response.rb 0000664 0000000 0000000 00000001046 13542416054 0031251 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module OAuth module TokenResponse attr_accessor :id_token def body if token.includes_scope? 'openid' id_token = self.id_token || Doorkeeper::OpenidConnect::IdToken.new(token) super .merge(id_token: id_token.as_jws_token) .reject { |_, value| value.blank? } else super end end end end end OAuth::TokenResponse.send :prepend, OpenidConnect::OAuth::TokenResponse end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/orm/ 0000775 0000000 0000000 00000000000 13542416054 0025342 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/orm/active_record.rb 0000664 0000000 0000000 00000001455 13542416054 0030505 0 ustar 00root root 0000000 0000000 require 'active_support/lazy_load_hooks' module Doorkeeper module OpenidConnect module Orm module ActiveRecord def initialize_models! super ActiveSupport.on_load(:active_record) do require 'doorkeeper/openid_connect/orm/active_record/access_grant' require 'doorkeeper/openid_connect/orm/active_record/request' if Doorkeeper.configuration.active_record_options[:establish_connection] [Doorkeeper::OpenidConnect::Request].each do |c| c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection] end end end end end end end Orm::ActiveRecord.singleton_class.send :prepend, OpenidConnect::Orm::ActiveRecord end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/orm/active_record/ 0000775 0000000 0000000 00000000000 13542416054 0030153 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/orm/active_record/access_grant.rb 0000664 0000000 0000000 00000000602 13542416054 0033132 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module AccessGrant def self.prepended(base) base.class_eval do has_one :openid_request, class_name: 'Doorkeeper::OpenidConnect::Request', inverse_of: :access_grant, dependent: :delete end end end end AccessGrant.send :prepend, OpenidConnect::AccessGrant end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/orm/active_record/request.rb 0000664 0000000 0000000 00000000556 13542416054 0032176 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class Request < ActiveRecord::Base self.table_name = "#{table_name_prefix}oauth_openid_requests#{table_name_suffix}".to_sym validates :access_grant_id, :nonce, presence: true belongs_to :access_grant, class_name: 'Doorkeeper::AccessGrant', inverse_of: :openid_request end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/rails/ 0000775 0000000 0000000 00000000000 13542416054 0025657 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/rails/routes.rb 0000664 0000000 0000000 00000003502 13542416054 0027525 0 ustar 00root root 0000000 0000000 require 'doorkeeper/openid_connect/rails/routes/mapping' require 'doorkeeper/openid_connect/rails/routes/mapper' module Doorkeeper module OpenidConnect module Rails class Routes module Helper def use_doorkeeper_openid_connect(options = {}, &block) Doorkeeper::OpenidConnect::Rails::Routes.new(self, &block).generate_routes!(options) end end def self.install! ActionDispatch::Routing::Mapper.send :include, Doorkeeper::OpenidConnect::Rails::Routes::Helper end attr_accessor :routes def initialize(routes, &block) @routes = routes @block = block end def generate_routes!(options) @mapping = Mapper.new.map(&@block) routes.scope options[:scope] || 'oauth', as: 'oauth' do map_route(:userinfo, :userinfo_routes) map_route(:discovery, :discovery_routes) end routes.scope as: 'oauth' do map_route(:discovery, :discovery_well_known_routes) end end private def map_route(name, method) return if @mapping.skipped?(name) mapping = @mapping[name] routes.scope controller: mapping[:controllers], as: mapping[:as] do send method end end def userinfo_routes routes.get :show, path: 'userinfo', as: '' routes.post :show, path: 'userinfo', as: nil end def discovery_routes routes.scope path: 'discovery' do routes.get :keys end end def discovery_well_known_routes routes.scope path: '.well-known' do routes.get :provider, path: 'openid-configuration' routes.get :webfinger end end end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/rails/routes/ 0000775 0000000 0000000 00000000000 13542416054 0027200 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/rails/routes/mapper.rb 0000664 0000000 0000000 00000001227 13542416054 0031013 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Rails class Routes class Mapper def initialize(mapping = Mapping.new) @mapping = mapping end def map(&block) instance_eval(&block) if block @mapping end def controllers(controller_names = {}) @mapping.controllers.merge!(controller_names) end def skip_controllers(*controller_names) @mapping.skips = controller_names end def as(alias_names = {}) @mapping.as.merge!(alias_names) end end end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/rails/routes/mapping.rb 0000664 0000000 0000000 00000001375 13542416054 0031166 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module Rails class Routes class Mapping attr_accessor :controllers, :as, :skips def initialize @controllers = { userinfo: 'doorkeeper/openid_connect/userinfo', discovery: 'doorkeeper/openid_connect/discovery' } @as = { userinfo: :userinfo, discovery: :discovery } @skips = [] end def [](routes) { controllers: @controllers[routes], as: @as[routes] } end def skipped?(controller) @skips.include?(controller) end end end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/response_types_config.rb 0000664 0000000 0000000 00000000624 13542416054 0031503 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect module ResponseTypeConfig private def calculate_authorization_response_types types = super if grant_flows.include? 'implicit_oidc' types << 'token' types << 'id_token' types << 'id_token token' end types end end end Config.send :prepend, OpenidConnect::ResponseTypeConfig end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/user_info.rb 0000664 0000000 0000000 00000001443 13542416054 0027065 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class UserInfo include ActiveModel::Validations def initialize(access_token) @access_token = access_token end def claims { sub: subject }.merge ClaimsBuilder.generate(@access_token, :user_info) end def as_json(*_) claims.reject { |_, value| value.nil? || value == '' } end private def subject Doorkeeper::OpenidConnect.configuration.subject.call(resource_owner, application).to_s end def resource_owner @resource_owner ||= Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token.call(@access_token) end def application @application ||= @access_token.application end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/openid_connect/version.rb 0000664 0000000 0000000 00000000120 13542416054 0026550 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect VERSION = '1.6.3'.freeze end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/request/ 0000775 0000000 0000000 00000000000 13542416054 0023246 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/doorkeeper/request/id_token.rb 0000664 0000000 0000000 00000000540 13542416054 0025366 0 ustar 00root root 0000000 0000000 require 'doorkeeper/request/strategy' module Doorkeeper module Request class IdToken < Strategy delegate :current_resource_owner, to: :server def pre_auth server.context.send(:pre_auth) end def request @request ||= OAuth::IdTokenRequest.new(pre_auth, current_resource_owner) end end end end doorkeeper-openid_connect-1.6.3/lib/doorkeeper/request/id_token_token.rb 0000664 0000000 0000000 00000000552 13542416054 0026571 0 ustar 00root root 0000000 0000000 require 'doorkeeper/request/strategy' module Doorkeeper module Request class IdTokenToken < Strategy delegate :current_resource_owner, to: :server def pre_auth server.context.send(:pre_auth) end def request @request ||= OAuth::IdTokenTokenRequest.new(pre_auth, current_resource_owner) end end end end doorkeeper-openid_connect-1.6.3/lib/generators/ 0000775 0000000 0000000 00000000000 13542416054 0021570 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/ 0000775 0000000 0000000 00000000000 13542416054 0023727 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/ 0000775 0000000 0000000 00000000000 13542416054 0026716 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/install_generator.rb 0000664 0000000 0000000 00000001066 13542416054 0032762 0 ustar 00root root 0000000 0000000 module Doorkeeper module OpenidConnect class InstallGenerator < ::Rails::Generators::Base include ::Rails::Generators::Migration source_root File.expand_path('../templates', __FILE__) desc 'Installs Doorkeeper OpenID Connect.' def install template 'initializer.rb', 'config/initializers/doorkeeper_openid_connect.rb' copy_file File.expand_path('../../../../../config/locales/en.yml', __FILE__), 'config/locales/doorkeeper_openid_connect.en.yml' route 'use_doorkeeper_openid_connect' end end end end doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/migration_generator.rb 0000664 0000000 0000000 00000001527 13542416054 0033307 0 ustar 00root root 0000000 0000000 require 'rails/generators/active_record' module Doorkeeper module OpenidConnect class MigrationGenerator < ::Rails::Generators::Base include ::Rails::Generators::Migration source_root File.expand_path('../templates', __FILE__) desc 'Installs Doorkeeper OpenID Connect migration file.' def install migration_template( 'migration.rb.erb', 'db/migrate/create_doorkeeper_openid_connect_tables.rb', migration_version: migration_version ) end def self.next_migration_number(dirname) ActiveRecord::Generators::Base.next_migration_number(dirname) end private def migration_version if ActiveRecord::VERSION::MAJOR >= 5 "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" end end end end end doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/templates/ 0000775 0000000 0000000 00000000000 13542416054 0030714 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/templates/initializer.rb 0000664 0000000 0000000 00000002721 13542416054 0033566 0 ustar 00root root 0000000 0000000 Doorkeeper::OpenidConnect.configure do issuer 'issuer string' signing_key <<-EOL -----BEGIN RSA PRIVATE KEY----- .... -----END RSA PRIVATE KEY----- EOL subject_types_supported [:public] resource_owner_from_access_token do |access_token| # Example implementation: # User.find_by(id: access_token.resource_owner_id) end auth_time_from_resource_owner do |resource_owner| # Example implementation: # resource_owner.current_sign_in_at end reauthenticate_resource_owner do |resource_owner, return_to| # Example implementation: # store_location_for resource_owner, return_to # sign_out resource_owner # redirect_to new_user_session_url end subject do |resource_owner, application| # Example implementation: # resource_owner.id # or if you need pairwise subject identifier, implement like below: # Digest::SHA256.hexdigest("#{resource_owner.id}#{URI.parse(application.redirect_uri).host}#{'your_secret_salt'}") end # Protocol to use when generating URIs for the discovery endpoint, # for example if you also use HTTPS in development # protocol do # :https # end # Expiration time on or after which the ID Token MUST NOT be accepted for processing. (default 120 seconds). # expiration 600 # Example claims: # claims do # normal_claim :_foo_ do |resource_owner| # resource_owner.foo # end # normal_claim :_bar_ do |resource_owner| # resource_owner.bar # end # end end doorkeeper-openid_connect-1.6.3/lib/generators/doorkeeper/openid_connect/templates/migration.rb.erb 0000664 0000000 0000000 00000000560 13542416054 0034002 0 ustar 00root root 0000000 0000000 class CreateDoorkeeperOpenidConnectTables < ActiveRecord::Migration<%= migration_version %> def change create_table :oauth_openid_requests do |t| t.integer :access_grant_id, null: false t.string :nonce, null: false end add_foreign_key( :oauth_openid_requests, :oauth_access_grants, column: :access_grant_id ) end end doorkeeper-openid_connect-1.6.3/spec/ 0000775 0000000 0000000 00000000000 13542416054 0017603 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/controllers/ 0000775 0000000 0000000 00000000000 13542416054 0022151 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/controllers/discovery_controller_spec.rb 0000664 0000000 0000000 00000006427 13542416054 0027773 0 ustar 00root root 0000000 0000000 require 'rails_helper' describe Doorkeeper::OpenidConnect::DiscoveryController, type: :controller do describe '#provider' do it 'returns the provider configuration' do get :provider data = JSON.parse(response.body) expect(data.sort).to eq({ 'issuer' => 'dummy', 'authorization_endpoint' => 'http://test.host/oauth/authorize', 'token_endpoint' => 'http://test.host/oauth/token', 'revocation_endpoint' => 'http://test.host/oauth/revoke', 'introspection_endpoint' => 'http://test.host/oauth/introspect', 'userinfo_endpoint' => 'http://test.host/oauth/userinfo', 'jwks_uri' => 'http://test.host/oauth/discovery/keys', 'scopes_supported' => ['openid'], 'response_types_supported' => ['code'], 'response_modes_supported' => ['query', 'fragment'], 'token_endpoint_auth_methods_supported' => [ 'client_secret_basic', 'client_secret_post', ], 'subject_types_supported' => [ 'public', ], 'id_token_signing_alg_values_supported' => [ 'RS256', ], 'claim_types_supported' => [ 'normal', ], 'claims_supported' => [ 'iss', 'sub', 'aud', 'exp', 'iat', 'name', 'variable_name', 'created_at', 'updated_at', 'token_id', 'both_responses', 'id_token_response', 'user_info_response', ], }.sort) end it 'uses the protocol option for generating URLs' do Doorkeeper::OpenidConnect.configure do protocol { :testing } end get :provider data = JSON.parse(response.body) expect(data['authorization_endpoint']).to eq 'testing://test.host/oauth/authorize' end end describe '#webfinger' do it 'requires the resource parameter' do expect do get :webfinger end.to raise_error ActionController::ParameterMissing end it 'returns the OpenID Connect relation' do get :webfinger, params: { resource: 'user@example.com' } data = JSON.parse(response.body) expect(data.sort).to eq({ 'subject' => 'user@example.com', 'links' => [ 'rel' => 'http://openid.net/specs/connect/1.0/issuer', 'href' => 'http://test.host/', ], }.sort) end end describe '#keys' do subject { get :keys } shared_examples 'a key response' do |options| expected_parameters = options[:expected_parameters] it "includes only #{expected_parameters.join(', ')} parameters" do subject data = JSON.parse(response.body) key = data['keys'].first expect(key.keys.map(&:to_sym)).to match_array(expected_parameters) end end context 'when using an RSA key' do it_behaves_like 'a key response', expected_parameters: [:kty, :kid, :e, :n, :use, :alg] end context 'when using an EC key' do before { configure_ec } it_behaves_like 'a key response', expected_parameters: [:kty, :kid, :crv, :x, :y, :use, :alg] end context 'when using an HMAC key' do before { configure_hmac } it_behaves_like 'a key response', expected_parameters: [:kty, :kid, :use, :alg] end end end doorkeeper-openid_connect-1.6.3/spec/controllers/doorkeeper/ 0000775 0000000 0000000 00000000000 13542416054 0024310 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/controllers/doorkeeper/authorizations_controller_spec.rb 0000664 0000000 0000000 00000022445 13542416054 0033204 0 ustar 00root root 0000000 0000000 require 'rails_helper' describe Doorkeeper::AuthorizationsController, type: :controller do let(:user) { create :user } let(:application) { create :application, scopes: default_scopes } let(:default_scopes) { 'openid profile' } let(:token_attributes) { { application_id: application.id, resource_owner_id: user.id, scopes: default_scopes } } def authorize!(params = {}) get :new, params: { response_type: 'code', current_user: user.id, client_id: application.uid, scope: default_scopes, redirect_uri: application.redirect_uri, }.merge(params) end def build_redirect_uri(params = {}) Doorkeeper::OAuth::Authorization::URIBuilder.uri_with_query(application.redirect_uri, params) end def expect_authorization_form! expect(response).to be_successful expect(response).to render_template('doorkeeper/authorizations/new') end def expect_successful_callback! expect(response).to be_redirect expect(response.location).to match(/^#{Regexp.quote application.redirect_uri}\?code=[-\w]+$/) end describe '#authenticate_resource_owner!' do context 'with OIDC requests' do before do expect(controller).to receive(:handle_oidc_prompt_param!) expect(controller).to receive(:handle_oidc_max_age_param!) end it 'renders the authorization form if logged in' do authorize! expect_authorization_form! end it 'redirects to login form when not logged in' do authorize! current_user: nil expect(response).to redirect_to '/login' end end context 'with non-OIDC requests' do before do expect(controller).not_to receive(:handle_oidc_prompt_param!) expect(controller).not_to receive(:handle_oidc_max_age_param!) end it 'when action is not :new' do get :show expect(response).to redirect_to '/login' end it 'when openid scope is not present' do authorize!(scope: 'profile') expect_authorization_form! end it 'when client_id and scope are missing' do authorize!(client_id: nil, scope: nil) expect(response).to be_successful expect(response).to render_template('doorkeeper/authorizations/error') end end end describe '#handle_oidc_prompt_param!' do it 'is ignored when the openid scope is not present' do authorize! scope: 'profile', prompt: 'invalid' expect_authorization_form! end context 'with a prompt=none parameter' do context 'and a matching token' do before do create :access_token, token_attributes end it 'redirects to the callback if logged in' do authorize! prompt: 'none' expect_successful_callback! end it 'returns an invalid_request error if another prompt value is present' do authorize! prompt: 'none login' error_params = { 'error' => 'invalid_request', 'error_description' => 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.' } expect(response.status).to redirect_to build_redirect_uri(error_params) expect(JSON.parse(response.body)).to eq(error_params) end context 'when not logged in' do let(:error_params) do { 'error' => 'login_required', 'error_description' => 'The authorization server requires end-user authentication', 'state' => 'somestate' } end it 'returns a login_required error' do authorize! prompt: 'none', current_user: nil, state: 'somestate' expect(response).to redirect_to build_redirect_uri(error_params) expect(JSON.parse(response.body)).to eq(error_params) end it 'does not redirect to an invalid redirect_uri' do authorize! prompt: 'none', current_user: nil, state: 'somestate', redirect_uri: 'https://evilapp.com' expect(response).not_to be_redirect expect(response.status).to eq(Doorkeeper.gem_version >= Gem::Version.new('5.1') ? 400 : 401) expect(JSON.parse(response.body)).to eq error_params.merge( 'error' => 'invalid_redirect_uri', 'error_description' => "The requested redirect uri is malformed or doesn't match client redirect URI." ) end end end context 'and no matching token' do it 'redirects to the callback if skip_authorization is set to true' do allow(controller).to receive(:skip_authorization?) { true } authorize! prompt: 'none' expect_successful_callback! end it 'returns a consent_required error when logged in' do authorize! prompt: 'none' error_params = { 'error' => 'consent_required', 'error_description' => 'The authorization server requires end-user consent' } expect(response).to redirect_to build_redirect_uri(error_params) expect(JSON.parse(response.body)).to eq(error_params) end end end context 'with a prompt=login parameter' do it 'redirects to the sign in form if not logged in' do authorize! prompt: 'login', current_user: nil expect(response).to redirect_to('/login') end it 'reauthenticates the user if logged in' do authorize! prompt: 'login' expect(response).to redirect_to('/reauthenticate') end end context 'with a prompt=consent parameter' do it 'renders the authorization form even if a matching token is present' do create :access_token, token_attributes authorize! prompt: 'consent' expect_authorization_form! end end context 'with a prompt=select_account parameter' do it 'returns an account_selection_required error' do authorize! prompt: 'select_account' error_params = { 'error' => 'account_selection_required', 'error_description' => 'The authorization server requires end-user account selection' } expect(response.status).to redirect_to build_redirect_uri(error_params) expect(JSON.parse(response.body)).to eq(error_params) end end context 'with an unknown prompt parameter' do it 'returns an invalid_request error' do authorize! prompt: 'maybe' error_params = { 'error' => 'invalid_request', 'error_description' => 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.' } expect(response.status).to redirect_to build_redirect_uri(error_params) expect(JSON.parse(response.body)).to eq(error_params) end end end describe '#handle_oidc_max_age_param!' do context 'with an invalid max_age parameter' do it 'renders the authorization form' do %w[ 0 -1 -23 foobar ].each do |max_age| authorize! max_age: max_age expect_authorization_form! end end end context 'with a max_age=10 parameter' do it 'renders the authorization form if the users last login was within 10 seconds' do user.update! current_sign_in_at: 5.seconds.ago authorize! max_age: 10 expect_authorization_form! end it 'reauthenticates the user if the last login was longer than 10 seconds ago' do user.update! current_sign_in_at: 5.minutes.ago authorize! max_age: 10 expect(response).to redirect_to '/reauthenticate' end it 'reauthenticates the user if the last login is unknown' do user.update! current_sign_in_at: nil authorize! max_age: 10 expect(response).to redirect_to '/reauthenticate' end end end describe '#reauthenticate_oidc_resource_owner' do let(:performed) { true } before do allow(subject).to receive(:performed?) { performed } allow(subject.request).to receive(:path) { '/oauth/authorize' } allow(subject.request).to receive(:query_parameters) { { client_id: 'foo', prompt: 'login consent select_account' }.with_indifferent_access } end def reauthenticate! passed_args = nil Doorkeeper::OpenidConnect.configure do reauthenticate_resource_owner do |*args| passed_args = args end end subject.send :reauthenticate_oidc_resource_owner, user passed_args end it 'calls reauthenticate_resource_owner with the current user and the return path' do resource_owner, return_to = reauthenticate! expect(resource_owner).to eq user expect(return_to).to eq '/oauth/authorize?client_id=foo&prompt=consent+select_account' end it 'removes login from the prompt parameter and keeps other values' do _, return_to = reauthenticate! return_params = Rack::Utils.parse_query(URI.parse(return_to).query) expect(return_params['prompt']).to eq 'consent select_account' end context 'with a reauthenticator that does not generate a response' do let(:performed) { false } it 'raises a login_required error' do expect do reauthenticate! end.to raise_error(Doorkeeper::OpenidConnect::Errors::LoginRequired) end end end end authorized_applications_controller_spec.rb 0000664 0000000 0000000 00000000500 13542416054 0034752 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/controllers/doorkeeper require 'rails_helper' describe Doorkeeper::AuthorizedApplicationsController, type: :controller do let(:access_token) { create :access_token } describe '#index' do it 'does not run the extended #authenticate_resource_owner!' do expect do get :index end.not_to raise_error end end end doorkeeper-openid_connect-1.6.3/spec/controllers/userinfo_controller_spec.rb 0000664 0000000 0000000 00000004330 13542416054 0027605 0 ustar 00root root 0000000 0000000 require 'rails_helper' describe Doorkeeper::OpenidConnect::UserinfoController, type: :controller do let(:client) { create :application } let(:user) { create :user, name: 'Joe' } let(:token) { create :access_token, application: client, resource_owner_id: user.id } describe '#show' do context 'with a valid access token authorized for the openid scope' do let(:token) { create :access_token, application: client, resource_owner_id: user.id, scopes: 'openid' } it 'returns the basic user information as JSON' do get :show, params: { access_token: token.token } expect(response.status).to eq 200 expect(JSON.parse(response.body)).to eq({ 'sub' => user.id.to_s, 'variable_name' => 'openid-name', 'created_at' => user.created_at.to_i, 'token_id' => token.id, 'both_responses' => 'both', 'user_info_response' => 'user_info', }) end end context 'with a valid access token authorized for the openid and profile scopes' do let(:token) { create :access_token, application: client, resource_owner_id: user.id, scopes: 'openid profile' } it 'returns the full user information as JSON' do get :show, params: { access_token: token.token } expect(response.status).to eq 200 expect(JSON.parse(response.body)).to eq({ 'sub' => user.id.to_s, 'name' => 'Joe', 'variable_name' => 'profile-name', 'created_at' => user.created_at.to_i, 'updated_at' => user.updated_at.to_i, 'token_id' => token.id, 'both_responses' => 'both', 'user_info_response' => 'user_info', }) end end context 'with a valid access token not authorized for the openid scope' do it 'returns an error' do get :show, params: { access_token: token.token } expect(response.status).to eq 403 end end context 'without a valid access token' do it 'returns an error' do get :show, params: { access_token: 'foobar' } expect(response.status).to eq 401 end end end end doorkeeper-openid_connect-1.6.3/spec/dummy/ 0000775 0000000 0000000 00000000000 13542416054 0020736 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/.rspec 0000664 0000000 0000000 00000000036 13542416054 0022052 0 ustar 00root root 0000000 0000000 --color --require spec_helper doorkeeper-openid_connect-1.6.3/spec/dummy/Rakefile 0000664 0000000 0000000 00000000343 13542416054 0022403 0 ustar 00root root 0000000 0000000 # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require_relative 'config/application' Rails.application.load_tasks doorkeeper-openid_connect-1.6.3/spec/dummy/app/ 0000775 0000000 0000000 00000000000 13542416054 0021516 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/ 0000775 0000000 0000000 00000000000 13542416054 0023020 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/config/ 0000775 0000000 0000000 00000000000 13542416054 0024265 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/config/manifest.js 0000664 0000000 0000000 00000000100 13542416054 0026420 0 ustar 00root root 0000000 0000000 //= link_tree ../images //= link_directory ../stylesheets .css doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/images/ 0000775 0000000 0000000 00000000000 13542416054 0024265 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/images/.keep 0000664 0000000 0000000 00000000000 13542416054 0025200 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/javascripts/ 0000775 0000000 0000000 00000000000 13542416054 0025351 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/javascripts/application.js 0000664 0000000 0000000 00000001245 13542416054 0030214 0 ustar 00root root 0000000 0000000 // This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require_tree . doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/stylesheets/ 0000775 0000000 0000000 00000000000 13542416054 0025374 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/assets/stylesheets/application.css 0000664 0000000 0000000 00000001340 13542416054 0030407 0 ustar 00root root 0000000 0000000 /* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require_tree . *= require_self */ doorkeeper-openid_connect-1.6.3/spec/dummy/app/channels/ 0000775 0000000 0000000 00000000000 13542416054 0023311 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/channels/application_cable/ 0000775 0000000 0000000 00000000000 13542416054 0026742 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/channels/application_cable/channel.rb 0000664 0000000 0000000 00000000117 13542416054 0030676 0 ustar 00root root 0000000 0000000 module ApplicationCable class Channel < ActionCable::Channel::Base end end doorkeeper-openid_connect-1.6.3/spec/dummy/app/channels/application_cable/connection.rb 0000664 0000000 0000000 00000000125 13542416054 0031424 0 ustar 00root root 0000000 0000000 module ApplicationCable class Connection < ActionCable::Connection::Base end end doorkeeper-openid_connect-1.6.3/spec/dummy/app/controllers/ 0000775 0000000 0000000 00000000000 13542416054 0024064 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/controllers/application_controller.rb 0000664 0000000 0000000 00000000141 13542416054 0031153 0 ustar 00root root 0000000 0000000 class ApplicationController < ActionController::Base protect_from_forgery with: :exception end doorkeeper-openid_connect-1.6.3/spec/dummy/app/controllers/concerns/ 0000775 0000000 0000000 00000000000 13542416054 0025676 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/controllers/concerns/.keep 0000664 0000000 0000000 00000000000 13542416054 0026611 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/helpers/ 0000775 0000000 0000000 00000000000 13542416054 0023160 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/helpers/application_helper.rb 0000664 0000000 0000000 00000000035 13542416054 0027345 0 ustar 00root root 0000000 0000000 module ApplicationHelper end doorkeeper-openid_connect-1.6.3/spec/dummy/app/jobs/ 0000775 0000000 0000000 00000000000 13542416054 0022453 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/jobs/application_job.rb 0000664 0000000 0000000 00000000053 13542416054 0026133 0 ustar 00root root 0000000 0000000 class ApplicationJob < ActiveJob::Base end doorkeeper-openid_connect-1.6.3/spec/dummy/app/mailers/ 0000775 0000000 0000000 00000000000 13542416054 0023152 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/mailers/application_mailer.rb 0000664 0000000 0000000 00000000146 13542416054 0027334 0 ustar 00root root 0000000 0000000 class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' end doorkeeper-openid_connect-1.6.3/spec/dummy/app/models/ 0000775 0000000 0000000 00000000000 13542416054 0023001 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/models/application_record.rb 0000664 0000000 0000000 00000000116 13542416054 0027165 0 ustar 00root root 0000000 0000000 class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end doorkeeper-openid_connect-1.6.3/spec/dummy/app/models/concerns/ 0000775 0000000 0000000 00000000000 13542416054 0024613 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/models/concerns/.keep 0000664 0000000 0000000 00000000000 13542416054 0025526 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/app/models/user.rb 0000664 0000000 0000000 00000000210 13542416054 0024275 0 ustar 00root root 0000000 0000000 class User < ActiveRecord::Base def self.authenticate!(name, password) User.where(name: name, password: password).first end end doorkeeper-openid_connect-1.6.3/spec/dummy/bin/ 0000775 0000000 0000000 00000000000 13542416054 0021506 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/bin/bundle 0000775 0000000 0000000 00000000201 13542416054 0022676 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) load Gem.bin_path('bundler', 'bundle') doorkeeper-openid_connect-1.6.3/spec/dummy/bin/rails 0000775 0000000 0000000 00000000215 13542416054 0022544 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' doorkeeper-openid_connect-1.6.3/spec/dummy/bin/rake 0000775 0000000 0000000 00000000132 13542416054 0022352 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require_relative '../config/boot' require 'rake' Rake.application.run doorkeeper-openid_connect-1.6.3/spec/dummy/bin/setup 0000775 0000000 0000000 00000001630 13542416054 0022574 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require 'pathname' require 'fileutils' include FileUtils # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end chdir APP_ROOT do # This script is a starting point to setup your application. # Add necessary setup steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') # cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" system! 'bin/rails restart' end doorkeeper-openid_connect-1.6.3/spec/dummy/bin/update 0000775 0000000 0000000 00000001416 13542416054 0022720 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require 'pathname' require 'fileutils' include FileUtils # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end chdir APP_ROOT do # This script is a way to update your development environment automatically. # Add necessary update steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') puts "\n== Updating database ==" system! 'bin/rails db:migrate' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" system! 'bin/rails restart' end doorkeeper-openid_connect-1.6.3/spec/dummy/config.ru 0000664 0000000 0000000 00000000202 13542416054 0022545 0 ustar 00root root 0000000 0000000 # This file is used by Rack-based servers to start the application. require_relative 'config/environment' run Rails.application doorkeeper-openid_connect-1.6.3/spec/dummy/config/ 0000775 0000000 0000000 00000000000 13542416054 0022203 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/config/application.rb 0000664 0000000 0000000 00000000736 13542416054 0025041 0 ustar 00root root 0000000 0000000 require_relative 'boot' # Pick the frameworks you want: require "active_record/railtie" require "action_controller/railtie" require "action_view/railtie" Bundler.require(*Rails.groups) module Dummy class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. end end doorkeeper-openid_connect-1.6.3/spec/dummy/config/boot.rb 0000664 0000000 0000000 00000000351 13542416054 0023472 0 ustar 00root root 0000000 0000000 # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) doorkeeper-openid_connect-1.6.3/spec/dummy/config/database.yml 0000664 0000000 0000000 00000001050 13542416054 0024466 0 ustar 00root root 0000000 0000000 # SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: sqlite3 pool: 5 timeout: 5000 development: <<: *default database: db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: db/test.sqlite3 production: <<: *default database: db/production.sqlite3 doorkeeper-openid_connect-1.6.3/spec/dummy/config/environment.rb 0000664 0000000 0000000 00000000200 13542416054 0025064 0 ustar 00root root 0000000 0000000 # Load the Rails application. require_relative 'application' # Initialize the Rails application. Rails.application.initialize! doorkeeper-openid_connect-1.6.3/spec/dummy/config/environments/ 0000775 0000000 0000000 00000000000 13542416054 0024732 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/config/environments/test.rb 0000664 0000000 0000000 00000002372 13542416054 0026242 0 ustar 00root root 0000000 0000000 Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. config.eager_load = false # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr # Raises error for missing translations # config.action_view.raise_on_missing_translations = true end doorkeeper-openid_connect-1.6.3/spec/dummy/config/initializers/ 0000775 0000000 0000000 00000000000 13542416054 0024711 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/config/initializers/doorkeeper.rb 0000664 0000000 0000000 00000000343 13542416054 0027375 0 ustar 00root root 0000000 0000000 Doorkeeper.configure do optional_scopes :openid resource_owner_authenticator do if params[:current_user].present? User.find(params[:current_user]) else redirect_to('/login') nil end end end doorkeeper-openid_connect-1.6.3/spec/dummy/config/initializers/doorkeeper_openid_connect.rb 0000664 0000000 0000000 00000005474 13542416054 0032456 0 ustar 00root root 0000000 0000000 Doorkeeper::OpenidConnect.configure do issuer 'dummy' signing_key <<-EOL -----BEGIN RSA PRIVATE KEY----- MIIEpgIBAAKCAQEAsjdnSA6UWUQQHf6BLIkIEUhMRNBJC1NN/pFt1EJmEiI88GS0 ceROO5B5Ooo9Y3QOWJ/n+u1uwTHBz0HCTN4wgArWd1TcqB5GQzQRP4eYnWyPfi4C feqAHzQp+v4VwbcK0LW4FqtW5D0dtrFtI281FDxLhARzkhU2y7fuYhL8fVw5rUhE 8uwvHRZ5CEZyxf7BSHxIvOZAAymhuzNLATt2DGkDInU1BmF75tEtBJAVLzWG/j4L PZh1EpSdfezqaXQlcy9PJi916UzTl0P7Yy+ulOdUsMlB6yo8qKTY1+AbZ5jzneHb GDU/O8QjYvii1WDmJ60t0jXicmOkGrOhruOptwIDAQABAoIBAQChYNwMeu9IugJi NsEf4+JDTBWMRpOuRrwcpfIvQAUPrKNEB90COPvCoju0j9OxCDmpdPtq1K/zD6xx khlw485FVAsKufSp4+g6GJ75yT6gZtq1JtKo1L06BFFzb7uh069eeP7+wB6JxPHw KlAqwxvsfADhxeolQUKCTMb3Vjv/Aw2cO/nn6RAOeftw2aDmFy8Xl+oTUtSxyib0 YCdU9cK8MxsxDdmowwHp04xRTm/wfG5hLEn7HMz1PP86iP9BiFsCqTId9dxEUTS1 K+VAt9FbxRAq5JlBocxUMHNxLigb94Ca2FOMR7F6l/tronLfHD801YoObF0fN9qW Cgw4aTO5AoGBAOR79hiZVM7/l1cBid7hKSeMWKUZ/nrwJsVfNpu1H9xt9uDu+79U mcGfM7pm7L2qCNGg7eeWBHq2CVg/XQacRNtcTlomFrw4tDXUkFN1hE56t1iaTs9m dN9IDr6jFgf6UaoOxxoPT9Q1ZtO46l043Nzrkoz8cBEBaBY20bUDwCYjAoGBAMet tt1ImGF1cx153KbOfjl8v54VYUVkmRNZTa1E821nL/EMpoONSqJmRVsX7grLyPL1 QyZe245NOvn63YM0ng0rn2osoKsMVJwYBEYjHL61iF6dPtW5p8FIs7auRnC3NrG0 XxHATZ4xhHD0iIn14iXh0XIhUVk+nGktHU1gbmVdAoGBANniwKdqqS6RHKBTDkgm Dhnxw6MGa+CO3VpA1xGboxuRHeoY3KfzpIC5MhojBsZDvQ8zWUwMio7+w2CNZEfm g99wYiOjyPCLXocrAssj+Rzh97AdzuQHf5Jh4/W2Dk9jTbdPSl02ltj2Z+2lnJFz pWNjnqimHrSI09rDQi5NulJjAoGBAImquujVpDmNQFCSNA7NTzlTSMk09FtjgCZW 67cKUsqa2fLXRfZs84gD+s1TMks/NMxNTH6n57e0h3TSAOb04AM0kDQjkKJdXfhA lrHEg4z4m4yf3TJ9Tat09HJ+tRIBPzRFp0YVz23Btg4qifiUDdcQWdbWIb/l6vCY qhsu4O4BAoGBANbceYSDYRdT7a5QjJGibkC90Z3vFe4rDTBgZWg7xG0cpSU4JNg7 SFR3PjWQyCg7aGGXiooCM38YQruACTj0IFub24MFRA4ZTXvrACvpsVokJlQiG0Z4 tuQKYki41JvYqPobcq/rLE/AM7PKJftW35nqFuj0MrsUwPacaVwKBf5J -----END RSA PRIVATE KEY----- EOL subject_types_supported [:public] resource_owner_from_access_token do |access_token| User.find_by(id: access_token.resource_owner_id) end auth_time_from_resource_owner do |resource_owner| resource_owner.current_sign_in_at end reauthenticate_resource_owner do |_resource_owner, _return_to| redirect_to '/reauthenticate' end subject do |resource_owner| resource_owner.id end claims do claim :name do |user| user.name end claim :variable_name, scope: :openid do |user, scopes| scopes.exists?(:profile) ? "profile-name" : "openid-name" end claim :created_at, scope: :openid do |user| user.created_at.to_i end claim :updated_at do |user| user.updated_at.to_i end claim :token_id, scope: :openid do |user, scopes, token| token.id end claim(:both_responses, scope: :openid, response: [:id_token, :user_info]) { 'both' } claim(:id_token_response, scope: :openid, response: [:id_token]) { 'id_token' } claim(:user_info_response, scope: :openid, response: :user_info) { 'user_info' } end end doorkeeper-openid_connect-1.6.3/spec/dummy/config/initializers/new_framework_defaults.rb 0000664 0000000 0000000 00000001113 13542416054 0031767 0 ustar 00root root 0000000 0000000 # Require `belongs_to` associations by default. This is a new Rails 5.0 # default, so it is introduced as a configuration option to ensure that apps # made on earlier versions of Rails are not affected when upgrading. if Rails::VERSION::MAJOR >= 5 Rails.application.config.active_record.belongs_to_required_by_default = true Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true if Rails::VERSION::MINOR >= 2 else # monkey-patch versioned migrations in Rails < 5.0 class ActiveRecord::Migration def self.[](version) self end end end doorkeeper-openid_connect-1.6.3/spec/dummy/config/locales/ 0000775 0000000 0000000 00000000000 13542416054 0023625 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/config/locales/doorkeeper_openid_connect.en.yml 0000664 0000000 0000000 00000002473 13542416054 0032165 0 ustar 00root root 0000000 0000000 en: doorkeeper: scopes: openid: 'Authenticate your account' profile: 'View your profile information' email: 'View your email address' address: 'View your physical address' phone: 'View your phone number' errors: messages: login_required: 'The authorization server requires end-user authentication' consent_required: 'The authorization server requires end-user consent' interaction_required: 'The authorization server requires end-user interaction' account_selection_required: 'The authorization server requires end-user account selection' openid_connect: errors: messages: # Configuration error messages resource_owner_from_access_token_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.resource_owner_from_access_token missing configuration.' auth_time_from_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.auth_time_from_resource_owner missing configuration.' reauthenticate_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.reauthenticate_resource_owner missing configuration.' subject_not_configured: 'ID Token generation failed due to Doorkeeper::OpenidConnect.configure.subject missing configuration.' doorkeeper-openid_connect-1.6.3/spec/dummy/config/routes.rb 0000664 0000000 0000000 00000000154 13542416054 0024051 0 ustar 00root root 0000000 0000000 Rails.application.routes.draw do use_doorkeeper use_doorkeeper_openid_connect root 'dummy#index' end doorkeeper-openid_connect-1.6.3/spec/dummy/config/secrets.yml 0000664 0000000 0000000 00000001705 13542416054 0024401 0 ustar 00root root 0000000 0000000 # Be sure to restart your server when you modify this file. # Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # You can use `rails secret` to generate a secure secret key. # Make sure the secrets in this file are kept private # if you're sharing your code publicly. development: secret_key_base: 047f8d91118b6fad743ccac15928b306d1880d9d104377eb1f7aeed909ce852c0a214074742163a6e0bc814482c8cdeae470c5edfc75eee37c8da6ccbbae4199 test: secret_key_base: 88becc3eb1c84af38da6deea4627f29f2bd41ba79dd279a0e379a41a82f18316f6f5221c73182adca329df8be13fd7c115804a82246989f1314e93d7efc745d3 # Do not keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> doorkeeper-openid_connect-1.6.3/spec/dummy/db/ 0000775 0000000 0000000 00000000000 13542416054 0021323 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate/ 0000775 0000000 0000000 00000000000 13542416054 0022753 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate/20111122132257_create_users.rb 0000664 0000000 0000000 00000000230 13542416054 0027414 0 ustar 00root root 0000000 0000000 class CreateUsers < ActiveRecord::Migration[4.2] def change create_table :users do |t| t.string :name t.timestamps end end end doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb 0000664 0000000 0000000 00000000171 13542416054 0031320 0 ustar 00root root 0000000 0000000 class AddPasswordToUsers < ActiveRecord::Migration[4.2] def change add_column :users, :password, :string end end doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb 0000664 0000000 0000000 00000003757 13542416054 0031773 0 ustar 00root root 0000000 0000000 class CreateDoorkeeperTables < ActiveRecord::Migration[4.2] def change create_table :oauth_applications do |t| t.string :name, null: false t.string :uid, null: false t.string :secret, null: false t.text :redirect_uri, null: false t.string :scopes, null: false, default: '' t.timestamps null: false end add_index :oauth_applications, :uid, unique: true create_table :oauth_access_grants do |t| t.integer :resource_owner_id, null: false t.references :application, null: false t.string :token, null: false t.integer :expires_in, null: false t.text :redirect_uri, null: false t.datetime :created_at, null: false t.datetime :revoked_at t.string :scopes end add_index :oauth_access_grants, :token, unique: true add_foreign_key( :oauth_access_grants, :oauth_applications, column: :application_id, ) create_table :oauth_access_tokens do |t| t.integer :resource_owner_id t.references :application # If you use a custom token generator you may need to change this column # from string to text, so that it accepts tokens larger than 255 # characters. More info on custom token generators in: # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator # # t.text :token, null: false t.string :token, null: false t.string :refresh_token t.integer :expires_in t.datetime :revoked_at t.datetime :created_at, null: false t.string :scopes end add_index :oauth_access_tokens, :token, unique: true add_index :oauth_access_tokens, :resource_owner_id add_index :oauth_access_tokens, :refresh_token, unique: true add_foreign_key( :oauth_access_tokens, :oauth_applications, column: :application_id, ) end end doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb 0000664 0000000 0000000 00000000427 13542416054 0031753 0 ustar 00root root 0000000 0000000 class AddOwnerToApplication < ActiveRecord::Migration[4.2] def change add_column :oauth_applications, :owner_id, :integer, null: true add_column :oauth_applications, :owner_type, :string, null: true add_index :oauth_applications, [:owner_id, :owner_type] end end 20160320211015_add_previous_refresh_token_to_access_tokens.rb 0000664 0000000 0000000 00000000347 13542416054 0035664 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration[4.2] def change add_column( :oauth_access_tokens, :previous_refresh_token, :string, default: "", null: false ) end end 20161102204540_add_current_sign_in_at_to_users.rb 0000664 0000000 0000000 00000000214 13542416054 0033260 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate class AddCurrentSignInAtToUsers < ActiveRecord::Migration[4.2] def change add_column :users, :current_sign_in_at, :datetime end end 20180904152859_add_confidential_to_applications.rb 0000664 0000000 0000000 00000000366 13542416054 0033432 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/db/migrate # frozen_string_literal: true class AddConfidentialToApplications < ActiveRecord::Migration[5.0] def change add_column( :oauth_applications, :confidential, :boolean, null: false, default: true ) end end doorkeeper-openid_connect-1.6.3/spec/dummy/db/schema.rb 0000664 0000000 0000000 00000005173 13542416054 0023116 0 ustar 00root root 0000000 0000000 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your # database schema. If you need to create the application database on another # system, you should be using db:schema:load, not running all the migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 2018_09_04_152859) do create_table "oauth_access_grants", force: :cascade do |t| t.integer "resource_owner_id", null: false t.integer "application_id", null: false t.string "token", null: false t.integer "expires_in", null: false t.text "redirect_uri", null: false t.datetime "created_at", null: false t.datetime "revoked_at" t.string "scopes" t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true end create_table "oauth_access_tokens", force: :cascade do |t| t.integer "resource_owner_id" t.integer "application_id" t.string "token", null: false t.string "refresh_token" t.integer "expires_in" t.datetime "revoked_at" t.datetime "created_at", null: false t.string "scopes" t.string "previous_refresh_token", default: "", null: false t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true end create_table "oauth_applications", force: :cascade do |t| t.string "name", null: false t.string "uid", null: false t.string "secret", null: false t.text "redirect_uri", null: false t.string "scopes", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "owner_id" t.string "owner_type" t.boolean "confidential", default: true, null: false t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type" t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true end create_table "users", force: :cascade do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" t.string "password" t.datetime "current_sign_in_at" end end doorkeeper-openid_connect-1.6.3/spec/dummy/lib/ 0000775 0000000 0000000 00000000000 13542416054 0021504 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/lib/assets/ 0000775 0000000 0000000 00000000000 13542416054 0023006 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/lib/assets/.keep 0000664 0000000 0000000 00000000000 13542416054 0023721 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/log/ 0000775 0000000 0000000 00000000000 13542416054 0021517 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/log/.keep 0000664 0000000 0000000 00000000000 13542416054 0022432 0 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/public/ 0000775 0000000 0000000 00000000000 13542416054 0022214 5 ustar 00root root 0000000 0000000 doorkeeper-openid_connect-1.6.3/spec/dummy/public/404.html 0000664 0000000 0000000 00000003034 13542416054 0023411 0 ustar 00root root 0000000 0000000
You may have mistyped the address or the page may have moved.
If you are the application owner check the logs for more information.
Maybe you tried to change something you didn't have access to.
If you are the application owner check the logs for more information.
If you are the application owner check the logs for more information.