Replace user info endpoint with supported claims
The route /api/v0/user/ will now be used as a non-OIDC route. In other words, the /api/v0/user/ will require the "read" scope while /api/openid_connect/user_info/ will require the "openid" scope
This commit is contained in:
parent
2be932ceff
commit
d834a1d4d0
11 changed files with 68 additions and 23 deletions
|
|
@ -25,8 +25,8 @@ module Api
|
||||||
request_object_signing_alg_values_supported: %i(HS256 HS384 HS512),
|
request_object_signing_alg_values_supported: %i(HS256 HS384 HS512),
|
||||||
subject_types_supported: %w(public pairwise),
|
subject_types_supported: %w(public pairwise),
|
||||||
id_token_signing_alg_values_supported: %i(RS256),
|
id_token_signing_alg_values_supported: %i(RS256),
|
||||||
token_endpoint_auth_methods_supported: %w(client_secret_basic client_secret_post)
|
token_endpoint_auth_methods_supported: %w(client_secret_basic client_secret_post),
|
||||||
# TODO: claims_supported: ["sub", "iss", "name", "email"]
|
claims_supported: %w(sub nickname profile picture zoneinfo)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
19
app/controllers/api/openid_connect/user_info_controller.rb
Normal file
19
app/controllers/api/openid_connect/user_info_controller.rb
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Api
|
||||||
|
module OpenidConnect
|
||||||
|
class UserInfoController < ApplicationController
|
||||||
|
include Api::OpenidConnect::ProtectedResourceEndpoint
|
||||||
|
|
||||||
|
before_action do
|
||||||
|
require_access_token Api::OpenidConnect::Scope.find_by(name: "openid")
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
render json: current_user, serializer: UserInfoSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
current_token ? current_token.authorization.user : nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
23
app/serializers/user_info_serializer.rb
Normal file
23
app/serializers/user_info_serializer.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
class UserInfoSerializer < ActiveModel::Serializer
|
||||||
|
attributes :sub, :nickname, :profile, :picture, :zoneinfo
|
||||||
|
|
||||||
|
def sub
|
||||||
|
object.diaspora_handle # TODO: Change to proper sub
|
||||||
|
end
|
||||||
|
|
||||||
|
def nickname
|
||||||
|
object.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile
|
||||||
|
File.join(AppConfig.environment.url, "people", object.guid).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def picture
|
||||||
|
File.join(AppConfig.environment.url, object.image_url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def zoneinfo
|
||||||
|
object.language
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
class UserSerializer < ActiveModel::Serializer
|
|
||||||
attributes :name, :email, :language, :username
|
|
||||||
end
|
|
||||||
|
|
@ -250,6 +250,8 @@ Diaspora::Application.routes.draw do
|
||||||
get ".well-known/webfinger", to: "discovery#webfinger"
|
get ".well-known/webfinger", to: "discovery#webfinger"
|
||||||
get ".well-known/openid-configuration", to: "discovery#configuration"
|
get ".well-known/openid-configuration", to: "discovery#configuration"
|
||||||
get "jwks.json", to: "id_tokens#jwks"
|
get "jwks.json", to: "id_tokens#jwks"
|
||||||
|
|
||||||
|
get "user_info", to: "user_info#show"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -28,5 +28,5 @@ end
|
||||||
When /^I parse the tokens and use it obtain user info$/ do
|
When /^I parse the tokens and use it obtain user info$/ do
|
||||||
client_json = JSON.parse(last_response.body)
|
client_json = JSON.parse(last_response.body)
|
||||||
access_token = client_json["access_token"]
|
access_token = client_json["access_token"]
|
||||||
get api_v0_user_path, access_token: access_token
|
get api_openid_connect_user_info_path, access_token: access_token
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ end
|
||||||
|
|
||||||
When /^I parse the bearer tokens and use it to access user info$/ do
|
When /^I parse the bearer tokens and use it to access user info$/ do
|
||||||
access_token = current_url[/(?<=access_token=)[^&]+/]
|
access_token = current_url[/(?<=access_token=)[^&]+/]
|
||||||
get api_v0_user_path, access_token: access_token
|
get api_openid_connect_user_info_path, access_token: access_token
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should see an "([^\"]*)" error$/ do |error_message|
|
Then /^I should see an "([^\"]*)" error$/ do |error_message|
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,19 @@ end
|
||||||
|
|
||||||
When /^I use received valid bearer tokens to access user info$/ do
|
When /^I use received valid bearer tokens to access user info$/ do
|
||||||
access_token_json = JSON.parse(last_response.body)
|
access_token_json = JSON.parse(last_response.body)
|
||||||
get api_v0_user_path, access_token: access_token_json["access_token"]
|
get api_openid_connect_user_info_path, access_token: access_token_json["access_token"]
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I use invalid bearer tokens to access user info$/ do
|
When /^I use invalid bearer tokens to access user info$/ do
|
||||||
get api_v0_user_path, access_token: SecureRandom.hex(32)
|
get api_openid_connect_user_info_path, access_token: SecureRandom.hex(32)
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should receive "([^\"]*)"'s id, username, and email$/ do |username|
|
Then /^I should receive "([^\"]*)"'s id, username, and email$/ do |username|
|
||||||
user_info_json = JSON.parse(last_response.body)
|
user_info_json = JSON.parse(last_response.body)
|
||||||
user = User.find_by_username(username)
|
user = User.find_by_username(username)
|
||||||
expect(user_info_json["username"]).to have_content(user.username)
|
user_profile_url = File.join(AppConfig.environment.url, "people", user.guid).to_s
|
||||||
expect(user_info_json["language"]).to have_content(user.language)
|
expect(user_info_json["profile"]).to have_content(user_profile_url)
|
||||||
expect(user_info_json["email"]).to have_content(user.email)
|
expect(user_info_json["zoneinfo"]).to have_content(user.language)
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should receive an "([^\"]*)" error$/ do |error_message|
|
Then /^I should receive an "([^\"]*)" error$/ do |error_message|
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,10 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
context "when already authorized" do
|
context "when already authorized" do
|
||||||
let!(:auth) { Api::OpenidConnect::Authorization.find_or_create_by(o_auth_application: client, user: alice,
|
let!(:auth) {
|
||||||
redirect_uri: "http://localhost:3000/") }
|
Api::OpenidConnect::Authorization.find_or_create_by(o_auth_application: client, user: alice,
|
||||||
|
redirect_uri: "http://localhost:3000/")
|
||||||
|
}
|
||||||
|
|
||||||
context "when valid parameters are passed" do
|
context "when valid parameters are passed" do
|
||||||
before do
|
before do
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,21 @@ describe Api::V0::UsersController do
|
||||||
end
|
end
|
||||||
let(:auth_with_read) do
|
let(:auth_with_read) do
|
||||||
auth = Api::OpenidConnect::Authorization.create!(o_auth_application: client, user: alice)
|
auth = Api::OpenidConnect::Authorization.create!(o_auth_application: client, user: alice)
|
||||||
auth.scopes << [Api::OpenidConnect::Scope.find_or_create_by(name: "read")]
|
auth.scopes << [Api::OpenidConnect::Scope.find_or_create_by(name: "openid"),
|
||||||
|
Api::OpenidConnect::Scope.find_or_create_by(name: "read")]
|
||||||
auth
|
auth
|
||||||
end
|
end
|
||||||
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
||||||
|
|
||||||
describe "#show" do
|
describe "#show" do
|
||||||
before do
|
before do
|
||||||
get api_v0_user_path, access_token: access_token_with_read
|
get api_openid_connect_user_info_path, access_token: access_token_with_read
|
||||||
end
|
end
|
||||||
|
|
||||||
it "shows the info" do
|
it "shows the info" do
|
||||||
json_body = JSON.parse(response.body)
|
json_body = JSON.parse(response.body)
|
||||||
expect(json_body["username"]).to eq(alice.username)
|
expect(json_body["nickname"]).to eq(alice.name)
|
||||||
expect(json_body["email"]).to eq(alice.email)
|
expect(json_body["profile"]).to eq(File.join(AppConfig.environment.url, "people", alice.guid).to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
end
|
end
|
||||||
let(:auth_with_read) do
|
let(:auth_with_read) do
|
||||||
auth = Api::OpenidConnect::Authorization.create!(o_auth_application: client, user: alice)
|
auth = Api::OpenidConnect::Authorization.create!(o_auth_application: client, user: alice)
|
||||||
auth.scopes << [Api::OpenidConnect::Scope.find_or_create_by(name: "read")]
|
auth.scopes << [Api::OpenidConnect::Scope.find_or_create_by(name: "openid"),
|
||||||
|
Api::OpenidConnect::Scope.find_or_create_by(name: "read")]
|
||||||
auth
|
auth
|
||||||
end
|
end
|
||||||
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
||||||
|
|
@ -18,7 +19,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
|
|
||||||
context "when valid access token is provided" do
|
context "when valid access token is provided" do
|
||||||
before do
|
before do
|
||||||
get api_v0_user_path, access_token: access_token_with_read
|
get api_openid_connect_user_info_path, access_token: access_token_with_read
|
||||||
end
|
end
|
||||||
|
|
||||||
it "includes private in the cache-control header" do
|
it "includes private in the cache-control header" do
|
||||||
|
|
@ -28,7 +29,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
|
|
||||||
context "when no access token is provided" do
|
context "when no access token is provided" do
|
||||||
before do
|
before do
|
||||||
get api_v0_user_path
|
get api_openid_connect_user_info_path
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should respond with a 401 Unauthorized response" do
|
it "should respond with a 401 Unauthorized response" do
|
||||||
|
|
@ -41,7 +42,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
|
|
||||||
context "when an invalid access token is provided" do
|
context "when an invalid access token is provided" do
|
||||||
before do
|
before do
|
||||||
get api_v0_user_path, access_token: invalid_token
|
get api_openid_connect_user_info_path, access_token: invalid_token
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should respond with a 401 Unauthorized response" do
|
it "should respond with a 401 Unauthorized response" do
|
||||||
|
|
@ -60,7 +61,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
context "when authorization has been destroyed" do
|
context "when authorization has been destroyed" do
|
||||||
before do
|
before do
|
||||||
auth_with_read.destroy
|
auth_with_read.destroy
|
||||||
get api_v0_user_path, access_token: access_token_with_read
|
get api_openid_connect_user_info_path, access_token: access_token_with_read
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should respond with a 401 Unauthorized response" do
|
it "should respond with a 401 Unauthorized response" do
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue