# Lower some rate limits for testing
max_changeset_comments_per_hour: 30
moderator_changeset_comments_per_hour: 60
+# Private key for signing id_tokens
+doorkeeper_signing_key: |
+ -----BEGIN PRIVATE KEY-----
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDA4pSRHIicerJQ
+ BvIy9lGJ6ZQA7SAGVM8QeNMBaQftS+ROMY+6CFCJ0kiwb9oDdtFNyo3gpgmlULMC
+ q0C96r0UllKnTSkHSntkKM0wy3TX0pa8QBaJbbcOXU13xu5cR7ffvtn2kQX8RZc9
+ eZtE/bSybNBDSiS4mbP31cSQ71EYsbfD3UiWOpOTbc6Xlw9kCkUjwXk36Jnim7gF
+ 1kFjD3Vq94ij4OVNxcFp+btrfhq2tsiXa9IPBlt1xTetHwj5HrxseDu2qNQNgPxY
+ ivFAA3t4BuIuou1HjAdzfqp7Ylsr2b7qx+w+Y9TqhH6AcKd0i1qxh6bYnJezH9JU
+ BjlJvJMhAgMBAAECggEAAID2/gldiqRqunkc1n48iJ2CufKPRAT3r3rT+OvNzf8F
+ 6csJAuWKVE8ndR0trBb6L/eooYloJWA4aiLes0BIMyQQs4go5HB7hwTw7ZYycsKF
+ i0NS676iHO2odKN2iZN/CvIO1AKH9KM35GdgvPA5XG1FU/pUbeOqNn+pQ5mkaWnt
+ kt+ndBpJQDPSS7nTY8g2BCh97SJSbxEPAccAqNLSvKQED4QVygC63jYZNPDxkJWI
+ guzNn4wv1AfM0DU4W5fI0UtNSxcWSsefWBJTOKO/uQr/XJglxVh6uKof1dnBZiJD
+ KU6/+bR1cXoKQ05HAcEcf/mtjJGwnze41p1EI22gYQKBgQDB+VZJwvxlME1MgEGJ
+ WFPPKiQspKjS0kgbfBw7Iny+mYM6YLpQyF0NFNRloALW2rHH2QLNSerHMlytZUAd
+ 1SluQZ4We6P3hLDi2J3p37lkIdBXhjJi8gdoEfQ1YVcCbPGbR2ZVwYms7BP3yiQY
+ ZLcHLUKPKG6hOZztY1gBYqoKqQKBgQD+kBtR8krdJHPEU3m+d/6NWlGk4KZgCFx5
+ ouN/aHtxE6Ge+mUwbrJun/oVrFjbX7ySYTYYb6SdKUrchyKfJL4Z89WHGwrFTV1/
+ 6J2ShXmoeUeic1TS4btcnFmZyCXlADk1eyHZm9wtkwd5e2lBfdRxzErKC42lWdaQ
+ rreP2nZHuQKBgQCiNbVgB6vznrn1kIe9qFylsJMBtkzryCe+vEILfaKd7VhdOEh2
+ h6ew6ctYlL/rFoV3H1YFgJvSKp5v7mz4xapY5oyiNpD+yzr06LrdulaZkuFcX//A
+ 2K8y61iyTw1pHNvKw6Gjcy6DqgRkwej/cTHR0ZqIhwJE1x4RMnOE7RJPyQKBgQCM
+ SLYFjtSa0b/KbYYl5NKu6xsbFYIaYgE0NwPP7rA4PG1QwwSIkDhcpmSXFQdSvYuZ
+ z2CUTtIUmfDbXs1BjmoEu07syYZB/MSN/I75c/z7TvqfF5ejLyqlerQV/yqC7ICa
+ bGTXGwFXTDNOSyhSIxm0LLT6ayt/9+Y6jU4zRFzyYQKBgGiScevkv/XNz9MXswJ+
+ 2bEIJNIJn0wIeuopifcDQrOTeCK+037t1AQ3lxMXisJABwG1jfw7WTjF3zz4dSUX
+ cK1+/2V+OkM/0nXjxPwPj7LiOediUyZNUn48r29uGOL1S83PSUdyST207CP6mZjc
+ K8aJmnGsVEAcWPzbpNh14q/c
+ -----END PRIVATE KEY-----
require "test_helper"
+require "jwt"
class OAuth2Test < ActionDispatch::IntegrationTest
def test_oauth2
token = request_token(client, code)
- test_token(token, user, client)
+ assert_equal "read_prefs", token["scope"]
+ test_token(token["access_token"], user, client)
end
def test_oauth2_oob
token = request_token(client, code)
- test_token(token, user, client)
+ assert_equal "read_prefs", token["scope"]
+ test_token(token["access_token"], user, client)
end
def test_oauth2_pkce_plain
token = request_token(client, code, verifier)
- test_token(token, user, client)
+ assert_equal "read_prefs", token["scope"]
+ test_token(token["access_token"], user, client)
end
def test_oauth2_pkce_s256
token = request_token(client, code, verifier)
- test_token(token, user, client)
+ assert_equal "read_prefs", token["scope"]
+ test_token(token["access_token"], user, client)
+ end
+
+ def test_openid_connect
+ user = create(:user)
+ client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "openid read_prefs")
+ state = SecureRandom.urlsafe_base64(16)
+ verifier = SecureRandom.urlsafe_base64(48)
+ challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(verifier), :padding => false)
+
+ authorize_client(user, client, :state => state, :code_challenge => challenge, :code_challenge_method => "S256", :scope => "openid read_prefs")
+ assert_response :redirect
+ code = validate_redirect(client, state)
+
+ token = request_token(client, code, verifier)
+
+ assert_equal "openid read_prefs", token["scope"]
+
+ access_token = token["access_token"]
+ assert_not_nil access_token
+
+ id_token = token["id_token"]
+ assert_not_nil id_token
+
+ data, _headers = JWT.decode id_token, Doorkeeper::OpenidConnect.signing_key.keypair, true, {
+ :algorithm => [Doorkeeper::OpenidConnect.signing_algorithm.to_s],
+ :verify_iss => true,
+ :iss => "#{Settings.server_protocol}://#{Settings.server_url}",
+ :verify_sub => true,
+ :sub => user.id,
+ :verify_aud => true,
+ :aud => client.uid
+ }
+
+ assert_equal user.id.to_s, data["sub"]
+ assert_not data.key?("preferred_username")
+
+ get oauth_userinfo_path
+ assert_response :unauthorized
+
+ auth_header = bearer_authorization_header(access_token)
+ get oauth_userinfo_path, :headers => auth_header
+ assert_response :success
+
+ userinfo = response.parsed_body
+
+ assert_not_nil userinfo
+ assert_equal user.id.to_s, userinfo["sub"]
+ assert_equal user.display_name, userinfo["preferred_username"]
end
private
def authorize_client(user, client, options = {})
- options = options.merge(:client_id => client.uid,
- :redirect_uri => client.redirect_uri,
- :response_type => "code",
- :scope => "read_prefs")
+ options = {
+ :client_id => client.uid,
+ :redirect_uri => client.redirect_uri,
+ :response_type => "code",
+ :scope => "read_prefs"
+ }.merge(options)
get oauth_authorization_path(options)
assert_response :redirect
assert_response :success
token = response.parsed_body
assert_equal "Bearer", token["token_type"]
- assert_equal "read_prefs", token["scope"]
- token["access_token"]
+ token
end
def test_token(token, user, client)