From 19966f52b42928b5e08dee54dde307230f7cc2b5 Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Tue, 23 May 2023 11:38:28 +0100 Subject: [PATCH] Update issuer value to default to the authorization_endpoint (#54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I was confusing myself when running Hydra v1.11 (rather than v1.9) and decided that the issuer should be based on the `token_endpoint` rather than the `authorization_endpoint`. In 1.11 it is possible to specify the `SELF_PUBLIC_URL` value to split between URLs that should be queried by the browser, and those queried by the hydra client (ie.. the rails app). This helps with discovery, but ends up with the `SELF_ISSUER_URL` being `docker.host.internal` such that the other endpoints are correctly set. This PR simplifies things back to match with v1.9 😅 meaning that we don't have to see the issuer by hand. --------- Co-authored-by: Greg Annandale --- CHANGELOG.md | 4 +++ README.md | 33 ++++++++++++++++++++-- lib/rpi_auth/configuration.rb | 2 +- spec/dummy/config/initializers/rpi_auth.rb | 13 --------- spec/rpi_auth/configuration_spec.rb | 8 +++--- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba151b9..fc620ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Altered default value of the `issuer` to track the `authorization_endpoint` rather than the `token_endpoint` (#54) + ### Fixed - Ensure `redirect_uri` is set in the OpenID Connect configuration (#53) diff --git a/README.md b/README.md index 0c94c5a..c9002e0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ RpiAuth.configure do |config| end ``` -The values above will allow you to login using the `gem-dev` client seeded in Hydra provided you run the host application on port `3009`. +The values above will allow you to login using the `gem-dev` client seeded in Hydra provided you run the host application on port `3009`. An example configuration can be found [in the dummy app](spec/dummy/config/initializers/rpi_auth.rb). You will need to change the values to match your application, ideally through ENV vars eg. @@ -66,7 +66,7 @@ class ApplicationController < ActionController::Base end ``` -This provides access to the `current_user` method in controllers and helpers. +This provides access to the `current_user` method in controllers and helpers. The dummy app [has an example of this](spec/dummy/app/controllers/application_controller.rb). Add the `authenticatable` concern to the host application's User model: @@ -76,7 +76,7 @@ class User < ApplicationRecord end ``` -This model needs to be the same one defined in the initializer, an instance will be created on login. +This model needs to be the same one defined in the initializer, an instance will be created on login. Again, checkout the [user model in the dummy app](spec/dummy/app/models/user.rb). To login via Hydra your app needs to send the user to `/auth/rpi` via a POST request: @@ -156,6 +156,33 @@ class in `config/application.rb`. config.railties_order = [RpiAuth::Engine, :main_app, :all] ``` +## Troubleshooting + +Diagnosing issues with OpenID Connect can be tricky, so here are some things to try. + +### Setting the token URL in development mode + +Typically we run both Profile/Hydra and our applications in Docker. Both the browser and the application have to communicate with Hydra, and in a docker situation this means using two different hostnames. The browser can use `localhost`, but inside docker containers `localhost` refers to the container itself, not the machine running Docker. So the container has to use `docker.host.internal` instead. As a result, the application needs to have a separate URL to check tokens on. We configure this as the `auth_token_url`. + +Typical local environment variables for development are + +``` +AUTH_CLIENT_ID=my-hydra-client-dev +AUTH_CLIENT_SECRET=1234567890 +AUTH_TOKEN_URL=http://host.docker.internal:9001/ +AUTH_URL=http://localhost:9001 # The URL where Hydra is running +HOST_URL=http://localhost:3000 # The URL where your app is running +IDENTITY_URL=http://localhost:3002 # The URL where Profile (Pi Accounts) is running +``` + +### Matching the Issuer + +When tokens are issued, the OpenID Connect library validates that the token's "issuer" (`iss`) value. This library assumes that it matches the `auth_url` value, complete with a trailing slash. If this is not the case, you can set the issuer manually. It should match the value in either the `docker-compose.yml` in the profile repo, or at `http://localhost:9001/.well-known/openid-configuration` when Hydra is running. + +### Discovery + +The Omniauth OpenID Connect gem can use discovery to work out the majority of the configuration. However this does not work in development, as the discovery URL is assumed to be available over HTTPS which is not the case in this scenario. + ## Upgrading between versions. This project follows semantic versioning, so upgrades between minor and patch diff --git a/lib/rpi_auth/configuration.rb b/lib/rpi_auth/configuration.rb index 91d131b..2df8a37 100644 --- a/lib/rpi_auth/configuration.rb +++ b/lib/rpi_auth/configuration.rb @@ -46,7 +46,7 @@ def authorization_endpoint end def issuer - @issuer ||= token_endpoint.merge('/').to_s + @issuer ||= authorization_endpoint.merge('/').to_s end def jwks_uri diff --git a/spec/dummy/config/initializers/rpi_auth.rb b/spec/dummy/config/initializers/rpi_auth.rb index 0a3b895..a2e6592 100644 --- a/spec/dummy/config/initializers/rpi_auth.rb +++ b/spec/dummy/config/initializers/rpi_auth.rb @@ -9,17 +9,4 @@ config.user_model = 'User' config.bypass_auth = false - - # In development, the issuer is set in the docker-compose.yml file in the - # Profile repo. If you see errors like - # - # (rpi) Authentication failure! Invalid ID token: Issuer does not match - # - # then set the issuer here to match the value in the docker-compose file. - # When Hydra is running, the issue value can also be viewed at - # http://localhost:9001/.well-known/openid-configuration - # - # In staging/production this shouldn't be an issue, as all the hostnames are - # the same. - config.issuer = "http://localhost:9001/" end diff --git a/spec/rpi_auth/configuration_spec.rb b/spec/rpi_auth/configuration_spec.rb index ec95f26..eb92ce3 100644 --- a/spec/rpi_auth/configuration_spec.rb +++ b/spec/rpi_auth/configuration_spec.rb @@ -64,14 +64,14 @@ it 'sets the authorization_endpoint correctly' do expect(configuration.authorization_endpoint).to eq URI.parse(auth_url).merge('/oauth2/auth') end + + it 'sets the issuer' do + expect(configuration.issuer).to eq URI.parse(expected_url).merge('/').to_s + end end end shared_examples 'sets up the token url defaults' do - it 'sets the issuer' do - expect(configuration.issuer).to eq URI.parse(expected_url).merge('/').to_s - end - it 'sets the token_endpoint' do expect(configuration.token_endpoint).to eq URI.parse(expected_url).merge('/oauth2/token') end