diff --git a/lib/omniauth/strategies/hydra1.rb b/lib/omniauth/strategies/hydra1.rb index d18473e..6a7744b 100644 --- a/lib/omniauth/strategies/hydra1.rb +++ b/lib/omniauth/strategies/hydra1.rb @@ -1,30 +1,17 @@ # frozen_string_literal: true -require 'omniauth-oauth2' +require 'omniauth/openid_connect' require 'jwt' module OmniAuth module Strategies - class Hydra1 < OmniAuth::Strategies::OAuth2 + class Hydra1 < OmniAuth::Strategies::OpenIDConnect + option :issuer, 'https://auth-v1.raspberrypi.org/' + option :uid_field, 'sub' option :client_options, { - site: 'https://auth-v1.raspberrypi.org', - authorize_url:'https://auth-v1.raspberrypi.org/oauth2/auth', - token_url: 'https://auth-v1.raspberrypi.org/oauth2/token' + discovery: true, + host: 'auth-v1.raspberrypi.org', } - - def authorize_params - super.tap do |params| - %w[scope client_options login_options].each do |v| - params[v.to_sym] = request.params[v] if request.params[v] - end - end - end - - def callback_url - full_host + callback_path - end - - uid { raw_info['sub'].to_s } info do { @@ -42,10 +29,6 @@ def callback_url } end - def raw_info - @raw_info ||= (JWT.decode access_token.params['id_token'], nil, false)[0] - end - def email raw_info['email'] end diff --git a/lib/omniauth/strategies/rpi.rb b/lib/omniauth/strategies/rpi.rb index ef48bbb..ac62632 100644 --- a/lib/omniauth/strategies/rpi.rb +++ b/lib/omniauth/strategies/rpi.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'omniauth-oauth2' require 'jwt' module OmniAuth::Strategies diff --git a/omniauth-rpi.gemspec b/omniauth-rpi.gemspec index 99e94cd..def9549 100644 --- a/omniauth-rpi.gemspec +++ b/omniauth-rpi.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'jwt', '~> 2.2.3' spec.add_runtime_dependency 'omniauth', '~> 2.0' - spec.add_runtime_dependency 'omniauth-oauth2', '~> 1.4' + spec.add_runtime_dependency 'omniauth_openid_connect', '~> 0.7.1' spec.add_development_dependency 'bundler', '~> 2.0' spec.add_development_dependency 'rake', '~> 12.3.3' @@ -30,4 +30,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rubocop', '~> 1.20' spec.add_development_dependency 'rubocop-rspec', '~> 2.4.0' spec.add_development_dependency 'simplecov', '~> 0.21.2' + spec.add_development_dependency 'webmock' end diff --git a/spec/fixtures/openid-configuration b/spec/fixtures/openid-configuration new file mode 100644 index 0000000..47098df --- /dev/null +++ b/spec/fixtures/openid-configuration @@ -0,0 +1,12 @@ +HTTP/1.1 200 OK +Date: Thu, 11 May 2023 15:00:04 GMT +Content-Type: application/json; charset=utf-8 +Content-Length: 1425 +Connection: keep-alive +Vary: Origin +Via: 1.1 vegur +CF-Cache-Status: DYNAMIC +Server: cloudflare +CF-RAY: 7c5b4a168b9406a2-LHR + +{"issuer":"https://auth-v1.raspberrypi.org/","authorization_endpoint":"https://auth-v1.raspberrypi.org/oauth2/auth","token_endpoint":"https://auth-v1.raspberrypi.org/oauth2/token","jwks_uri":"https://auth-v1.raspberrypi.org/.well-known/jwks.json","subject_types_supported":["public"],"response_types_supported":["code","code id_token","id_token","token id_token","token","token id_token code"],"claims_supported":["sub"],"grant_types_supported":["authorization_code","implicit","client_credentials","refresh_token"],"response_modes_supported":["query","fragment"],"userinfo_endpoint":"https://auth-v1.raspberrypi.org/userinfo","scopes_supported":["offline_access","offline","openid"],"token_endpoint_auth_methods_supported":["client_secret_post","client_secret_basic","private_key_jwt","none"],"userinfo_signing_alg_values_supported":["none","RS256"],"id_token_signing_alg_values_supported":["RS256"],"request_parameter_supported":true,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"claims_parameter_supported":false,"revocation_endpoint":"https://auth-v1.raspberrypi.org/oauth2/revoke","backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"end_session_endpoint":"https://auth-v1.raspberrypi.org/oauth2/sessions/logout","request_object_signing_alg_values_supported":["RS256","none"]} \ No newline at end of file diff --git a/spec/omniauth/strategies/hydra1_spec.rb b/spec/omniauth/strategies/hydra1_spec.rb index 301b171..e5118f8 100644 --- a/spec/omniauth/strategies/hydra1_spec.rb +++ b/spec/omniauth/strategies/hydra1_spec.rb @@ -16,10 +16,12 @@ def make_env(path = '/auth/rpi', props = {}) [OmniAuth::Strategies::Hydra1, OmniAuth::Strategies::Rpi].each{|provider| RSpec.describe provider do before do + WebMock.disable_net_connect! OmniAuth.config.test_mode = true end - + after do + WebMock.enable_net_connect! OmniAuth.config.test_mode = false end @@ -33,47 +35,49 @@ def make_env(path = '/auth/rpi', props = {}) let(:parsed_response) { instance_double('ParsedResponse') } let(:response) { instance_double('Response', :parsed => parsed_response) } - let(:development_site) { 'http://localhost:9000/api/v3' } - let(:development_authorize_url) { 'http://localhost:9000/login/oauth/authorize' } - let(:development_token_url) { 'http://localhost:9000/login/oauth/access_token' } + let(:development_host) { 'localhost' } + let(:development_authorization_endpoint) { 'http://localhost:9000/login/oauth/authorize' } + let(:development_token_endpoint) { 'http://localhost:9000/login/oauth/access_token' } let(:development) do - described_class.new('RASPBERRY_KEY', 'RASPBERRY_SECRET', + described_class.new(app, client_options: { - site: development_site, - authorize_url: development_authorize_url, - token_url: development_token_url + host: development_host, + authorization_endpoint: development_authorization_endpoint, + token_endpoint: development_token_endpoint, + discovery: false }) end before(:each) do allow(strategy).to receive(:access_token).and_return(access_token) + stub_request(:get, "https://auth-v1.raspberrypi.org/.well-known/openid-configuration").to_return(File.new('./spec/fixtures/openid-configuration')) end context 'client options' do - it 'has the correct site url' do - expect(strategy.options.client_options.site).to eq('https://auth-v1.raspberrypi.org') - end - - it 'has the correct authorize url' do - expect(strategy.options.client_options.authorize_url).to eq('https://auth-v1.raspberrypi.org/oauth2/auth') + it 'has the correct host' do + expect(strategy.options.client_options.host).to eq('auth-v1.raspberrypi.org') end - it 'has the correct token url' do - expect(strategy.options.client_options.token_url).to eq('https://auth-v1.raspberrypi.org/oauth2/token') + it 'can use autodiscovery' do + expect(strategy.config).not_to be_nil end describe 'defaults are overrideable' do it 'for site' do - expect(development.options.client_options.site).to eq(development_site) + expect(development.options.client_options.host).to eq(development_host) end it 'for authorize url' do - expect(development.options.client_options.authorize_url).to eq(development_authorize_url) + expect(development.options.client_options.authorization_endpoint).to eq(development_authorization_endpoint) end it 'for token url' do - expect(development.options.client_options.token_url).to eq(development_token_url) + expect(development.options.client_options.token_endpoint).to eq(development_token_endpoint) + end + + it 'for discovery' do + expect(development.options.client_options.discovery).to be false end end end @@ -132,7 +136,7 @@ def make_env(path = '/auth/rpi', props = {}) expect(strategy.image).to be_nil expect(strategy.info['image']).to be_nil end - end + end context '#extra' do it 'returns roles and picture from deserialised extra if available' do @@ -148,12 +152,12 @@ def make_env(path = '/auth/rpi', props = {}) end end - describe '#callback_url' do + describe '#callback_endpoint' do it 'is a combination of host and callback path' do allow(strategy).to receive(:full_host).and_return('https://example.com') strategy.instance_variable_set(:@env, {}) - expect(strategy.callback_url).to eq("https://example.com/auth/#{provider_name provider}/callback") + expect(strategy.callback_endpoint).to eq("https://example.com/auth/#{provider_name provider}/callback") end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6156501..8a3083c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,7 @@ require 'bundler/setup' require 'omniauth-rpi' +require 'webmock/rspec' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure