gitlab-omniauth-openid-connect-0.10.1/0000755000004100000410000000000014424604376017622 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/.travis.yml0000644000004100000410000000013114424604376021726 0ustar www-datawww-datalanguage: ruby rvm: - 2.4 - 2.5 - 2.6 - 2.7 - 3.0 - jruby-head - ruby-head gitlab-omniauth-openid-connect-0.10.1/test/0000755000004100000410000000000014424604376020601 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/test/fixtures/0000755000004100000410000000000014424604376022452 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/test/fixtures/test.crt0000644000004100000410000000217714424604376024152 0ustar www-datawww-data-----BEGIN CERTIFICATE----- MIIDJDCCAgwCCQC57Ob2JfXb+DANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJK UDEOMAwGA1UECBMFVG9reW8xITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5 IEx0ZDESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDgwMTA4NTAxM1oXDTE1MDgw MTA4NTAxM1owVDELMAkGA1UEBhMCSlAxDjAMBgNVBAgTBVRva3lvMSEwHwYDVQQK ExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMTCWxvY2FsaG9zdDCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+7czSGHN2087T+oX2kBCY/ XN6UOS/mdU2Gn//omZlyxsQXIqvgBLNWeCVt4QdlFUbgPLggfXUelECV/RUOCIIi F2Th4t3x1LviN2XkUiva0DZBnOycqEaJdkyreEuGL1CLVZgZjKmSzNqLl0Yci3D0 zgVsXFZSadQebietm4CCmfJYREt9NJxXcrLxVDgat/Xm/KJBsohs3f+cbBT8EXer 7+2oZjZoVUgw1hu0alaOvAfE4mxsVwjn3g2mjDqRJLbbuWqgDobjMHah+d4zwJvN ePK8E0hfaz/XBLsJ4e6bQA3M3bANEgSvsicup/qb/0th4gUdc/kj4aJGj0RP7oEC AwEAATANBgkqhkiG9w0BAQUFAAOCAQEADuVec/8u2qJiq6K2W/gSLGYCBZq64OrA s7L2+S82m9/3gAb62wGcDNZjIGFDQubXmO6RhHv7JUT5YZqv9/kRGTJcHDUrwwoN IE99CIPizp7VfnrZ6GsYeszSsw3m+mKTETm+6ELmaSDbYAsrCg4IpGwUF0L88ATv CJ8QzW4X7b9dYVc7UAYyCie2N65GXfesBbRlSwFLuVqIzZfMdNpNijTIUwUqGSME b8IjLYzvekP53CO4wEBRrAVIPNXgftorxIE30OLWua2Qw3y6Pn+Qp5fLe47025S7 Lcec18/FbHG0Vbq0qO9cKQw80XyK31N6z556wr2GN2WyixkzVRddXA== -----END CERTIFICATE----- gitlab-omniauth-openid-connect-0.10.1/test/fixtures/jwks.json0000644000004100000410000000070214424604376024322 0ustar www-datawww-data{"keys": [{ "kty": "RSA", "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", "e": "AQAB", "alg": "RS256", "kid": "1e9gdk7" }] } gitlab-omniauth-openid-connect-0.10.1/test/lib/0000755000004100000410000000000014424604376021347 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/test/lib/omniauth/0000755000004100000410000000000014424604376023173 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/test/lib/omniauth/strategies/0000755000004100000410000000000014424604376025345 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/test/lib/omniauth/strategies/openid_connect_test.rb0000644000004100000410000010016614424604376031724 0ustar www-datawww-datarequire_relative '../../../test_helper' module OmniAuth module Strategies class OpenIDConnectTest < StrategyTestCase def test_client_options_defaults assert_equal 'https', strategy.options.client_options.scheme assert_equal 443, strategy.options.client_options.port assert_equal '/authorize', strategy.options.client_options.authorization_endpoint assert_equal '/token', strategy.options.client_options.token_endpoint end def test_request_phase expected_redirect = /^https:\/\/example\.com\/authorize\?client_id=1234&nonce=\w{32}&response_type=code&scope=openid&state=\w{32}$/ strategy.options.issuer = 'example.com' strategy.options.client_options.host = 'example.com' strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase end def test_logout_phase_with_discovery expected_redirect = %r{^https:\/\/example\.com\/logout$} strategy.options.client_options.host = 'example.com' strategy.options.discovery = true issuer = stub('OpenIDConnect::Discovery::Issuer') issuer.stubs(:issuer).returns('https://example.com/') ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer) config = stub('OpenIDConnect::Discovery::Provder::Config') config.stubs(:authorization_endpoint).returns('https://example.com/authorization') config.stubs(:token_endpoint).returns('https://example.com/token') config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo') config.stubs(:jwks_uri).returns('https://example.com/jwks') config.stubs(:end_session_endpoint).returns('https://example.com/logout') ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config) request.stubs(:path_info).returns('/auth/openid_connect/logout') request.stubs(:path).returns('/auth/openid_connect/logout') strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.other_phase end def test_logout_phase_with_discovery_and_post_logout_redirect_uri expected_redirect = 'https://example.com/logout?post_logout_redirect_uri=https%3A%2F%2Fmysite.com' strategy.options.client_options.host = 'example.com' strategy.options.discovery = true strategy.options.post_logout_redirect_uri = 'https://mysite.com' issuer = stub('OpenIDConnect::Discovery::Issuer') issuer.stubs(:issuer).returns('https://example.com/') ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer) config = stub('OpenIDConnect::Discovery::Provder::Config') config.stubs(:authorization_endpoint).returns('https://example.com/authorization') config.stubs(:token_endpoint).returns('https://example.com/token') config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo') config.stubs(:jwks_uri).returns('https://example.com/jwks') config.stubs(:end_session_endpoint).returns('https://example.com/logout') ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config) request.stubs(:path_info).returns('/auth/openid_connect/logout') request.stubs(:path).returns('/auth/openid_connect/logout') strategy.expects(:redirect).with(expected_redirect) strategy.other_phase end def test_logout_phase strategy.options.issuer = 'example.com' strategy.options.client_options.host = 'example.com' request.stubs(:path_info).returns('/auth/openid_connect/logout') strategy.expects(:call_app!) strategy.other_phase end def test_request_phase_with_params expected_redirect = /^https:\/\/example\.com\/authorize\?claims_locales=es&client_id=1234&login_hint=john.doe%40example.com&nonce=\w{32}&response_type=code&scope=openid&state=\w{32}&ui_locales=en$/ strategy.options.issuer = 'example.com' strategy.options.client_options.host = 'example.com' request.stubs(:params).returns('login_hint' => 'john.doe@example.com', 'ui_locales' => 'en', 'claims_locales' => 'es') strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase end def test_request_phase_with_discovery expected_redirect = /^https:\/\/example\.com\/authorization\?client_id=1234&nonce=\w{32}&response_type=code&scope=openid&state=\w{32}$/ strategy.options.client_options.host = 'example.com' strategy.options.discovery = true issuer = stub('OpenIDConnect::Discovery::Issuer') issuer.stubs(:issuer).returns('https://example.com/') ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer) config = stub('OpenIDConnect::Discovery::Provder::Config') config.stubs(:authorization_endpoint).returns('https://example.com/authorization') config.stubs(:token_endpoint).returns('https://example.com/token') config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo') config.stubs(:jwks_uri).returns('https://example.com/jwks') ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config) strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase assert_equal strategy.options.issuer, 'https://example.com/' assert_equal strategy.options.client_options.authorization_endpoint, 'https://example.com/authorization' assert_equal strategy.options.client_options.token_endpoint, 'https://example.com/token' assert_equal strategy.options.client_options.userinfo_endpoint, 'https://example.com/userinfo' assert_equal strategy.options.client_options.jwks_uri, 'https://example.com/jwks' assert_nil strategy.options.client_options.end_session_endpoint end def test_request_phase_with_response_mode expected_redirect = /^https:\/\/example\.com\/authorize\?client_id=1234&nonce=\w{32}&response_mode=form_post&response_type=id_token&scope=openid&state=\w{32}$/ strategy.options.issuer = 'example.com' strategy.options.response_mode = 'form_post' strategy.options.response_type = 'id_token' strategy.options.client_options.host = 'example.com' strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase end def test_request_phase_with_response_mode_symbol expected_redirect = /^https:\/\/example\.com\/authorize\?client_id=1234&nonce=\w{32}&response_mode=form_post&response_type=id_token&scope=openid&state=\w{32}$/ strategy.options.issuer = 'example.com' strategy.options.response_mode = 'form_post' strategy.options.response_type = :id_token strategy.options.client_options.host = 'example.com' strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase end def test_option_acr_values strategy.options.client_options[:host] = 'foobar.com' assert(!(strategy.authorize_uri =~ /acr_values=/), 'URI must not contain acr_values') strategy.options.acr_values = 'urn:some:acr:values:value' assert(strategy.authorize_uri =~ /acr_values=/, 'URI must contain acr_values') end def test_option_custom_attributes strategy.options.client_options[:host] = 'foobar.com' strategy.options.extra_authorize_params = {resource: 'xyz'} assert(strategy.authorize_uri =~ /resource=xyz/, 'URI must contain custom params') end def test_uid assert_equal user_info.sub, strategy.uid strategy.options.uid_field = 'preferred_username' assert_equal user_info.preferred_username, strategy.uid strategy.options.uid_field = 'something' assert_equal user_info.sub, strategy.uid end def test_callback_phase(session = {}, params = {}) code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = jwks.to_s strategy.options.response_type = 'code' strategy.unstub(:user_info) access_token = stub('OpenIDConnect::AccessToken') access_token.stubs(:access_token) access_token.stubs(:refresh_token) access_token.stubs(:expires_in) access_token.stubs(:scope) access_token.stubs(:id_token).returns(jwt.to_s) client.expects(:access_token!).at_least_once.returns(access_token) access_token.expects(:userinfo!).returns(user_info) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:raw_attributes).returns('sub' => 'sub', 'name' => 'name', 'email' => 'email') id_token.stubs(:verify!).with(issuer: strategy.options.issuer, client_id: @identifier, nonce: nonce).returns(true) id_token.expects(:verify!) strategy.expects(:decode_id_token).twice.with(access_token.id_token).returns(id_token) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_id_token state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => jwt.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = jwks.to_json strategy.options.response_type = 'id_token' strategy.unstub(:user_info) access_token = stub('OpenIDConnect::AccessToken') access_token.stubs(:access_token) access_token.stubs(:refresh_token) access_token.stubs(:expires_in) access_token.stubs(:scope) access_token.stubs(:id_token).returns(jwt.to_s) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:raw_attributes).returns('sub' => 'sub', 'name' => 'name', 'email' => 'email') id_token.stubs(:verify!).with(issuer: strategy.options.issuer, client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) id_token.expects(:verify!) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_id_token_no_kid other_rsa_private = OpenSSL::PKey::RSA.generate(2048) key = JSON::JWK.new(private_key) other_key = JSON::JWK.new(other_rsa_private) state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => jwt.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = { 'keys' => [other_key, key] }.to_json strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_id_token_with_kid other_rsa_private = OpenSSL::PKey::RSA.generate(2048) key = JSON::JWK.new(private_key) other_key = JSON::JWK.new(other_rsa_private) state = SecureRandom.hex(16) jwt_with_kid = JSON::JWT.new(payload).sign(key, :RS256) request.stubs(:params).returns('id_token' => jwt_with_kid.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = { 'keys' => [other_key, key] }.to_json strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_id_token_with_kid_and_no_matching_kid other_rsa_private = OpenSSL::PKey::RSA.generate(2048) key = JSON::JWK.new(private_key) other_key = JSON::JWK.new(other_rsa_private) state = SecureRandom.hex(16) jwt_with_kid = JSON::JWT.new(payload).sign(key, :RS256) request.stubs(:params).returns('id_token' => jwt_with_kid.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.client_signing_alg = :RS256 # We use private_key here instead of the wrapped key, which contains a kid strategy.options.client_jwk_signing_key = { 'keys' => [other_key, private_key] }.to_json strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) assert_raises JSON::JWK::Set::KidNotFound do strategy.callback_phase end end def test_callback_phase_with_id_token_with_hs256 state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => jwt_with_hs256.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.client_options.secret = hmac_secret strategy.options.client_signing_alg = :HS256 strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_hs256_jwt_secret state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => jwt_with_hs256.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.jwt_secret = hmac_secret strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_hs256_base64_jwt_secret state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => jwt_with_hs256.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.jwt_secret_base64 = Base64.encode64(hmac_secret) strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_id_token_no_matching_key rsa_private = OpenSSL::PKey::RSA.generate(2048) other_rsa_private = OpenSSL::PKey::RSA.generate(2048) key = JSON::JWK.new(rsa_private) other_key = JSON::JWK.new(other_rsa_private) token = JSON::JWT.new(payload).sign(rsa_private, :RS256).to_s state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => token, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = issuer strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = { 'keys' => [other_key] }.to_json strategy.options.response_type = 'id_token' strategy.unstub(:user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) assert_raises JSON::JWK::Set::KidNotFound do strategy.callback_phase end end def test_callback_phase_with_discovery state = SecureRandom.hex(16) request.stubs(:params).returns('code' => jwt.to_s, 'state' => state) request.stubs(:path_info).returns('') strategy.options.client_options.host = 'example.com' strategy.options.discovery = true issuer = stub('OpenIDConnect::Discovery::Issuer') issuer.stubs(:issuer).returns('https://example.com/') ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer) config = stub('OpenIDConnect::Discovery::Provder::Config') config.stubs(:authorization_endpoint).returns('https://example.com/authorization') config.stubs(:token_endpoint).returns('https://example.com/token') config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo') config.stubs(:jwks_uri).returns('https://example.com/jwks') config.stubs(:jwks).returns(JSON::JWK::Set.new(jwks['keys'])) ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:raw_attributes).returns('sub' => 'sub', 'name' => 'name', 'email' => 'email') id_token.stubs(:verify!).with(issuer: 'https://example.com/', client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) strategy.unstub(:user_info) access_token = stub('OpenIDConnect::AccessToken') access_token.stubs(:access_token) access_token.stubs(:refresh_token) access_token.stubs(:expires_in) access_token.stubs(:scope) access_token.stubs(:id_token).returns(jwt.to_s) client.expects(:access_token!).at_least_once.returns(access_token) access_token.expects(:userinfo!).returns(user_info) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_jwks_uri id_token = jwt.to_s state = SecureRandom.hex(16) request.stubs(:params).returns('id_token' => id_token, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.options.client_options.jwks_uri = 'https://jwks.example.com' strategy.options.response_type = 'id_token' HTTPClient .any_instance.stubs(:get_content) .with(strategy.options.client_options.jwks_uri) .returns(jwks.to_json) strategy.unstub(:user_info) access_token = stub('OpenIDConnect::AccessToken') access_token.stubs(:access_token) access_token.stubs(:refresh_token) access_token.stubs(:expires_in) access_token.stubs(:scope) access_token.stubs(:id_token).returns(id_token) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:raw_attributes).returns('sub' => 'sub', 'name' => 'name', 'email' => 'email') id_token.stubs(:verify!).with(issuer: strategy.options.issuer, client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) id_token.expects(:verify!) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase end def test_callback_phase_with_error state = SecureRandom.hex(16) request.stubs(:params).returns('error' => 'invalid_request') request.stubs(:path_info).returns('') strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}}) strategy.expects(:fail!) strategy.callback_phase end def test_callback_phase_with_invalid_state code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => 'foobar') request.stubs(:path_info).returns('') strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!) strategy.callback_phase end def test_callback_phase_without_code state = SecureRandom.hex(16) request.stubs(:params).returns('state' => state) request.stubs(:path_info).returns('') strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!).with(:missing_code, is_a(OmniAuth::OpenIDConnect::MissingCodeError)) strategy.callback_phase end def test_callback_phase_without_id_token state = SecureRandom.hex(16) request.stubs(:params).returns('state' => state) request.stubs(:path_info).returns('') strategy.options.response_type = 'id_token' strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!).with(:missing_id_token, is_a(OmniAuth::OpenIDConnect::MissingIdTokenError)) strategy.callback_phase end def test_callback_phase_without_id_token_symbol state = SecureRandom.hex(16) request.stubs(:params).returns('state' => state) request.stubs(:path_info).returns('') strategy.options.response_type = :id_token strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!).with(:missing_id_token, is_a(OmniAuth::OpenIDConnect::MissingIdTokenError)) strategy.callback_phase end def test_callback_phase_with_timeout code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.stubs(:access_token).raises(::Timeout::Error.new('error')) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).with(issuer: 'example.com', client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) strategy.callback_phase end def test_callback_phase_with_etimeout code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.stubs(:access_token).raises(::Errno::ETIMEDOUT.new('error')) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).with(issuer: 'example.com', client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) strategy.callback_phase end def test_callback_phase_with_socket_error code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.stubs(:access_token).raises(::SocketError.new('error')) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).with(issuer: 'example.com', client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) strategy.callback_phase end def test_callback_phase_with_rack_oauth2_client_error code = SecureRandom.hex(16) state = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => state) request.stubs(:path_info).returns('') strategy.options.issuer = 'example.com' strategy.stubs(:access_token).raises(::Rack::OAuth2::Client::Error.new('error', error: 'Unknown')) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.expects(:fail!) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).with(issuer: 'example.com', client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) strategy.callback_phase end def test_info info = strategy.info assert_equal user_info.name, info[:name] assert_equal user_info.email, info[:email] assert_equal user_info.email_verified, info[:email_verified] assert_equal user_info.preferred_username, info[:nickname] assert_equal user_info.given_name, info[:first_name] assert_equal user_info.family_name, info[:last_name] assert_equal user_info.gender, info[:gender] assert_equal user_info.picture, info[:image] assert_equal user_info.phone_number, info[:phone] assert_equal({ website: user_info.website }, info[:urls]) end def test_extra assert_equal({ raw_info: user_info.as_json }, strategy.extra) end def test_credentials strategy.options.issuer = 'example.com' strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = jwks.to_json id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) access_token = stub('OpenIDConnect::AccessToken') access_token.stubs(:access_token).returns(SecureRandom.hex(16)) access_token.stubs(:refresh_token).returns(SecureRandom.hex(16)) access_token.stubs(:expires_in).returns(Time.now) access_token.stubs(:scope).returns('openidconnect') access_token.stubs(:id_token).returns(jwt.to_s) client.expects(:access_token!).returns(access_token) access_token.expects(:refresh_token).returns(access_token.refresh_token) access_token.expects(:expires_in).returns(access_token.expires_in) assert_equal( { id_token: access_token.id_token, token: access_token.access_token, refresh_token: access_token.refresh_token, expires_in: access_token.expires_in, scope: access_token.scope }, strategy.credentials ) end def test_option_send_nonce strategy.options.client_options[:host] = 'foobar.com' assert(strategy.authorize_uri =~ /nonce=/, 'URI must contain nonce') strategy.options.send_nonce = false assert(!(strategy.authorize_uri =~ /nonce=/), 'URI must not contain nonce') end def test_failure_endpoint_redirect OmniAuth.config.stubs(:failure_raise_out_environments).returns([]) strategy.stubs(:env).returns({}) request.stubs(:params).returns('error' => 'access denied') result = strategy.callback_phase assert(result.is_a? Array) assert(result[0] == 302, 'Redirect') assert(result[1]["Location"] =~ /\/auth\/failure/) end def test_state strategy.options.state = -> { 42 } expected_redirect = /&state=42/ strategy.options.issuer = 'example.com' strategy.options.client_options.host = 'example.com' strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase session = { 'state' => 42 } # this should succeed as the correct state is passed with the request test_callback_phase(session, { 'state' => 42 }) # the following should fail because the wrong state is passed to the callback code = SecureRandom.hex(16) request.stubs(:params).returns('code' => code, 'state' => 43) request.stubs(:path_info).returns('') strategy.call!('rack.session' => session) strategy.expects(:fail!) strategy.callback_phase end def test_dynamic_state # Stub request parameters request.stubs(:path_info).returns('') strategy.call!('rack.session' => { }, QUERY_STRING: { state: 'abc', client_id: '123' } ) strategy.options.state = lambda { |env| # Get params from request, e.g. CGI.parse(env['QUERY_STRING']) env[:QUERY_STRING][:state] + env[:QUERY_STRING][:client_id] } expected_redirect = /&state=abc123/ strategy.options.issuer = 'example.com' strategy.options.client_options.host = 'example.com' strategy.expects(:redirect).with(regexp_matches(expected_redirect)) strategy.request_phase end def test_option_client_auth_method state = SecureRandom.hex(16) opts = strategy.options.client_options opts[:host] = 'foobar.com' strategy.options.issuer = 'foobar.com' strategy.options.client_auth_method = :not_basic strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = jwks.to_json json_response = { access_token: 'test_access_token', id_token: jwt.to_s, token_type: 'Bearer', }.to_json success = Struct.new(:status, :body).new(200, json_response) request.stubs(:path_info).returns('') strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).with(issuer: strategy.options.issuer, client_id: @identifier, nonce: nonce).returns(true) ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token) HTTPClient.any_instance.stubs(:post).with( "#{ opts.scheme }://#{ opts.host }:#{ opts.port }#{ opts.token_endpoint }", { scope: 'openid', grant_type: :client_credentials, client_id: @identifier, client_secret: @secret }, {} ).returns(success) assert(strategy.send :access_token) end def test_public_key_with_jwks strategy.options.client_signing_alg = :RS256 strategy.options.client_jwk_signing_key = jwks.to_json assert_equal JSON::JWK::Set, strategy.public_key.class end def test_public_key_with_jwk strategy.options.client_signing_alg = :RS256 jwk = jwks[:keys].first strategy.options.client_jwk_signing_key = jwk.to_json assert_equal JSON::JWK, strategy.public_key.class end def test_public_key_with_x509 strategy.options.client_signing_alg = :RS256 strategy.options.client_x509_signing_key = File.read('./test/fixtures/test.crt') assert_equal OpenSSL::PKey::RSA, strategy.public_key.class end def test_secret_with_hmac strategy.options.client_options.secret = 'secret' strategy.options.client_signing_alg = :HS256 assert_equal strategy.options.client_options.secret, strategy.secret end def test_id_token_auth_hash state = SecureRandom.hex(16) strategy.options.response_type = 'id_token' strategy.options.issuer = 'example.com' id_token = stub('OpenIDConnect::ResponseObject::IdToken') id_token.stubs(:verify!).returns(true) id_token.stubs(:raw_attributes, :to_h).returns(payload) request.stubs(:params).returns('state' => state, 'nounce' => nonce, 'id_token' => id_token) request.stubs(:path_info).returns('') strategy.stubs(:decode_id_token).returns(id_token) strategy.stubs(:stored_state).returns(state) strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce }) strategy.callback_phase auth_hash = strategy.send(:env)['omniauth.auth'] assert auth_hash.key?('provider') assert auth_hash.key?('uid') assert auth_hash.key?('info') assert auth_hash.key?('extra') assert auth_hash['extra'].key?('raw_info') end end end end gitlab-omniauth-openid-connect-0.10.1/test/strategy_test_case.rb0000644000004100000410000000435614424604376025032 0ustar www-datawww-dataclass StrategyTestCase < MiniTest::Test class DummyApp def call(env); end end attr_accessor :identifier, :secret, :issuer, :nonce def setup @identifier = '1234' @secret = '1234asdgat3' @issuer = "https://server.example.com" @nonce = SecureRandom.hex(16) end def client strategy.client end def payload { "iss": issuer, "aud": identifier, "sub": "248289761001", "nonce": nonce, "exp": Time.now.to_i + 1000, "iat": Time.now.to_i + 1000 } end def private_key @private_key ||= OpenSSL::PKey::RSA.generate(512) end def jwt @jwt ||= JSON::JWT.new(payload).sign(private_key, :RS256) end def hmac_secret @hmac_secret ||= SecureRandom.hex(16) end def jwt_with_hs256 @jwt_with_hs256 ||= JSON::JWT.new(payload).sign(hmac_secret, :HS256) end def jwks @jwks ||= begin key = JSON::JWK.new(private_key) keyset = JSON::JWK::Set.new(key) { keys: keyset } end end def user_info @user_info ||= OpenIDConnect::ResponseObject::UserInfo.new( sub: SecureRandom.hex(16), name: Faker::Name.name, email: Faker::Internet.email, email_verified: Faker::Boolean.boolean, nickname: Faker::Name.first_name, preferred_username: Faker::Internet.user_name, given_name: Faker::Name.first_name, family_name: Faker::Name.last_name, gender: 'female', picture: Faker::Internet.url + '.png', phone_number: Faker::PhoneNumber.phone_number, website: Faker::Internet.url, ) end def request @request ||= stub('Request').tap do |request| request.stubs(:params).returns({}) request.stubs(:cookies).returns({}) request.stubs(:env).returns({}) request.stubs(:scheme).returns({}) request.stubs(:ssl?).returns(false) request.stubs(:path).returns('') end end def strategy @strategy ||= OmniAuth::Strategies::OpenIDConnect.new(DummyApp.new).tap do |strategy| strategy.options.client_options.identifier = @identifier strategy.options.client_options.secret = @secret strategy.stubs(:request).returns(request) strategy.stubs(:user_info).returns(user_info) strategy.stubs(:script_name).returns('') end end end gitlab-omniauth-openid-connect-0.10.1/test/test_helper.rb0000644000004100000410000000056014424604376023445 0ustar www-datawww-datalib = File.expand_path('../../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'simplecov' require 'minitest/autorun' require 'mocha/minitest' require 'faker' require 'active_support' require 'omniauth_openid_connect' require_relative 'strategy_test_case' SimpleCov.command_name 'test' SimpleCov.start OmniAuth.config.test_mode = true gitlab-omniauth-openid-connect-0.10.1/README.md0000644000004100000410000002564414424604376021114 0ustar www-datawww-data# OmniAuth::OpenIDConnect This project was forked from [m0n9oose/omniauth_openid_connect](https://github.com/m0n9oose/omniauth_openid_connect) since a number of important bug fixes have not been merged in the past year. Originally was [omniauth-openid-connect](https://github.com/jjbohn/omniauth-openid-connect) I've forked this repository and launch as separate gem because maintaining of original was dropped. [![Build Status](https://travis-ci.org/m0n9oose/omniauth_openid_connect.png?branch=master)](https://travis-ci.org/m0n9oose/omniauth_openid_connect) ## Installation Add this line to your application's Gemfile: gem 'gitlab-omniauth-openid-connect', require: 'omniauth_openid_connect' And then execute: $ bundle Or install it yourself as: $ gem install omniauth_openid_connect ## Supported Ruby Versions OmniAuth::OpenIDConnect is tested under 2.4, 2.5, 2.6, 2.7 ## Usage Example configuration ```ruby config.omniauth :openid_connect, { name: :my_provider, scope: [:openid, :email, :profile, :address], response_type: :code, uid_field: "preferred_username", client_options: { port: 443, scheme: "https", host: "myprovider.com", identifier: ENV["OP_CLIENT_ID"], secret: ENV["OP_SECRET_KEY"], redirect_uri: "http://myapp.com/users/auth/openid_connect/callback", }, } ``` ### Options Overview | Field | Description | Required | Default | Example/Options | |------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------------------------|-----------------------------------------------------| | name | Arbitrary string to identify connection and identify it from other openid_connect providers | no | String: openid_connect | :my_idp | | issuer | Root url for the authorization server | yes | | https://myprovider.com | | discovery | Should OpenID discovery be used. This is recommended if the IDP provides a discovery endpoint. See client config for how to manually enter discovered values. | no | false | one of: true, false | | client_auth_method | Which authentication method to use to authenticate your app with the authorization server | no | Sym: basic | "basic", "jwks" | | scope | Which OpenID scopes to include (:openid is always required) | no | Array [:openid] | [:openid, :profile, :email] | | response_type | Which OAuth2 response type to use with the authorization request | no | String: code | one of: 'code', 'id_token' | | state | A value to be used for the OAuth2 state parameter on the authorization request. Can be a proc that generates a string. | no | Random 16 character string | Proc.new { SecureRandom.hex(32) } | | response_mode | The response mode per [spec](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html) | no | nil | one of: :query, :fragment, :form_post, :web_message | | display | An optional parameter to the authorization request to determine how the authorization and consent page | no | nil | one of: :page, :popup, :touch, :wap | | prompt | An optional parameter to the authrization request to determine what pages the user will be shown | no | nil | one of: :none, :login, :consent, :select_account | | send_scope_to_token_endpoint | Should the scope parameter be sent to the authorization token endpoint? | no | true | one of: true, false | | post_logout_redirect_uri | The logout redirect uri to use per the [session management draft](https://openid.net/specs/openid-connect-session-1_0.html) | no | empty | https://myapp.com/logout/callback | | uid_field | The field of the user info response to be used as a unique id | no | 'sub' | "sub", "preferred_username" | | client_options | A hash of client options detailed in its own section | yes | | | | jwt_secret | For HMAC with SHA2 (e.g. HS256) signing algorithms, specify the secret used to sign the JWT token. Defaults to the OAuth2 client secret if not specified. For secrets in binary, use `jwt_secret_base64`. | no | client_options.secret | "mysecret" | | jwt_secret_base64 | For HMAC with SHA2 (e.g. HS256) signing algorithms, specify the base64-encoded secret used to sign the JWT token. Defaults to the OAuth2 client secret if not specified. `jwt_secret` takes precedence. | no | client_options.secret | "bXlzZWNyZXQ=\n" ### Client Config Options These are the configuration options for the client_options hash of the configuration. | Field | Description | Default | Replaced by discovery? | |------------------------|-----------------------------------------------------------------|------------|------------------------| | identifier | The OAuth2 client_id | | | | secret | The OAuth2 client secret | | | | redirect_uri | The OAuth2 authorization callback url in your app | | | | scheme | The http scheme to use | https | | | host | The host of the authorization server | nil | | | port | The port for the authorization server | 443 | | | authorization_endpoint | The authorize endpoint on the authorization server | /authorize | yes | | token_endpoint | The token endpoint on the authorization server | /token | yes | | userinfo_endpoint | The user info endpoint on the authorization server | /userinfo | yes | | jwks_uri | The jwks_uri on the authorization server | /jwk | yes | | end_session_endpoint | The url to call to log the user out at the authorization server | nil | yes | ### Additional Configuration Notes * `name` is arbitrary, I recommend using the name of your provider. The name configuration exists because you could be using multiple OpenID Connect providers in a single app. **NOTE**: if you use this gem with Devise you should use `:openid_connect` name, or Devise would route to 'users/auth/:provider' rather than 'users/auth/openid_connect' * `response_type` tells the authorization server which grant type the application wants to use, currently, only `:code` (Authorization Code grant) and `:id_token` (Implicit grant) are valid. * If you want to pass `state` paramete by yourself. You can set Proc Object. e.g. `state: Proc.new { SecureRandom.hex(32) }` * `nonce` is optional. If don't want to pass "nonce" parameter to provider, You should specify `false` to `send_nonce` option. (default true) * Support for other client authentication methods. If don't specified `:client_auth_method` option, automatically set `:basic`. * Use "OpenID Connect Discovery", You should specify `true` to `discovery` option. (default false) * In "OpenID Connect Discovery", generally provider should have Webfinger endpoint. If provider does not have Webfinger endpoint, You can specify "Issuer" to option. e.g. `issuer: "https://myprovider.com"` It means to get configuration from "https://myprovider.com/.well-known/openid-configuration". * The uid is by default using the `sub` value from the `user_info` response, which in some applications is not the expected value. To avoid such limitations, the uid label can be configured by providing the omniauth `uid_field` option to a different label (i.e. `preferred_username`) that appears in the `user_info` details. * The `issuer` property should exactly match the provider's issuer link. * The `response_mode` option is optional and specifies how the result of the authorization request is formatted. * Some OpenID Connect providers require the `scope` attribute in requests to the token endpoint, even if this is not in the protocol specifications. In those cases, the `send_scope_to_token_endpoint` property can be used to add the attribute to the token request. Initial value is `true`, which means that the scope attribute is included by default. For the full low down on OpenID Connect, please check out [the spec](http://openid.net/specs/openid-connect-core-1_0.html). ## Contributing 1. Fork it ( http://github.com/m0n9oose/omniauth-openid-connect/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Cover your changes with tests and make sure they're green (`bundle install && bundle exec rake test`) 4. Commit your changes (`git commit -am 'Add some feature'`) 5. Push to the branch (`git push origin my-new-feature`) 6. Create new Pull Request gitlab-omniauth-openid-connect-0.10.1/CHANGELOG.md0000644000004100000410000001217014424604376021434 0ustar www-datawww-data# v0.10.1 (24.01.20230) - [Deprecate gem in favor of omniauth_open_id_connect](https://gitlab.com/gitlab-org/ruby/gems/gitlab-omniauth-openid-connect/-/merge_requests/26) # v0.10.0 (05.24.2022) - [Allow Omniauth v2](https:////gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/22) # v0.9.1 (01.03.2022) - [Assume public key encryption unless HMAC is specified](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/19) # v0.9.0 (01.03.2022) - [Add support for ES[256|384|512|256K] algorithms](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/17) # v0.8.0 (07.16.2021) - [Add `jwt_secret_base64` option to support binary secrets](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/12) # v0.7.0 (07.16.2021) - [Add `jwt_secret` option to support Keycloak private key](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/10) # v0.6.0 (07.08.2021) - [Support verification of HS256-signed JWTs](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/8) # v0.5.0 (05.07.2021) - [Add email_verified field to info dict](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/7) - [Simplify error handling for decoding individual keys](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/6) - [Always convert client_signing_alg to be a symbol](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/5) # v0.4.0 (04.23.2021) - [Fetch key from JWKS URI if available](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/3) - [Fix handling of JWT without key ID](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/2) - [Add .gitlab-ci.yml and test with Ruby 3.0](https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect/-/merge_requests/1) # v0.3.5 (07.06.2020) - bugfix: Info from decoded id_token is not exposed into `request.env['omniauth.auth']` [#61](https://github.com/m0n9oose/omniauth_openid_connect/pull/61) - bugfix: NoMethodError (`undefined method 'count' for #`) [#60](https://github.com/m0n9oose/omniauth_openid_connect/pull/60) # v0.3.4 (21.05.2020) - Try to verify id_token when response_type is code [#44](https://github.com/m0n9oose/omniauth_openid_connect/pull/44) - Provide more information on error [#49](https://github.com/m0n9oose/omniauth_openid_connect/pull/49) - Update configuration documentation [#53](https://github.com/m0n9oose/omniauth_openid_connect/pull/53) - Add documentation about the send_scope_to_token_endpoint config property [#52](https://github.com/m0n9oose/omniauth_openid_connect/pull/52) - refactor: take uid_field from raw_attributes [#54](https://github.com/m0n9oose/omniauth_openid_connect/pull/54) - chore(ci): add 2.7, ruby-head and jruby-head [#55](https://github.com/m0n9oose/omniauth_openid_connect/pull/55) # v0.3.3 (09.11.2019) - Pass `acr_values` to authorize url [#43](https://github.com/m0n9oose/omniauth_openid_connect/pull/43) - Add raw info for id token [#42](https://github.com/m0n9oose/omniauth_openid_connect/pull/42) - Fixed `id_token` verification when `id_token` is not used [#41](https://github.com/m0n9oose/omniauth_openid_connect/pull/41) - Cast `response_type` to string when checking if it is set in params [#36](https://github.com/m0n9oose/omniauth_openid_connect/pull/36) - Support both symbol and string version of `response_type` option [#35](https://github.com/m0n9oose/omniauth_openid_connect/pull/35) - Fix gemspec homepage [#33](https://github.com/m0n9oose/omniauth_openid_connect/pull/33) - Add support for `response_type` `id_token` [#32](https://github.com/m0n9oose/omniauth_openid_connect/pull/32) # v0.3.2 (03.08.2019) - Use response_mode in `authorize_uri` if the option is defined [#30](https://github.com/m0n9oose/omniauth_openid_connect/pull/30) - Move verification of `id_token` to before accessing tokens [#28](https://github.com/m0n9oose/omniauth_openid_connect/pull/28) - Update omniauth dependency [#26](https://github.com/m0n9oose/omniauth_openid_connect/pull/26) # v0.3.1 (08.06.2019) - Set default OmniAuth name to openid_connect [#23](https://github.com/m0n9oose/omniauth_openid_connect/pull/23) # v0.3.0 (27.04.2019) - RP-Initiated Logout phase [#5](https://github.com/m0n9oose/omniauth_openid_connect/pull/5) - Allows `ui_locales`, `claims_locales` and `login_hint` as request params [#6](https://github.com/m0n9oose/omniauth_openid_connect/pull/6) - Make uid label configurable [#11](https://github.com/m0n9oose/omniauth_openid_connect/pull/11) - Allow rails applications to handle state mismatch [#14](https://github.com/m0n9oose/omniauth_openid_connect/pull/14) - Handle errors when fetching access_token at callback_phase [#17](https://github.com/m0n9oose/omniauth_openid_connect/pull/17) - Allow state method to receive env [#19](https://github.com/m0n9oose/omniauth_openid_connect/pull/19) # v0.2.4 (06.01.2019) - Prompt and login hint [#4](https://github.com/m0n9oose/omniauth_openid_connect/pull/4) - Bump openid_connect dependency [#9](https://github.com/m0n9oose/omniauth_openid_connect/pull/9) gitlab-omniauth-openid-connect-0.10.1/.rubocop.yml0000644000004100000410000000202214424604376022070 0ustar www-datawww-dataLineLength: Description: 'Limit lines to 130 characters.' Max: 130 Layout/SpaceInsideStringInterpolation: Enabled: false Layout/MultilineOperationIndentation: EnforcedStyle: indented StringLiterals: EnforcedStyle: single_quotes Style/TrailingCommaInArrayLiteral: EnforcedStyleForMultiline: comma Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma Style/SafeNavigation: Enabled: false Style/EmptyMethod: Description: 'Checks the formatting of empty method definitions.' StyleGuide: '#no-single-line-methods' Enabled: false HashSyntax: Description: "Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax\n{ :a => 1, :b => 2 }" EnforcedStyle: ruby19 Enabled: true RedundantBegin: Enabled: true Documentation: Enabled: false Metrics/AbcSize: Max: 50 Metrics/CyclomaticComplexity: Max: 50 Metrics/PerceivedComplexity: Max: 15 Metrics/BlockLength: Max: 40 Metrics/MethodLength: Max: 45 AllCops: Exclude: - bin/**/* - Rakefile - config/**/* - test/**/* gitlab-omniauth-openid-connect-0.10.1/.gitignore0000644000004100000410000000027314424604376021614 0ustar www-datawww-data*.gem *.rbc .bundle .config .idea .yardoc InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp .ruby-version .ruby-gemset Gemfile.lock gitlab-omniauth-openid-connect-0.10.1/NOTICE0000644000004100000410000000107714424604376020533 0ustar www-datawww-data############################################################ # Deprecation notice for gitlab-omniauth-openid-connect gem ############################################################ All changes in this gem are now upstreamed in omniauth_openid_connect gem v0.6.0 under the OmniAuth group: https://github.com/omniauth/omniauth_openid_connect. In your Gemfile, replace the line: gem 'gitlab-omniauth-openid-connect', '~> 0.10', require: 'omniauth_openid_connect' With: gem 'omniauth_openid_connect', '~> 0.6' The gitlab-omniauth-openid-connect gem is no longer updated. gitlab-omniauth-openid-connect-0.10.1/Rakefile0000644000004100000410000000031214424604376021263 0ustar www-datawww-datarequire 'bundler/gem_tasks' require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' t.test_files = FileList['test/lib/omniauth/**/*_test.rb'] t.verbose = true end task default: :test gitlab-omniauth-openid-connect-0.10.1/lib/0000755000004100000410000000000014424604376020370 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/lib/omniauth/0000755000004100000410000000000014424604376022214 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/lib/omniauth/strategies/0000755000004100000410000000000014424604376024366 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/lib/omniauth/strategies/openid_connect.rb0000644000004100000410000003301414424604376027703 0ustar www-datawww-data# frozen_string_literal: true require 'addressable/uri' require 'base64' require 'timeout' require 'net/http' require 'open-uri' require 'omniauth' require 'openid_connect' require 'forwardable' module OmniAuth module Strategies class OpenIDConnect include OmniAuth::Strategy extend Forwardable RESPONSE_TYPE_EXCEPTIONS = { 'id_token' => { exception_class: OmniAuth::OpenIDConnect::MissingIdTokenError, key: :missing_id_token }.freeze, 'code' => { exception_class: OmniAuth::OpenIDConnect::MissingCodeError, key: :missing_code }.freeze, }.freeze def_delegator :request, :params option :name, 'openid_connect' option(:client_options, identifier: nil, secret: nil, redirect_uri: nil, scheme: 'https', host: nil, port: 443, authorization_endpoint: '/authorize', token_endpoint: '/token', userinfo_endpoint: '/userinfo', jwks_uri: '/jwk', end_session_endpoint: nil) option :issuer option :discovery, false option :client_signing_alg # Deprecated since we detect what is used to sign the JWT option :jwt_secret option :jwt_secret_base64 option :client_jwk_signing_key option :client_x509_signing_key option :scope, [:openid] option :response_type, 'code' # ['code', 'id_token'] option :state option :response_mode # [:query, :fragment, :form_post, :web_message] option :display, nil # [:page, :popup, :touch, :wap] option :prompt, nil # [:none, :login, :consent, :select_account] option :hd, nil option :max_age option :ui_locales option :id_token_hint option :acr_values option :send_nonce, true option :send_scope_to_token_endpoint, true option :client_auth_method option :post_logout_redirect_uri option :extra_authorize_params, {} option :uid_field, 'sub' def uid user_info.raw_attributes[options.uid_field.to_sym] || user_info.sub end info do { name: user_info.name, email: user_info.email, email_verified: user_info.email_verified, nickname: user_info.preferred_username, first_name: user_info.given_name, last_name: user_info.family_name, gender: user_info.gender, image: user_info.picture, phone: user_info.phone_number, urls: { website: user_info.website }, } end extra do { raw_info: user_info.raw_attributes } end credentials do { id_token: access_token.id_token, token: access_token.access_token, refresh_token: access_token.refresh_token, expires_in: access_token.expires_in, scope: access_token.scope, } end def client @client ||= ::OpenIDConnect::Client.new(client_options) end def config @config ||= ::OpenIDConnect::Discovery::Provider::Config.discover!(options.issuer) end def request_phase options.issuer = issuer if options.issuer.to_s.empty? discover! redirect authorize_uri end def callback_phase error = params['error_reason'] || params['error'] error_description = params['error_description'] || params['error_reason'] invalid_state = params['state'].to_s.empty? || params['state'] != stored_state raise CallbackError, error: params['error'], reason: error_description, uri: params['error_uri'] if error raise CallbackError, error: :csrf_detected, reason: "Invalid 'state' parameter" if invalid_state return unless valid_response_type? options.issuer = issuer if options.issuer.nil? || options.issuer.empty? verify_id_token!(params['id_token']) if configured_response_type == 'id_token' discover! client.redirect_uri = redirect_uri return id_token_callback_phase if configured_response_type == 'id_token' client.authorization_code = authorization_code access_token super rescue CallbackError => e fail!(e.error, e) rescue ::Rack::OAuth2::Client::Error => e fail!(e.response[:error], e) rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e fail!(:timeout, e) rescue ::SocketError => e fail!(:failed_to_connect, e) end def other_phase if logout_path_pattern.match?(current_path) options.issuer = issuer if options.issuer.to_s.empty? discover! return redirect(end_session_uri) if end_session_uri end call_app! end def authorization_code params['code'] end def end_session_uri return unless end_session_endpoint_is_valid? end_session_uri = URI(client_options.end_session_endpoint) end_session_uri.query = encoded_post_logout_redirect_uri end_session_uri.to_s end def authorize_uri client.redirect_uri = redirect_uri opts = { response_type: options.response_type, response_mode: options.response_mode, scope: options.scope, state: new_state, login_hint: params['login_hint'], ui_locales: params['ui_locales'], claims_locales: params['claims_locales'], prompt: options.prompt, nonce: (new_nonce if options.send_nonce), hd: options.hd, acr_values: options.acr_values, } opts.merge!(options.extra_authorize_params) unless options.extra_authorize_params.empty? client.authorization_uri(opts.reject { |_k, v| v.nil? }) end def public_key @public_key ||= begin if options.discovery config.jwks elsif configured_public_key configured_public_key elsif client_options.jwks_uri fetch_key end end end # Some OpenID providers use the OAuth2 client secret as the shared secret, but # Keycloak uses a separate key that's stored inside the database. def secret options.jwt_secret || base64_decoded_jwt_secret || client_options.secret end private def base64_decoded_jwt_secret return unless options.jwt_secret_base64 Base64.decode64(options.jwt_secret_base64) end def fetch_key @fetch_key ||= parse_jwk_key(::OpenIDConnect.http_client.get_content(client_options.jwks_uri)) end def issuer resource = "#{ client_options.scheme }://#{ client_options.host }" resource = "#{ resource }:#{ client_options.port }" if client_options.port ::OpenIDConnect::Discovery::Provider.discover!(resource).issuer end def discover! return unless options.discovery client_options.authorization_endpoint = config.authorization_endpoint client_options.token_endpoint = config.token_endpoint client_options.userinfo_endpoint = config.userinfo_endpoint client_options.jwks_uri = config.jwks_uri client_options.end_session_endpoint = config.end_session_endpoint if config.respond_to?(:end_session_endpoint) end def user_info return @user_info if @user_info if access_token.id_token decoded = decode_id_token(access_token.id_token).raw_attributes @user_info = ::OpenIDConnect::ResponseObject::UserInfo.new access_token.userinfo!.raw_attributes.merge(decoded) else @user_info = access_token.userinfo! end end def access_token return @access_token if @access_token @access_token = client.access_token!( scope: (options.scope if options.send_scope_to_token_endpoint), client_auth_method: options.client_auth_method ) verify_id_token!(@access_token.id_token) if configured_response_type == 'code' @access_token end # Unlike ::OpenIDConnect::ResponseObject::IdToken.decode, this # method splits the decoding and verification of JWT into two # steps. First, we decode the JWT without verifying it to # determine the algorithm used to sign. Then, we verify it using # the appropriate public key (e.g. if algorithm is RS256) or # shared secret (e.g. if algorithm is HS256). This works around a # limitation in the openid_connect gem: # https://github.com/nov/openid_connect/issues/61 def decode_id_token(id_token) decoded = JSON::JWT.decode(id_token, :skip_verification) algorithm = decoded.algorithm.to_sym keyset = case algorithm when :HS256, :HS384, :HS512 secret else public_key end decoded.verify!(keyset) ::OpenIDConnect::ResponseObject::IdToken.new(decoded) rescue JSON::JWK::Set::KidNotFound # If the JWT has a key ID (kid), then we know that the set of # keys supplied doesn't contain the one we want, and we're # done. However, if there is no kid, then we try each key # individually to see if one works: # https://github.com/nov/json-jwt/pull/92#issuecomment-824654949 raise if decoded&.header&.key?('kid') decoded = decode_with_each_key!(id_token, keyset) raise unless decoded decoded end def decode!(id_token, key) ::OpenIDConnect::ResponseObject::IdToken.decode(id_token, key) end def decode_with_each_key!(id_token, keyset) return unless keyset.is_a?(JSON::JWK::Set) keyset.each do |key| begin decoded = decode!(id_token, key) rescue JSON::JWS::VerificationFailed, JSON::JWS::UnexpectedAlgorithm, JSON::JWS::UnknownAlgorithm next end return decoded if decoded end nil end def client_options options.client_options end def new_state state = if options.state.respond_to?(:call) if options.state.arity == 1 options.state.call(env) else options.state.call end end session['omniauth.state'] = state || SecureRandom.hex(16) end def stored_state session.delete('omniauth.state') end def new_nonce session['omniauth.nonce'] = SecureRandom.hex(16) end def stored_nonce session.delete('omniauth.nonce') end def session return {} if @env.nil? super end def configured_public_key @configured_public_key ||= begin if options.client_jwk_signing_key parse_jwk_key(options.client_jwk_signing_key) elsif options.client_x509_signing_key parse_x509_key(options.client_x509_signing_key) end end end def parse_x509_key(key) OpenSSL::X509::Certificate.new(key).public_key end def parse_jwk_key(key) json = JSON.parse(key) return JSON::JWK::Set.new(json['keys']) if json.key?('keys') JSON::JWK.new(json) end def decode(str) UrlSafeBase64.decode64(str).unpack1('B*').to_i(2).to_s end def redirect_uri return client_options.redirect_uri unless params['redirect_uri'] "#{ client_options.redirect_uri }?redirect_uri=#{ CGI.escape(params['redirect_uri']) }" end def encoded_post_logout_redirect_uri return unless options.post_logout_redirect_uri URI.encode_www_form( post_logout_redirect_uri: options.post_logout_redirect_uri ) end def end_session_endpoint_is_valid? client_options.end_session_endpoint && client_options.end_session_endpoint =~ URI::DEFAULT_PARSER.make_regexp end def logout_path_pattern @logout_path_pattern ||= %r{\A#{Regexp.quote(request_path)}(/logout)} end def id_token_callback_phase user_data = decode_id_token(params['id_token']).raw_attributes env['omniauth.auth'] = AuthHash.new( provider: name, uid: user_data['sub'], info: { name: user_data['name'], email: user_data['email'] }, extra: { raw_info: user_data } ) call_app! end def valid_response_type? return true if params.key?(configured_response_type) error_attrs = RESPONSE_TYPE_EXCEPTIONS[configured_response_type] fail!(error_attrs[:key], error_attrs[:exception_class].new(params['error'])) false end def configured_response_type @configured_response_type ||= options.response_type.to_s end def verify_id_token!(id_token) return unless id_token decode_id_token(id_token).verify!(issuer: options.issuer, client_id: client_options.identifier, nonce: stored_nonce) end class CallbackError < StandardError attr_accessor :error, :error_reason, :error_uri def initialize(data) super self.error = data[:error] self.error_reason = data[:reason] self.error_uri = data[:uri] end def message [error, error_reason, error_uri].compact.join(' | ') end end end end end OmniAuth.config.add_camelization 'openid_connect', 'OpenIDConnect' gitlab-omniauth-openid-connect-0.10.1/lib/omniauth/openid_connect.rb0000644000004100000410000000023714424604376025532 0ustar www-datawww-data# frozen_string_literal: true require 'omniauth/openid_connect/errors' require 'omniauth/openid_connect/version' require 'omniauth/strategies/openid_connect' gitlab-omniauth-openid-connect-0.10.1/lib/omniauth/openid_connect/0000755000004100000410000000000014424604376025203 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/lib/omniauth/openid_connect/version.rb0000644000004100000410000000014714424604376027217 0ustar www-datawww-data# frozen_string_literal: true module OmniAuth module OpenIDConnect VERSION = '0.10.1' end end gitlab-omniauth-openid-connect-0.10.1/lib/omniauth/openid_connect/errors.rb0000644000004100000410000000030714424604376027044 0ustar www-datawww-data# frozen_string_literal: true module OmniAuth module OpenIDConnect class Error < RuntimeError; end class MissingCodeError < Error; end class MissingIdTokenError < Error; end end end gitlab-omniauth-openid-connect-0.10.1/lib/omniauth_openid_connect.rb0000644000004100000410000000010114424604376025600 0ustar www-datawww-data# frozen_string_literal: true require 'omniauth/openid_connect' gitlab-omniauth-openid-connect-0.10.1/CONTRIBUTING.md0000644000004100000410000000424114424604376022054 0ustar www-datawww-data## Developer Certificate of Origin and License By contributing to GitLab B.V., you accept and agree to the following terms and conditions for your present and future contributions submitted to GitLab B.V. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., you reserve all right, title, and interest in and to your Contributions. All contributions are subject to the Developer Certificate of Origin and license set out at [docs.gitlab.com/ce/legal/developer_certificate_of_origin](https://docs.gitlab.com/ce/legal/developer_certificate_of_origin). _This notice should stay as the first item in the CONTRIBUTING.md file._ ## Code of conduct As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing contact@gitlab.com. This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org), version 1.1.0, available at [https://contributor-covenant.org/version/1/1/0/](https://contributor-covenant.org/version/1/1/0/). gitlab-omniauth-openid-connect-0.10.1/gitlab-omniauth-openid-connect.gemspec0000644000004100000410000000313714424604376027162 0ustar www-datawww-data# frozen_string_literal: true lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'omniauth/openid_connect/version' Gem::Specification.new do |spec| spec.name = 'gitlab-omniauth-openid-connect' spec.version = OmniAuth::OpenIDConnect::VERSION spec.authors = ['John Bohn', 'Ilya Shcherbinin'] spec.email = ['jjbohn@gmail.com', 'm0n9oose@gmail.com'] spec.summary = 'OpenID Connect Strategy for OmniAuth' spec.description = 'OpenID Connect Strategy for OmniAuth.' spec.homepage = 'https://gitlab.com/gitlab-org/gitlab-omniauth-openid-connect' spec.license = 'MIT' spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] spec.post_install_message = File.read('NOTICE') if File.exist?('NOTICE') spec.add_dependency 'addressable', '~> 2.7' spec.add_dependency 'omniauth', '>= 1.9', '< 3' spec.add_dependency 'openid_connect', '~> 1.2' spec.add_development_dependency 'faker', '~> 2.17' spec.add_development_dependency 'guard', '~> 2.14' spec.add_development_dependency 'guard-bundler', '~> 3.0' spec.add_development_dependency 'guard-minitest', '~> 2.4' spec.add_development_dependency 'minitest', '~> 5.14' spec.add_development_dependency 'mocha', '~> 1.12' spec.add_development_dependency 'rake', '~> 13.0' spec.add_development_dependency 'rubocop', '~> 1.12' spec.add_development_dependency 'simplecov', '~> 0.16' end gitlab-omniauth-openid-connect-0.10.1/Guardfile0000644000004100000410000000055714424604376021456 0ustar www-datawww-data# frozen_string_literal: true # A sample Guardfile # More info at https://github.com/guard/guard#readme guard 'minitest' do # with Minitest::Unit watch(%r{^test/(.*)\/(.*)_test\.rb}) watch(%r{^lib/(.*)\.rb}) { |m| "test/lib/#{m[1]}_test.rb" } watch(%r{^test/test_helper\.rb}) { 'test' } end guard :bundler do watch('Gemfile') watch(/^.+\.gemspec/) end gitlab-omniauth-openid-connect-0.10.1/Gemfile0000644000004100000410000000010514424604376021111 0ustar www-datawww-data# frozen_string_literal: true source 'https://rubygems.org' gemspec gitlab-omniauth-openid-connect-0.10.1/.github/0000755000004100000410000000000014424604376021162 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/.github/stale.yml0000644000004100000410000000125414424604376023017 0ustar www-datawww-data# Number of days of inactivity before an issue becomes stale daysUntilStale: 60 # Number of days of inactivity before a stale issue is closed daysUntilClose: 7 # Issues with these labels will never be considered stale exemptLabels: - pinned - security # Label to use when marking an issue as stale staleLabel: wontfix # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false gitlab-omniauth-openid-connect-0.10.1/.github/workflows/0000755000004100000410000000000014424604376023217 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/.github/workflows/rubocop.yml0000644000004100000410000000073214424604376025415 0ustar www-datawww-dataname: Rubocop check on: pull_request: branches: - "*" push: branches: - master jobs: build: name: RuboCop Action runs-on: ubuntu-latest steps: - name: Checkout Action uses: actions/checkout@v1 - name: Rubocop Linter Action uses: andrewmcodes/rubocop-linter-action@v3.2.0 with: action_config_path: '.github/config/rubocop_linter_action.yml' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} gitlab-omniauth-openid-connect-0.10.1/.github/config/0000755000004100000410000000000014424604376022427 5ustar www-datawww-datagitlab-omniauth-openid-connect-0.10.1/.github/config/rubocop_linter_action.yml0000644000004100000410000000512014424604376027533 0ustar www-datawww-data# Description: The name of the check that will be created. # Valid Options: A reasonably sized string. # Default: 'Rubocop Action' check_name: 'Rubocop Results' # Description: Versions required to run your RuboCop checks. # Valid options: RuboCop and any RuboCop extension, by default the latest gem version will be used. You can explicitly state that # (not required) or use a version number, like '1.5.1'. # Default: # versions: # - rubocop: 'latest' versions: - rubocop - rubocop-minitest - rubocop-performance: '1.5.1' # Description: Rubocop configuration file path relative to the workspace. # Valid options: A valid file path inside of the workspace. # Default: nil # Note: This does not need to be filled out for Rubocop to still find your config. # Resource: https://rubocop.readthedocs.io/en/stable/configuration/ rubocop_config_path: '.rubocop.yml' # Run all cops enabled by configuration except this list. # Valid options: list of valid cop(s) and/or departments. # Default: nil # Resource: https://rubocop.readthedocs.io/en/stable/cops/ # rubocop_excluded_cops: # - 'Style/FrozenStringLiteralComment' # Minimum severity for exit with error code # Valid options: 'refactor', 'convention', 'warning', 'error', or 'fatal'. # Default: 'warning' # Resource: https://rubocop.readthedocs.io/en/stable/configuration/#severity # rubocop_fail_level: 'warning' # Whether or not to use --force-exclusion when building the rubocop command. Use this if you are only linting modified # files and typically excluded files have been changed. For example, if you exclude db/schema.rb in your rubocop.yml # but a change gets made, then with the check_scope config set to 'modified' rubocop will lint db/schema.rb. If you set # this to true, rubocop will ignore it. # Valid options: true || false # Default: false # Instead of installing gems from rubygems, we can run `bundle install` on your project, # you would need to do this if you are using something like 'rubocop-github' or if you don't # want to list out dependencies with the `versions` key. # Valid options: true || false # Default: false # bundle: false # The scope of code that Rubocop should lint. Use this if you only want to lint changed files. If this is not set # or not equal to 'modified', Rubocop is run against the entire codebase. Note that this will not work on the master branch. # Valid options: 'modified' # Default: nil # The base branch against which changes will be compared, if check_scope config is set to 'modified'. # This setting is not used if check_scope != 'modified'. # Valid options: 'origin/another_branch' # Default: 'origin/master' gitlab-omniauth-openid-connect-0.10.1/LICENSE.txt0000644000004100000410000000205214424604376021444 0ustar www-datawww-dataCopyright (c) 2014 John Bohn MIT License 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. gitlab-omniauth-openid-connect-0.10.1/.gitlab-ci.yml0000644000004100000410000000100214424604376022247 0ustar www-datawww-data.test-template: &test cache: paths: - vendor/ruby before_script: - gem install bundler --no-document - bundle config set --local path 'vendor/ruby' - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby - ruby -v # Print out ruby version for debugging script: - bundle exec rake test rspec: image: "ruby:${RUBY_VERSION}" parallel: matrix: - RUBY_VERSION: [ "2.6", "2.7", "3.0", "3.1" ] <<: *test