Implement OAuth Userinfo Endpoint

This commit is contained in:
Emelia Smith 2024-10-16 21:19:07 +02:00
parent 8b56509625
commit fca51d0397
No known key found for this signature in database
5 changed files with 83 additions and 0 deletions

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Oauth::UserinfoController < Api::BaseController
before_action -> { doorkeeper_authorize! :profile }, only: [:show]
before_action :require_user!
def show
@account = current_account
render json: @account, serializer: OauthUserinfoSerializer
end
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
class OauthUserinfoSerializer < ActiveModel::Serializer
include RoutingHelper
attributes :iss, :sub, :name, :preferred_username, :profile, :picture
def iss
root_url
end
def sub
ActivityPub::TagManager.instance.uri_for(object)
end
def name
object.unavailable? ? '' : object.display_name
end
def preferred_username
object.username
end
def profile
ActivityPub::TagManager.instance.url_for(object)
end
def picture
full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_original_url)
end
end

View File

@ -23,6 +23,7 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do
methods: %i(post put delete get patch options)
resource '/oauth/token', methods: [:post]
resource '/oauth/revoke', methods: [:post]
resource '/oauth/userinfo', methods: [:get]
end
end
end

View File

@ -64,6 +64,10 @@ Rails.application.routes.draw do
tokens: 'oauth/tokens'
end
namespace :oauth do
get 'userinfo', to: 'userinfo#show', defaults: { format: 'json' }
end
scope path: '.well-known' do
scope module: :well_known do
get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' }

View File

@ -0,0 +1,36 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Oauth Userinfo Endpoint' do
include RoutingHelper
describe 'GET /oauth/userinfo' do
subject do
get '/oauth/userinfo', headers: headers
end
let(:user) { Fabricate(:user) }
let(:account) { user.account }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'profile' }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
it 'returns http success' do
subject
expect(response).to have_http_status(:success)
expect(response.content_type).to start_with('application/json')
expect(response.parsed_body).to include({
iss: root_url,
sub: account_url(account),
name: account.display_name,
preferred_username: account.username,
profile: short_account_url(account),
picture: full_asset_url(account.unavailable? ? account.avatar.default_url : account.avatar_original_url),
})
end
end
end